JSP
什么是JSP以及他有什么用
servlet程序用于接收并处理客户端的请求,并做出响应,并将响应(一般是一个Html页面)回传给客户端
- 演示一般情况下回传html页面
- a.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
这是html页面数据
</body>
</html>
- servlet程序
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HtmlServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通过响应的回传流回传html页面数据
//设置响应的字符集
resp.setContentType("text/html;charset=utf-8");
final PrintWriter writer = resp.getWriter();
writer.write("<!DOCTYPE html>");
writer.write("<html lang=\"en\">");
writer.write("<head>");
writer.write(" <meta charset=\"UTF-8\">");
writer.write(" <title>Title</title>");
writer.write("</head>");
writer.write("<body>");
writer.write("这是html页面数据");
writer.write("</body>");
writer.write("</html>");
}
}
我们需要用servlet程序给客户端回传a.html页面,可以发现我们需要将html代码的每一行都需要通过write方法写入到客户端。可以发现这样非常麻烦
而且在实际的项目中,页面的代码成千上万,这样太难写了,维护成本也太高了
-
如果我们使用jsp文件呢
-
创建a.jsp文件
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/14
Time: 22:59
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
</body>
</html>
- 这里感觉jsp的原理还不是很懂,特此标记
jsp小结
- 1.如何创建jsp页面
直接在web目录下面创建jsp文件即可
jsp页面的本质
- 我们重新启动项目
- 接下来当我们访问jsp文件的时候会发生什么呢?
- 我们打开a_jsp类
- 我们打开
HttpJspBase类的源代码
- 通过观察jsp文件的java文件的底层原码,不难发现其底层也是通过输出流把html页面回传给客户端
jsp的三种语法
(a)jsp头部的page指令
-
我们知道servlet程序可以写循环,if间接访问数据库,这些jsp都可以做到吗
-
contentType属性:表示jsp返回数据(可以是页面)类型是什么,以及其字符集
在其翻译的servlet程序中以response.setContentType()来体现 -
pageEncoding表示当前jsp文件本身的字符集(一般默认不写)
-
import属性可以像java类一样可以导包,导类
-
演示缓存区溢出的情况
-
我们有下面要输出大量内容并且不刷新缓存的jap文件,然后访问
- errorPage属性:当jsp文件出现异常,跳转导errorPage属性所保存的路径
注意:jsp文件本质上来说是servlet程序,里面的资源路径还是被服务器解析,而不是被服务器解析
- isErrorPage属性
当我们在jsp文件中将isErrorPage设置为ture,然后访问jsp文件后可以看到他对应的servlet中出现了异常对象
jsp常用脚本
1.声明脚本(本质上就是用来扩展生成的servlet程序)
- jsp中注释<%-- --%>(IDEA快捷键ctrl+shift+/)
- 敲<%!,然后回车,IDEA将会自动补全
从上面的内容我们知道jsp文件本质上是servlet程序,在被服务器解析的时候会被解析成servelt程序并生成对应的java代码和class代码。声明脚本是指用于在JSP页面中声明变量或方法的脚本。JSP声明脚本使用<%! %>标记来包含Java代码,这些代码在编译时被嵌入到Servlet类中。
2.表达式脚本(常用)
3.代码脚本
- 1.在和html页面一样jsp页面上的标签文字内容和直接由浏览器进行解析
- 2.由表达式脚本输出的内容,由out.wirit()发送给浏览器进行解析
问题:本来想使用System.out.println()来向控制台输出,但是一直报错。好像是jsp禁用了一些系统的功能。后面怎么解决这个问题还没有解决
jsp的三种注释
-
java注释一般是写在声明脚本或者代码脚本中
-
jsp注释可以注释掉Jps中的一切
jsp中九大内置对象
jsp 中的内置对象,是指 Tomcat 在翻译 jsp 页面成为 Servlet 源代码后,内部提供的九大对象,叫内置对象。
jsp四个域对象的演示
- 在九大内置对象中有4个是域对象
- 域对象:可以像map集合一样存储数据
注意:从一个jps跳转到另一个jsp是一个请求,因为Jps本质上是servlt程序
重新部署或者重启服务器,Application才会消失
-
有四个域对象,我们到底使用哪个?
我们的域对象会存储在内存中,域对象的今早释放可以减轻服务器的压力。 最小的使用范围就会在最短的时间内,在数据不需要使用的使用将他的内存释放掉。所以
我们根据自己的需求从使用从小到大进行选择 -
演示4个域对象的使用范围
-
1.我们先创建a.jsp页面,并在存储4个域的域对象,并输出域对象
-
a.jsp
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/17
Time: 16:03
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<h>这是c.jsp文件</h><br>
<%
//在jsp的4个域对象中存储值
pageContext.setAttribute("key","pageContext");
request.setAttribute("key","request");
session.setAttribute("key","session");
application.setAttribute("key","application");
%>
pageContext是否有值 <%= pageContext.getAttribute("key")%><br>
request是否有值 <%= request.getAttribute("key")%><br>
session是否有值 <%= session.getAttribute("key")%><br>
application是否有值 <%= application.getAttribute("key")%><br>
</head>
<body>
</body>
</html>
因为都在这四个域的访问范围内
-
2.在c.jsp中请求转发到d.jsp中
-
d.jsp
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/17
Time: 16:07
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
</head>
<body>
<h>d.jsp文件</h> <br>
pageContext是否有值 <%= pageContext.getAttribute("key")%><br>
request是否有值 <%= request.getAttribute("key")%><br>
session是否有值 <%= session.getAttribute("key")%><br>
application是否有值 <%= application.getAttribute("key")%><br>
</body>
</html>
我们可以发现pageContext中的值是空的了,因为已经超出了在jsp页面中的范围。因为请求转发是一次请求所以request的值还在
-
3.重新访问一下d.jsp
我们发现request的值不见了,因为又是一次请求,超出了请求的范围 -
4.浏览器重新访问
关于浏览器从新访问就已经不属于一次会话了,所以session的值就没有了 -
4.重启服务器,项目重新部署applicton就没有了
jsp中的out输出和response.getWriter输出的区别
- out.pirnt和out.write方法
- 都是输出字符串
- 发现没有任何问题
- 当我们输出整形时
- 发现我们的write方法出现了问题
- 为什么write()方法输出整形会有问题?
- 结论
JSP常用标签之静态包含
-
静态包含的使用
-
使用main.jsp来模拟一个网站的结构
main.jsp
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/17
Time: 18:06
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>一个网站</title>
</head>
<body>
头部信息<br>
主题内容<br>
<%--页脚信息用静态包含--%>
<%@include file="/include/footer.jsp"%>
</body>
</html>
- footer.jsp(main.jsp静态包含的文件,提供页脚信息)
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/17
Time: 18:09
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>页脚内容</title>
</head>
<body>
页脚信息
</body>
</html>
-
静态包含实现的底层原理
-
静态包含特点
-
静态包含文件他不会被服务器解析成servlet文件,而是将该文件的代码整体拷贝到main.jsp文件中,然后一起被翻译成servlet程序
常用标签之动态包含
- 1.动态包含可以达成静态包含一样的效果
- 换成动态包含来实现
发现一样可以实现同样的效果 - 但是动态包含的底层原理有什么不同吗?
- 动态包含特点
- 原理
对于静态包含和动态包含来说:目前绝大多数情况下只用使用静态包含就可以了
常用标签之请求转发
jsp练习题
1.九九乘法口诀表
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/17
Time: 20:17
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--输出九九乘法口诀表--%>
<%
for (int i = 1; i <=9 ; i++) {
for (int j = 1; j <= i; j++) {%>
<%=i+"*"+j+"="+(i*j)%>
<%}%>
<br>
<%
}
%>
</body>
</html>
我们发现他的输出对的不是很齐,所以我们把他添加表格
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/17
Time: 20:17
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--输出九九乘法口诀表--%>
<table>
<% for (int i = 1; i <=9 ; i++) {%>
<tr>
<% for (int j = 1; j <= i; j++) {%>
<td> <%=i+"*"+j+"="+(i*j)%></td>
<%}%>
</tr>
<% } %>
</table>
</body>
</html>
-
这样输出就对齐了
-
我们可以给table标签添加样式,这样效果更好
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/17
Time: 20:17
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style type="text/css">
table{
width: 650px;
}
</style>
</head>
<body>
<%--输出九九乘法口诀表--%>
<h1 align="center">九九乘法口诀表</h1>
<table align="center">
<% for (int i = 1; i <=9 ; i++) {%>
<tr>
<% for (int j = 1; j <= i; j++) {%>
<td> <%=i+"*"+j+"="+(i*j)%></td>
<%}%>
</tr>
<% } %>
</table>
</body>
</html>
练习2:遍历输出10个学生信息到表格中
- 先准备一个Student类
package com.pojo;
public class Student {
private Integer id;
private String name;
private Integer age;
private String phone;
public Student() {
}
public Student(Integer id, String name, Integer age, String phone) {
this.id = id;
this.name = name;
this.age = age;
this.phone = phone;
}
/**
* 获取
* @return id
*/
public Integer getId() {
return id;
}
/**
* 设置
* @param id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public Integer getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(Integer age) {
this.age = age;
}
/**
* 获取
* @return phone
*/
public String getPhone() {
return phone;
}
/**
* 设置
* @param phone
*/
public void setPhone(String phone) {
this.phone = phone;
}
public String toString() {
return "Student{id = " + id + ", name = " + name + ", age = " + age + ", phone = " + phone + "}";
}
}
- jsp文件
<%@ page import="com.pojo.Student" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/18
Time: 12:22
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
table{
border: 1px red solid;
width: 600px;
border-collapse: collapse;
}
td,th{
border: 1px red solid;
}
</style>
</head>
<body>
<%--练习2:遍历输出10个学生信息到表格中--%>
<%
//创建10个学生对象并实例化
List<Student> list = new ArrayList<Student>();
int t=5;
for (int i = 0; i <10; i++) {
t +=i;
list.add(new Student(i++,"刘涛"+t,19+t,"1234"+t));
}
%>
<table>
<tr>
<td>id</td>
<td>姓名</td>
<td>年龄</td>
<td>电话</td>
</tr>
<% for (Student student : list) {%>
<tr>
<td> <%=student.getId()%></td>
<td> <%= student.getName()%></td>
<td> <%=student.getAge()%></td>
<td> <%=student.getPhone()%></td>
</tr>
<% }%>
</table>
</body>
</html>
- 运行结果
请求转发的使用说明
**问题概述:客户端搜索特定数据,服务器处理并响应
- 前面的将对象输出到浏览器中是给这个使用请求转发做铺垫
- servlnt程序
package com.servlet;
import com.pojo.Student;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
//用于处理查询学生信息的servlet程序
public class SearchStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.接收客户端的请求参数
//2.调用service的方法进行请求处理
//3.获得返回的学生对象
//前面的2步之前演示过,这里直接将数据给出来
List<Student> list = new ArrayList<Student>();
int t=5;
for (int i = 0; i <10; i++) {
t +=i;
list.add(new Student(i++,"刘涛"+t,19+t,"1234"+t));
}
//4.将他们保存到request域中
req.setAttribute("list",list);
//5.进行请求转发
req.getRequestDispatcher("/test/showStudent.jsp").forward(req,resp);
}
}
- jsp程序
<%@ page import="com.pojo.Student" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/9/18
Time: 12:22
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
table{
border: 1px red solid;
width: 600px;
border-collapse: collapse;
}
td,th{
border: 1px red solid;
}
</style>
</head>
<body>
<%
//获取request域中的对象
List<Student> list =(List) request.getAttribute("list");
%>
<table>
<tr>
<td>id</td>
<td>姓名</td>
<td>年龄</td>
<td>电话</td>
</tr>
<% for (Student student : list) {%>
<tr>
<td> <%=student.getId()%></td>
<td> <%= student.getName()%></td>
<td> <%=student.getAge()%></td>
<td> <%=student.getPhone()%></td>
</tr>
<% }%>
</table>
</body>
</html>
什么是Listener监听器
ServletContextListener监听器
-
ServletContextListener监听器可以用于监听ServletContext对象的创建和销毁。
-
ServletContext对象在web工程被创建的时候被创建在服务器关闭的时候被销毁
监听器的细节看官方文档 -
ServletContextListener监听器使用的演示
-
监听器类
package com.listen;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
//用于监听ServletContext对象的创建和销毁
public class MyListener implements ServletContextListener {
//1、编写一个类去实现 ServletContextListener
//2、实现其两个回调方法
//3、到 web.xml 中去配置监听
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象被创建了");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象被销毁了");
}
}
- 监听器配置
我们在启动服务器后将会调用MyLister里面的初始化方法,在关闭服务器器将会调用MyListener中的销毁方法