介绍

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 {
@Override
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");
}
}

10-jsp_jsp页面

10-jsp_java_02

10-jsp_html_03

使用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>

10-jsp_ide_04

jsp页面的本质

jsp页面本质上是一个Servlet程序。当第一次访问jsp页面时,tomcat会将jsp页面翻译成一个Java源文件,并将其编译为字节码文件。查看CATALINA_BASE: "C:\Users\xurui\.IntelliJIdea2017.3\system\tomcat\Tomcat_8_0_50_JavaWeb_5"

10-jsp_java_05

在a_jsp.java中定义的类继承HttpJspBase,而该类继承HttpServlet

10-jsp_java_06

其实jsp的方式也是通过输出流将页面数据回传给客户端,所以这和一开始我们创建Servlet并通过输出流回传页面数据本质上是一样的

10-jsp_java_07

jsp的page指令

即<%@ page contentType="text/html;charset=UTF-8" language="java" %>,它可以修改jsp页面中一些重要的属性或行为

常用属性有

language 表示jsp翻译后是什么语言文件,只支持java

contentType jsp返回的数据类型,在对应的Servlet程序中

10-jsp_数据_08

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后

10-jsp_java_09

表达式脚本(常用)

格式为<%=表达式%>,用来在jsp页面上输出数据,包括整型、浮点型、字符串、对象

表达式不能以;结束

<%=12 %><br>
<%=12.12 %><br>
<%="字符串" %><br>
<%=map %><br>

10-jsp_html_10

访问a.jsp后

10-jsp_java_11

表达式脚本会被翻译到_jspService()中(上面的输出语句就是在该方法中),所以可以在表达式脚本中直接使用_jspService()中的对象

10-jsp_html_12

<%=12 %><br>
<%=12.12 %><br>
<%="字符串" %><br>
<%=map %><br>
<%=request.getParameter("username") %>

10-jsp_java_13

代码脚本

格式为<% 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()中写的代码也能写代码脚本中

10-jsp_数据_14

10-jsp_java_15

10-jsp_jsp页面_16

多个代码脚本可以组成一个完整的Java语句

10-jsp_html_17

10-jsp_ide_18

代码脚本和表达式脚本组合使用,在jsp页面上输出数据

<table border="1" cellpadding="0">
<%
for (int j = 0 ; j < 10 ; j++) {
%>
<tr>
<td><%=j + 1%></td>
</tr>
<%
}
%>
</table>

10-jsp_ide_19

jsp中的三种注释

10-jsp_数据_20

jsp中的九个内置对象

tomcat翻译jsp为Servlet源代码后,其中提供的九个内置对象

需设置isErrorPage属性为true

10-jsp_数据_21

10-jsp_ide_22

从上到下分别为:请求对象、响应对象、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>

在四个域对象范围内,所以它们都有值

10-jsp_jsp页面_23

在scope.jsp中添加请求转发到scope2.jsp中的代码

10-jsp_java_24

<%--
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有值

10-jsp_java_25

直接请求scope2.jsp,与访问scope.jsp相比,这是两次请求,所以request没有值

10-jsp_数据_26

关闭浏览器再打开,或打开另一浏览器,会话不在了,所以session没有值

10-jsp_jsp页面_27

点击重新部署,application没有值

10-jsp_html_28

这四个域对象使用的优先顺序是按有效范围的从小到大,即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之后

10-jsp_jsp页面_29

jsp翻译后的代码使用out输出,所以一般情况下我们也使用out输出,避免打乱顺序

out的write()和print(),前者输出字符串时没有问题,但输出整型时出错;后者可以输出任意数据类型,它是将参数转换为字符串后调用write()输出

10-jsp_ide_30

在jsp页面中,统一使用out.print()输出

10-jsp_java_31

常用标签之静态包含

10-jsp_数据_32

10-jsp_数据_33

<%--
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>

10-jsp_ide_34

查看jsp翻译后的Servlet程序,只有main_jsp.java,被包含的jsp没有被翻译为java文件。查看该文件内容,静态包含其实就是把被包含的jsp页面的内容在相应位置用out.write()输出

10-jsp_jsp页面_35

常用标签之动态包含

<%--
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>

和静态包含效果一样,但可以传递参数

10-jsp_java_36

不同的是动态包含会将包含的jsp页面翻译为java文件,且在main_jsp.java中使用下面这行代码对被包含的jsp页面进行输出,就是将main.jsp中的request、response、out对象传递给footer.jsp,所以它们使用同一个out缓冲区

10-jsp_数据_37

常用标签之请求转发

10-jsp_java_38

练习:九九乘法表

<%--
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-jsp_jsp页面_39

练习:遍历输出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;
}

@Override
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>

10-jsp_jsp页面_40

请求转发的使用说明

因为Servlet程序不适合用于回传用户要查找的数据,所以这步操作往往通过请求转发交给jsp页面实现

10-jsp_jsp页面_41

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 {
@Override
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,重写部署生效

10-jsp_ide_42

注意访问的是Servlet程序,不是jsp页面

10-jsp_ide_43

Listener监听器

JavaWeb三大组件之一(Servlet程序、Filter过滤器、Listener监听器),Listener是javaEE的规范(即接口),它的作用是监听某种事物的变化,然后通过回调函数反馈给客户程序去做一些相应的处理


ServletContextListener监听器演示

ServletContex对象在web工程启动时创建,停止时销毁。ServletContextListener可以监听ServletContext对象的创建和销毁,它在监听到创建和销毁后会分别调用ServletContextListener监听器的方法进行反馈

10-jsp_html_44

使用步骤:1,编写一个ServletContextListener的实现类;2,实现其中的两个回调方法;3,在web.xml中配置监听器

package com.atguigu.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListenerImpl implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象被创建了");
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext对象被销毁了");
}
}

web.xml

10-jsp_java_45

当重新部署和停止web工程

10-jsp_ide_46