介绍
jsp(Java Server Pages)是Java的服务器页面,它的主要作用是代替Servlet程序回传HTML页面的数据,因为Servlet程序回传HTML页面数据是一件非常繁琐的事情,开发和维护成本较高
新建动态web工程08_jsp
package com.atguigu.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 PrintHtml extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通过响应的回传流回传HTML页面数据
resp.setContentType("text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("<!DOCTYPE html>\r\n");
writer.write("<html lang=\"en\">\r\n");
writer.write(" <head>\r\n");
writer.write(" <meta charset=\"UTF-8\">\r\n");
writer.write(" <title>Title</title>\r\n");
writer.write(" </head>\r\n");
writer.write(" <body>\r\n");
writer.write(" 这是HTML页面数据\r\n");
writer.write(" </body>\r\n");
writer.write("</html>\r\n");
}
}
使用jsp,在web目录下新建a.jsp文件
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/5
Time: 12:38
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>
这是HTML页面数据
</body>
</html>
jsp页面的本质
jsp页面本质上是一个Servlet程序。当第一次访问jsp页面时,tomcat会将jsp页面翻译成一个Java源文件,并将其编译为字节码文件。查看CATALINA_BASE: "C:\Users\xurui\.IntelliJIdea2017.3\system\tomcat\Tomcat_8_0_50_JavaWeb_5"
在a_jsp.java中定义的类继承HttpJspBase,而该类继承HttpServlet
其实jsp的方式也是通过输出流将页面数据回传给客户端,所以这和一开始我们创建Servlet并通过输出流回传页面数据本质上是一样的
jsp的page指令
即<%@ page contentType="text/html;charset=UTF-8" language="java" %>,它可以修改jsp页面中一些重要的属性或行为
常用属性有
language 表示jsp翻译后是什么语言文件,只支持java
contentType jsp返回的数据类型,在对应的Servlet程序中
pageEncoding jsp页面本身的字符集
import 和java文件一样,用于导包、导类
autoFlush 和下面的buffer都是给上面提到的输出流out使用,当输出流out缓冲区满了后,是否自动刷新缓冲区,默认true
buffer 设置out缓冲区大小,默认8kb
errorPage 当jsp页面运行出错,设置自动跳转的页面路径,以/开头,表示到web目录
isErrorPage 设置当前页面是否为错误信息页面,默认为false
session 设置访问当前jsp页面,是否创建HttpSession对象,默认为true
extends 设置jsp翻译出来的Java类默认继承哪个类
声明脚本(基本不用)
格式为<%! 声明的Java代码 %>,可以给jsp翻译出来的Java类定义属性、方法、静态代码块或内部类等
<% page import="java.util.Map" %>
<% page import="java.util.HashMap" %><%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/5
Time: 12:38
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>
<%-- 声明类属性 --%>
<%!
private Integer id;
private String name;
private static Map<String, Object> map;
%>
<%-- 声明静态代码块 --%>
<%!
static {
map = new HashMap<String, Object>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
}
%>
<%-- 声明类方法 --%>
<%!
public int abc() {
return 12;
}
%>
<%-- 声明内部类 --%>
<%!
public static class A {
private Integer id = 12;
private String abc = "abc";
}
%>
</body>
</html>
访问a.jsp后
表达式脚本(常用)
格式为<%=表达式%>,用来在jsp页面上输出数据,包括整型、浮点型、字符串、对象
表达式不能以;结束
<%=12 %><br>
<%=12.12 %><br>
<%="字符串" %><br>
<%=map %><br>
访问a.jsp后
表达式脚本会被翻译到_jspService()中(上面的输出语句就是在该方法中),所以可以在表达式脚本中直接使用_jspService()中的对象
<%=12 %><br>
<%=12.12 %><br>
<%="字符串" %><br>
<%=map %><br>
<%=request.getParameter("username") %>
代码脚本
格式为<% Java语句 %>,用来在jsp页面中编写想要的功能,如if判断、for循环
<%
int i = 12;
if (i == 12) {
System.out.println("TRUE");
} else {
System.out.println("FALSE");
}
%>
<%
for (int j = 0 ; j < 10 ; j++) {
System.out.print(j + " ");
}
%>
访问a.jsp后在控制台输出结果,代码脚本也被翻译到_jspService()中,也就是说能在_jspService()中写的代码也能写代码脚本中
多个代码脚本可以组成一个完整的Java语句
代码脚本和表达式脚本组合使用,在jsp页面上输出数据
<table border="1" cellpadding="0">
<%
for (int j = 0 ; j < 10 ; j++) {
%>
<tr>
<td>第<%=j + 1%>行</td>
</tr>
<%
}
%>
</table>
jsp中的三种注释
jsp中的九个内置对象
tomcat翻译jsp为Servlet源代码后,其中提供的九个内置对象
需设置isErrorPage属性为true
从上到下分别为:请求对象、响应对象、jsp的上下文对象、会话对象、异常对象、ServletContext对象、ServletConfig对象、jsp输出流对象、指向当前jsp的对象
四个域对象的演示
分别是pageContext、request、session、application,域对象是可以像Map一样存取数据的对象,这四个域对象功能一样,不同的是它们对数据的存取范围
pageContext在当前jsp页面范围内有效,request在一次请求内有效,session在一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器),application在整个web工程范围内有效(只要web工程不停止,数据都在。它在web工程启动时创建,停止时销毁)
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/6
Time: 12:34
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>
<h1>scope.jsp页面</h1>
<%
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>
</body>
</html>
在四个域对象范围内,所以它们都有值
在scope.jsp中添加请求转发到scope2.jsp中的代码
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/6
Time: 14:32
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>
<h1>scope2.jsp页面</h1>
pageContext域是否有值:<%=pageContext.getAttribute("key")%><br>
request域是否有值:<%=request.getAttribute("key")%><br>
session域是否有值:<%=session.getAttribute("key")%><br>
application域是否有值:<%=application.getAttribute("key")%><br>
</body>
</html>
由于不在scope.jsp页面中,所以pageContext没有值;由于是请求转发,所以这算一次请求,request有值;浏览器未关闭,会话一直在,session有值;服务器未停,application有值
直接请求scope2.jsp,与访问scope.jsp相比,这是两次请求,所以request没有值
关闭浏览器再打开,或打开另一浏览器,会话不在了,所以session没有值
点击重新部署,application没有值
这四个域对象使用的优先顺序是按有效范围的从小到大,即pageContext->request->session->application
out和response输出的区别
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/6
Time: 19:49
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>
<%
out.write("out输出1 <br/>");
out.write("out输出2 <br/>");
response.getWriter().write("response输出1 <br/>");
response.getWriter().write("response输出2 <br/>");
%>
</body>
</html>
response的输出在前,这是因为当jsp页面中的所有代码执行完后(out和response分别将数据写入自己的缓冲区),接着会执行两个操作:1,执行out.flush()将out缓冲区的数据追加写入到response缓冲区;2,执行response的刷新操作,把所有数据发送给客户端。所以out输出在response之后
jsp翻译后的代码使用out输出,所以一般情况下我们也使用out输出,避免打乱顺序
out的write()和print(),前者输出字符串时没有问题,但输出整型时出错;后者可以输出任意数据类型,它是将参数转换为字符串后调用write()输出
在jsp页面中,统一使用out.print()输出
常用标签之静态包含
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/6
Time: 22:43
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>
头部信息 <br>
主体信息 <br>
<%--
静态包含,file属性指定要包含的jsp页面路径,
地址的第一个/表示为http://ip:port/工程名/,映射到web目录
--%>
<%@include file="/include/footer.jsp"%>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/6
Time: 22:43
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>
脚页信息 <br>
</body>
</html>
查看jsp翻译后的Servlet程序,只有main_jsp.java,被包含的jsp没有被翻译为java文件。查看该文件内容,静态包含其实就是把被包含的jsp页面的内容在相应位置用out.write()输出
常用标签之动态包含
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/6
Time: 22:43
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>
头部信息 <br>
主体信息 <br>
<%--
动态包含,page属性指定要包含的jsp页面路径,
地址的第一个/表示为http://ip:port/工程名/,映射到web目录
--%>
<jsp:include page="/include/footer.jsp">
<jsp:param name="username" value="bbj" />
<jsp:param name="password" value="root" />
</jsp:include>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/6
Time: 22:43
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>
脚页信息 <br>
<%-- 动态包含可以传递参数 --%>
<%=request.getParameter("password")%>
</body>
</html>
和静态包含效果一样,但可以传递参数
不同的是动态包含会将包含的jsp页面翻译为java文件,且在main_jsp.java中使用下面这行代码对被包含的jsp页面进行输出,就是将main.jsp中的request、response、out对象传递给footer.jsp,所以它们使用同一个out缓冲区
常用标签之请求转发
练习:九九乘法表
<%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/7
Time: 0:45
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><%=j + "x" + i + "=" + (i*j)%></td>
<% } %>
</tr>
<% } %>
</table>
</body>
</html>
练习:遍历输出10个学生信息到表格中
package com.atguigu.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;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", phone='" + phone + '\'' +
'}';
}
}
<%@ page import="java.util.List" %>
<%@ page import="com.atguigu.pojo.Student" %>
<%@ page import="java.util.ArrayList" %><%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/7
Time: 1:45
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>
<%
List<Student> studentList = new ArrayList<Student>();
for (int i = 0 ; i < 10 ; i++) {
int t = i + 1;
studentList.add(new Student(t, "name"+t, 18+t, "phone"+t));
}
%>
<table>
<tr>
<td>编号</td>
<td>姓名</td>
<td>年龄</td>
<td>电话</td>
<td>操作</td>
</tr>
<% for (Student student : studentList) { %>
<tr>
<td><%=student.getId()%></td>
<td><%=student.getName()%></td>
<td><%=student.getAge()%></td>
<td><%=student.getPhone()%></td>
<td>删除,修改</td>
</tr>
<% } %>
</table>
</body>
</html>
请求转发的使用说明
因为Servlet程序不适合用于回传用户要查找的数据,所以这步操作往往通过请求转发交给jsp页面实现
package com.atguigu.servlet;
import com.atguigu.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;
public class SearchStudentServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 模拟从数据库中查找数据
List<Student> studentList = new ArrayList<Student>();
for (int i = 0 ; i < 10 ; i++) {
int t = i + 1;
studentList.add(new Student(t, "name"+t, 18+t, "phone"+t));
}
// 使用请求转发,就算一次请求,所以共享同一request域,使用它保存查找到的数据
req.setAttribute("stuList", studentList);
req.getRequestDispatcher("/test/showStudent.jsp").forward(req, resp);
}
}
<%@ page import="java.util.List" %>
<%@ page import="com.atguigu.pojo.Student" %>
<%@ page import="java.util.ArrayList" %><%--
Created by IntelliJ IDEA.
User: xurui
Date: 2021/10/7
Time: 1:45
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> studentList = (List<Student>) request.getAttribute("stuList");
%>
<table>
<tr>
<td>编号</td>
<td>姓名</td>
<td>年龄</td>
<td>电话</td>
<td>操作</td>
</tr>
<% for (Student student : studentList) { %>
<tr>
<td><%=student.getId()%></td>
<td><%=student.getName()%></td>
<td><%=student.getAge()%></td>
<td><%=student.getPhone()%></td>
<td>删除,修改</td>
</tr>
<% } %>
</table>
</body>
</html>
web.xml,重写部署生效
注意访问的是Servlet程序,不是jsp页面
Listener监听器
JavaWeb三大组件之一(Servlet程序、Filter过滤器、Listener监听器),Listener是javaEE的规范(即接口),它的作用是监听某种事物的变化,然后通过回调函数反馈给客户程序去做一些相应的处理
ServletContextListener监听器演示
ServletContex对象在web工程启动时创建,停止时销毁。ServletContextListener可以监听ServletContext对象的创建和销毁,它在监听到创建和销毁后会分别调用ServletContextListener监听器的方法进行反馈
使用步骤:1,编写一个ServletContextListener的实现类;2,实现其中的两个回调方法;3,在web.xml中配置监听器
package com.atguigu.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListenerImpl implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象被创建了");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext对象被销毁了");
}
}
web.xml
当重新部署和停止web工程