一、JSP 的介绍与创建

  1. JSP 的全称是 Java Server Pages,即 Java 的服务器页面
  2. JSP 的主要作用是代替 Servlet 程序回传 HTML 页面的数据
  3. web 目录 (或其他) 右击 —> new —> JSP/JSPX —> 输入文件名 —> 选择 JSP file 创建

二、JSP 的本质

JSP 页面本质上是一个 Servlet 程序,第一次访问 JSP 页面时 (运行 Tomcat 服务器后在浏览器地址栏输入路径),Tomcat 服务器会将此 JSP 页面翻译成为一个 Java 源文件,并对其进行编译成为. class 字节码文件 (一个. java,一个. class),当打开. java 文件时发现其中的内容是:

7、Jsp与Listener - 图1

我们跟踪原代码发现,HttpJspBase 类。它直接地继承了 HttpServlet 类。也就是说。jsp 翻译出来的 java 类,它间接了继承了 HttpServlet 类。也就是说,翻译出来的是一个 Servlet 程序

7、Jsp与Listener - 图2

总结:通过翻译的 java 源代码我们就可以得到结果:jsp 就是 Servlet 程序。

也可以去观察翻译出来的 Servlet 程序的源代码,不难发现。其底层实现,也是通过输出流。把 html 页面数据回传给客户端。

三、JSP 的语法

1、头部指令

JSP 头部的 page 指令:

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>

JSP 头部的 page 指令可以修改 JSP 页面中的一些重要属性或行为
(以下属性均写在 page 指令中,默认 page 指令中没有出现的属性都采用默认值):

  • contentType 属性:表示 JSP 返回的数据类型是什么,即 response.setContentType() 的参数值
  • language 属性:表示 JSP 翻译之后是什么语言文件 (目前只支持 Java)
  • pageEncoding 属性:表示当前 JSP 文件本身的字符集 (可在 IDEA 右下角看到)
  • import 属性:表示导包 (导类),与 Java 一致
  • autoFlush 属性:设置当 out 输出流缓冲区满了之后是否自动刷新缓冲区,默认值是 true
  • buffer 属性:设置 out 缓冲区的大小,默认是 8kb
    注意:out 缓冲区满了之后不能自动刷新的话会报错
  • errorPage 属性:设置当 JSP 页面运行出错时自动跳转到的页面 (错误信息页面) 的路径,这个 路径一般都是以斜杠打头,表示请求的地址是http://ip:port / 工程路径 /,对应代码 web 目录
  • isErrorPage 属性:设置当前 JSP 页面是否是错误信息页面,默认是 false,如果是 true 可以 获取错误信
  • session 属性:设置访问当前 JSP 页面时是否会创建 HttpSession 对象,默认值是 true
  • extends 属性:设置 JSP 页面翻译出来的 Java 类默认继承谁

注意:以上默认值除非有特殊需要,否则不建议修改

2、JSP 中的常用脚本(重要)

2.1、声明脚本

格式:<%! 声明 Java 代码 %>

作用:可以给 JSP 翻译出来的 Java 类定义属性、方法、静态代码块、内部类等

特点:不会在浏览器的页面上显示出来,仅存在于翻译后的 Java 类中

1、声明类属性

2、声明 static 静态代码块

3、声明类方法

4、声明内部类

  1. <%@ page import="java.util.Map" %>
  2. <%@ page import="java.util.HashMap" %><%--
  3. Created by IntelliJ IDEA.
  4. User: DELL
  5. Date: 2021/11/12
  6. Time: 22:04
  7. To change this template use File | Settings | File Templates.
  8. --%>
  9. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  10. <html>
  11. <head>
  12. <title>Title</title>
  13. </head>
  14. <body>
  15. <%--1、声明类属性--%>
  16. <%!
  17. private Integer id;
  18. private String name;
  19. private static Map<String,Object> map;
  20. %>
  21. <%--2、声明 static 静态代码块--%>
  22. <%!
  23. static {
  24. map = new HashMap<String,Object>();
  25. map.put("key1", "value1");
  26. map.put("key2", "value2");
  27. map.put("key3", "value3");
  28. }
  29. %>
  30. <%--3、声明类方法--%>
  31. <%!
  32. public int abc(){
  33. return 12;
  34. }
  35. %>
  36. <%--4、声明内部类--%>
  37. <%!
  38. public static class A {
  39. private Integer id = 12;
  40. private String abc = "abc";
  41. }
  42. %>
  43. </body>
  44. </html>

声明脚本代码翻译对照:

7、Jsp与Listener - 图3

2.2、表达式脚本

格式:<%= 表达式 %>

作用:在浏览器的 JSP 页面上输出数据 (只有此脚本可以在浏览器的页面上输出数据)

特点:

  1. 所有的表达式脚本都会被翻译到对应的 Java 类的_ jspService() 方法中,故表达式脚本可以 直接使用_jspService() 方法参数中的对象
  2. 表达式脚本都会被编译后的 Java 类中的 out.print() 方法输出到浏览器页面上
  3. 表达式脚本中的表达式不能以分号结束
  1. <%=12 %> <br>
  2. <%=12.12 %> <br>
  3. <%="我是字符串" %> <br>
  4. <%=map%> <br>
  5. <%=request.getParameter("username")%>

7、Jsp与Listener - 图4

2.3、代码脚本

格式:<% Java 语句 %>

作用:在 JSP 页面中可以根据需求,编写需要的 Java 代码

特点:

  1. 代码脚本翻译后都在_jspService 方法中,故代码脚本可以直接使用此方法参数中的对象
  2. 可以由多个代码脚本块组合完成一个完整的 Java 语句
  3. 代码脚本还可以和表达式脚本一起组合使用,在 JSP 页面上输出数据

练习:

  1. 代码脚本——if 语句
  2. 代码脚本——for 循环语句
  3. 翻译后 java 文件中_jspService 方法内的代码都可以写
  1. <%--练习:--%>
  2. <%--1.代码脚本----if 语句--%>
  3. <%
  4. int i = 13 ;
  5. if (i == 12) {
  6. %>
  7. <h1>国哥好帅</h1>
  8. <%
  9. } else {
  10. %>
  11. <h1>国哥又骗人了!</h1>
  12. <%
  13. }
  14. %>
  15. <br>
  16. <%--2.代码脚本----for 循环语句--%>
  17. <table border="1" cellspacing="0">
  18. <%
  19. for (int j = 0; j < 10; j++) {
  20. %>
  21. <tr>
  22. <td><%=j + 1%>行</td>
  23. </tr>
  24. <%
  25. }
  26. %>
  27. </table>
  28. <%--3.翻译后 java 文件中_jspService 方法内的代码都可以写--%>
  29. <%
  30. String username = request.getParameter("username");
  31. System.out.println("用户名的请求参数值是:" + username);
  32. %>

7、Jsp与Listener - 图5

3、JSP 三种注释

  1. HTML 注释:<!--HTML 注释 -->
    HTML 注释会被翻译到 JSP 文件对应的 Java 类的_jspService 方法中,以 out.write() 输出到客户端,
    write 方法会自动识别标签,执行标签对应的功能,不会在浏览器的页面上输出注释
  2. Java 注释:(1) // 单行注释 (2) /* 多行注释 */
    Java 注释要写在声明脚本和代码脚本中才被认为是 Java 注释,会被翻译到 JSP 文件对应的 Java 类的_jspService 方法中,在对应的 Java 类中也是注释
  3. JSP 注释:<%- - 这是 JSP 注释 - -%>
    JSP 注释中的内容不会在 JSP 文件翻译后的 Java 类中出现,即注释中的内容没有任何功能

四、JSP 九大内置对象

jsp 中的内置对象,是指 Tomcat 在翻译 jsp 页面成为 Servlet 源代码后,内部提供的九大对象,叫内置对象。

7、Jsp与Listener - 图6

request:请求对象
response:响应对象
pageContext:JSP 的上下文对象
session:会话对象
application:ServletContext 对象
config:ServletConfig 对象
out:JSP 输出流对象
page:指向当前 JSP 的对象
exception:异常对象

五、JSP 四大域对象

域对象 作用范围
pageContext (PageContextImpl 类) 当前 jsp 页面范围内有效
request (HttpServletRequest 类) 一次请求内有效
session (HttpSession 类) 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器)
application (ServletContext 类) 整个 web 工程范围内都有效(只要 web 工程不停止,数据都在)

域对象是可以像 Map 一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存取范围。

虽然四个域对象都可以存取数据。在使用上它们是有优先顺序的。

四个域在使用的时候,优先顺序分别是,他们从小到大的范围的顺序。

pageContext ==>>> request ==>>> session ==>>> application

scope.jsp

  1. <body>
  2. <h1>scope.jsp 页面</h1>
  3. <%
  4. // 往四个域中都分别保存了数据
  5. pageContext.setAttribute("key", "pageContext");
  6. request.setAttribute("key", "request");
  7. session.setAttribute("key", "session");
  8. application.setAttribute("key", "application");
  9. %>
  10. pageContext 域是否有值:<%=pageContext.getAttribute("key")%> <br>
  11. request 域是否有值:<%=request.getAttribute("key")%> <br>
  12. session 域是否有值:<%=session.getAttribute("key")%> <br>
  13. application 域是否有值:<%=application.getAttribute("key")%> <br>
  14. <%
  15. request.getRequestDispatcher("/scope2.jsp").forward(request,response);
  16. %>
  17. </body>

scope2.jsp

  1. <body>
  2. <h1>scope2.jsp 页面</h1>
  3. pageContext 域是否有值:<%=pageContext.getAttribute("key")%> <br>
  4. request 域是否有值:<%=request.getAttribute("key")%> <br>
  5. session 域是否有值:<%=session.getAttribute("key")%> <br>
  6. application 域是否有值:<%=application.getAttribute("key")%> <br>
  7. </body>

运行结果 1:
7、Jsp与Listener - 图7

运行结果 2:
7、Jsp与Listener - 图8

六、jsp 中的out输出和response.getWriter输出的区别

相同点:

  1. response 中表示响应,我们经常用于设置返回给客户端的内容(输出)
  2. out 也是给用户做输出使用的。

不同点:

7、Jsp与Listener - 图9

注意:由于官方的代码中翻译后的 Java 代码底层都是使用 out 进行输出,故一般都使用 out 进行输出

out 又分为 write 方法和 print 方法:

  1. out.print():会将任何内容转换成字符串后调用 write 方法输出
  2. out.write():输出字符串没有问题,但输出 int 型时会将 int 转换成 char 输出,导致输出的并非是想要的数字而是数字对应的 ASCII 码

结论:JSP 页面的代码脚本中任何要输出在浏览器的内容均使用 out.print() 方法

七、jsp 的常用标签

1、jsp 静态包含

使用场景:

7、Jsp与Listener - 图10

web文件夹下有一个include文件夹,在此文件夹下有footer.jsp以及main.jsp

main.jsp

  1. <%--
  2. Created by IntelliJ IDEA.
  3. User: Administrator
  4. Date: 2020/2/23
  5. Time: 22:04
  6. To change this template use File | Settings | File Templates.
  7. --%>
  8. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  9. <html>
  10. <head>
  11. <title>Title</title>
  12. </head>
  13. <body>
  14. 头部信息 <br>
  15. 主体内容 <br>
  16. <%--
  17. <%@ include file=""%> 就是静态包含
  18. file 属性指定你要包含的jsp页面的路径
  19. 地址中第一个斜杠 / 表示为http://ip:port/工程路径/ 映射到代码的web目录
  20. 静态包含的特点:
  21. 1、静态包含不会翻译被包含的jsp页面。
  22. 2、静态包含其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出。
  23. <%@ include file="/include/footer.jsp"%>--%>
  24. <%--
  25. <jsp:include page=""></jsp:include> 这是动态包含
  26. page 属性是指定你要包含的jsp页面的路径
  27. 动态包含也可以像静态包含一样。把被包含的内容执行输出到包含位置
  28. 动态包含的特点:
  29. 1、动态包含会把包含的jsp页面也翻译成为java代码
  30. 2、动态包含底层代码使用如下代码去调用被包含的jsp页面执行输出。
  31. JspRuntimeLibrary.include(request, response, "/include/footer.jsp", out, false);
  32. 3、动态包含,还可以传递参数
  33. --%>
  34. <jsp:include page="/include/footer.jsp">
  35. <jsp:param name="username" value="bbj"/>
  36. <jsp:param name="password" value="root"/>
  37. </jsp:include>
  38. </body>
  39. </html>

footer.jsp

  1. <%--
  2. Created by IntelliJ IDEA.
  3. User: Administrator
  4. Date: 2020/2/23
  5. Time: 22:05
  6. To change this template use File | Settings | File Templates.
  7. --%>
  8. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  9. <html>
  10. <head>
  11. <title>Title</title>
  12. </head>
  13. <body>
  14. 脚页信息 <br>
  15. 改二下 <%=request.getParameter("password")%>
  16. </body>
  17. </html>

2、jsp的动态包含

动态包含的底层原理:

7、Jsp与Listener - 图11

3、jsp 标签-转发

  1. <%--
  2. <jsp:forward page=""></jsp:forward> 是请求转发标签,它的功能就是请求转发page 属性设置请求转发的路径
  3. --%>
  4. <jsp:forward page="/scope2.jsp"></jsp:forward>

八、jsp练习题

1、在 jsp 页面中输出九九乘法口诀表

  1. <%--
  2. Created by IntelliJ IDEA.
  3. User: DELL
  4. Date: 2021/11/12
  5. Time: 23:42
  6. To change this template use File | Settings | File Templates.
  7. --%>
  8. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  9. <html>
  10. <head>
  11. <title>Title</title>
  12. <style type="text/css">
  13. table{
  14. width: 650px;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <%-- 练习一:在jsp页面中输出九九乘法口诀表 --%>
  20. <h1 align="center">九九乘法口诀表</h1>
  21. <table align="center">
  22. <% for (int i = 1; i <= 9; i++) { %>
  23. <tr>
  24. <% for (int j = 1; j <= i ; j++) { %>
  25. <td><%=j + "x" + i + "=" + (i*j)%></td>
  26. <% } %>
  27. </tr>
  28. <% } %>
  29. </table>
  30. </body>
  31. </html>

7、Jsp与Listener - 图12

2、jsp 输出一个表格,里面有 10 个学生信息

7、Jsp与Listener - 图13

Student 类:

  1. public class Student {
  2. private Integer id;
  3. private String name;
  4. private Integer age;
  5. private String phone;

SearchStudentServlet 程序:

  1. public class SearchStudentServlet extends HttpServlet {
  2. @Override
  3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  4. // 获取请求的参数
  5. // 发 sql 语句查询学生的信息
  6. // 使用 for 循环生成查询到的数据做模拟
  7. List<Student> studentList = new ArrayList<Student>();
  8. for (int i = 0; i < 10; i++) {
  9. int t = i + 1;
  10. studentList.add(new Student(t,"name"+t, 18+t,"phone"+t));
  11. }
  12. // 保存查询到的结果(学生信息)到 request 域中
  13. req.setAttribute("stuList", studentList);
  14. // 请求转发到 showStudent.jsp 页面
  15. req.getRequestDispatcher("/test/showStudent.jsp").forward(req,resp);
  16. }
  17. }

showStudent.jsp 页面

  1. <%@ page import="java.util.List" %>
  2. <%@ page import="com.atguigu.pojo.Student" %>
  3. <%@ page import="java.util.ArrayList" %>
  4. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  5. <html>
  6. <head>
  7. <title>Title</title>
  8. <style>
  9. table{
  10. border: 1px blue solid;
  11. width: 600px;
  12. border-collapse: collapse;
  13. }
  14. td,th{
  15. border: 1px blue solid;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <%--练习二:jsp 输出一个表格,里面有 10 个学生信息。--%>
  21. <%
  22. List<Student> studentList = (List<Student>) request.getAttribute("stuList");
  23. %>
  24. <table>
  25. <tr>
  26. <td>编号</td>
  27. <td>姓名</td>
  28. <td>年龄</td>
  29. <td>电话</td>
  30. <td>操作</td>
  31. </tr>
  32. <% for (Student student : studentList) { %>
  33. <tr>
  34. <td><%=student.getId()%></td>
  35. <td><%=student.getName()%></td>
  36. <td><%=student.getAge()%></td>
  37. <td><%=student.getPhone()%></td>
  38. <td>删除、修改</td>
  39. </tr>
  40. <% } %>
  41. </table>
  42. </body>
  43. </html>

九、Listener 监听器

1、Listener 监听器的介绍

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

2、ServletContextListener 监听器

ServletContextListener 监听器可以监听 ServletContext 对象的创建和销毁 (web 工程启动时创建,停止时销毁),监听到创建和销毁之后都会调用 ServletContextListener 监听器的方法进行反馈:

  1. public interface ServletContextListener extends EventListener {
  2. //在ServletContext对象创建之后调用
  3. public void contextInitialized(ServletContextEvent sce);
  4. //在ServletContext对象销毁之后调用
  5. public void contextDestroyed(ServletContextEvent sce);
  6. }

3、ServletContextListener 监听器的使用步骤

  1. 编写一个类实现 ServletContextListener 接口
  2. 重写两个方法
  3. 在 web.xml 文件中配置监听器

代码演示 1:创建一个类

  1. public class ListenerTest implements ServletContextListener {
  2. @Override
  3. public void contextInitialized(ServletContextEvent servletContextEvent) {
  4. System.out.println("ServletContext对象创建");
  5. }
  6. @Override
  7. public void contextDestroyed(ServletContextEvent servletContextEvent) {
  8. System.out.println("ServletContext对象销毁");
  9. }
  10. }

代码演示 2:在 web.xml 中配置

  1. <listener>
  2. <!-- <listener-class>标签中写上述程序的全类名 -->
  3. <listener-class>com.qizegao.servlet.ListenerTest</listener-class>
  4. </listener>

运行结果:
Tomcat 服务器启动之后控制台输出 ServletContext 对象创建
Tomcat 服务器停止之后控制台输出 ServletContext 对象销毁

注意

  1. 查看翻译后的 Java 源文件的方法:启动 Tomcat 服务器访问到 JSP 页面之后在控制台输出的信息的前端找到 Using CATALINA_BASE 中的路径,在硬盘中打开此目录,点击 work —> Catalina —> localhost,找到对应的工程文件夹寻找即可
  2. 访问 JSP 页面其实是在执行对应的翻译后的 Java 代码的_ jspService 方法:翻译后的 Java 类中没有 service 方法,而是重写了父类的_jspService 方法,这个方法会被父类的 service 方法调用