一、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 文件时发现其中的内容是:
    JSP - 图1
    而 HttpJspBase 类直接继承于 HttpServlet 类,即 JSP 翻译出来的 Java 类间接继承于 HttpServlet 类,证明 JSP 页面是一个 Servlet 程序

    三、JSP 的语法

    1. 头部指令

    JSP 头部的 page 指令:
    JSP - 图2
    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 中的常用脚本

1. 声明脚本
格式:<%! 声明 Java 代码 %>
作用:可以给 JSP 翻译出来的 Java 类定义属性、方法、静态代码块、内部类等
特点:不会在浏览器的页面上显示出来,仅存在于翻译后的 Java 类中

代码演示:声明脚本的使用 (此 JSP 文件在 web 目录下,名为 First.jsp)

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@ page import="java.util.HashMap" %>
  3. <%@ page import="java.util.Map" %>
  4. <html>
  5. <head>
  6. <title>Title</title>
  7. </head>
  8. <body>
  9. <%--1.声明类属性--%>
  10. <%!
  11. private String name;
  12. private static Map<String, Object> map;
  13. %>
  14. <%--2.声明类方法--%>
  15. <%!
  16. public int sum() {
  17. return 12;
  18. }
  19. %>
  20. <%--3.声明静态代码块--%>
  21. <%!
  22. static {
  23. map = new HashMap<String, Object>();
  24. map.put("key1", "value1");
  25. }
  26. %>
  27. </body>
  28. </html>

对应的翻译后的 java 源文件:
JSP - 图3

2. 表达式脚本
格式:<%= 表达式 %>
作用:在浏览器的 JSP 页面上输出数据 (只有此脚本可以在浏览器的页面上输出数据)
特点:
(1) 所有的表达式脚本都会被翻译到对应的 Java 类的_jspService() 方法中,故表达式脚本可以 直接使用_jspService() 方法参数中的对象
(2) 表达式脚本都会被编译后的 Java 类中的 out.print() 方法输出到浏览器页面上
(3) 表达式脚本中的表达式不能以分号结束

代码演示:表达式脚本的使用 (此 JSP 文件在 web 目录下,名为 First.jsp)

<%=22 %> <br/>
<%="可以输出字符串" %> <br/>
<%=map %> <br/>
<%--使用_jspService方法中的对象--%>
<%=request.getParameter("username") %>

启动 Tomcat 服务器后浏览器的运行结果:
JSP - 图4

对应的翻译后的 Java 源文件 (在_jspService 方法中):
JSP - 图5

注意

  1. write 方法中的标签、转义字符自动识别为对应的
    功能,不在页面输出,执行各自代表的功能
  2. out 的两个方法也在_jspService 方法中,也都是 java 语言
  3. 只有 print、write 方法、表达式脚本中的内容才可在浏览器中显示,其余 Java 代码的 sout 在控制台输出

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

代码演示:代码脚本的使用 (此 JSP 文件在 web 目录下,名为 First.jsp)

<%--1.if语句--%>
<%
    int i = 1;
    if (i == 1) {
        System.out.println("我爱祖国!");
    } else {
        System.out.println("我很爱祖国!");
    }
%> <br/>
<%--2.for循环语句--%>
<%
    for (int j = 0 ; j < 3; j++) {
        System.out.println("第" + j + "次循环");
    }
%> <br/>
<%--3.使用_jspService方法参数中的对象--%>
<%
    String username = request.getParameter("username");
    System.out.println("username对应的值为:" + username);
%>

运行结果:
启动 Tomcat 服务器后在地址栏输入:http://localhost:8080/MyTest/First.jsp?username=Jaychou
在控制台显示:
JSP - 图6

对应的翻译后的 Java 源文件 (在_jspService 方法中):
JSP - 图7

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 页面翻译为 Java 类之后内部提供的九大对象:
(将 page 指令的 isErrorPage 属性写成 true 可以出现 exception 对象)
JSP - 图8
request:请求对象
response:响应对象
pageContext:JSP 的上下文对象
session:会话对象
application:ServletContext 对象
config:ServletConfig 对象
out:JSP 输出流对象
page:指向当前 JSP 的对象
exception:异常对象

五、JSP 四大域对象

JSP - 图9
域对象是指可以像 Map 一样存取数据的对象,四个域对象功能一样,只是对数据的存取范围不同

代码演示 1:四个域对象存取数据的范围的不同 (在 web 目录下创建 scope1.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>scope1</title>
</head>
<body>
    <h1>scope1.jsp页面</h1>
    <%
        //向四个域对象中分别保存数据
        pageContext.setAttribute("key", "pageContext");
        request.setAttribute("key", "request");
        session.setAttribute("key", "session");
        application.setAttribute("key", "application");
    %>
    <%-- <jsp:forward page=""></jsp:forward>是请求转发标签,
         page属性设置请求转发的路径 --%>
    <jsp:forward page="/scope2.jsp"></jsp:forward>
</body>

代码演示 2:在 web 目录下创建 scope2.jsp

<head>
    <title>Title</title>
</head>
<body>
    <h1>scope2.jsp页面</h1>
    <%-- JSP页面中不加任何标签直接输入的内容被write方法输出在浏览器的页面上   --%>
    pageContext域是否有值:<%=pageContext.getAttribute("key")%> <br>
    request域是否有值:<%=request.getAttribute("key")%> <br>
    session域是否有值:<%=session.getAttribute("key")%> <br>
    application域是否有值:<%=application.getAttribute("key")%> <br>
</body>

运行结果 1:
JSP - 图10

运行结果 2:
JSP - 图11

注意:若四个域对象在使用时范围都可满足要求,则使用的优先顺序是 (范围从小到大):
pageContext —> request —> session —> application

六、JSP 的 out 输出和 response.getWriter 输出的异同

  1. 相同点:response 表示响应,用于给客户端 (浏览器) 返回内容
    out 同样也是用于给客户端 (浏览器) 输出内容
  2. 不同点:
    JSP - 图12
  3. 注意:由于官方的代码中翻译后的 Java 代码底层都是使用 out 进行输出,故一般都使用 out 进行 输出,out 又分为 write 方法和 print 方法:
    (1) out.print():会将任何内容转换成字符串后调用 write 方法输出
    (2) out.write():输出字符串没有问题,但输出 int 型时会将 int 转换成 char 输出,导致输出的并非是想要的数字而是数字对应的 ASCII 码
    结论:JSP 页面的代码脚本中任何要输出在浏览器的内容均使用 out.print() 方法

    七、JSP 的常用标签

    1. 静态包含

    (1) 使用场景:
    JSP - 图13

(2) 使用方法:
<%@include file=””%>
其中 file 属性设置要包含的 JSP 页面,以 / 打头,代表http://ip:port / 工程路径 /,对应 web 目录

代码演示 1:在 web 目录下创建 body.jsp

<body>
    头部信息 <br>
    主体信息 <br>
    <%@include file="/foot.jsp"%>
</body>

代码演示 2:在 web 目录下创建 foot.jsp

<body>
    页脚信息 <br>
</body>

运行结果:
JSP - 图14
(3) 静态包含的特点:
①静态包含不会将被包含的 JSP 页面翻译成. java.class 文件
②静态包含是把被包含的页面的代码拷贝到 body.jsp 对应的 Java 文件的对应位置执行输出

2. 动态包含

(1) 使用方法:

其中 page 属性设置要包含的 JSP 页面,与静态包含一致

(2) 动态包含的特点:
①动态包含将被包含的 JSP 页面翻译成. java.class 文件
②动态包含还可以传递参数
③动态包含底层使用如下代码调用被包含的 JSP 页面执行输出:
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, “/foot.jsp”, out, false);

代码演示 1:在 web 目录下创建 body.jsp

<body>
    头部信息 <br>
    主体信息 <br>
    <jsp:include page="/foot.jsp">
        <jsp:param name="username" value="Jaychou"/>
        <jsp:param name="password" value="root"/>
    </jsp:include>
</body>

注意

  1. 设置参数的标签要写在动态包含之中
  2. 出现 Expecting “jsp:param” standard action with “name” and “value” attributes 异常,两个原因:
    ①动态包含中未设置参数但没有把 放在一行上
    ②动态包含中加了注释
    代码演示 2:在 web 目录下创建 foot.jsp
    <body>
     页脚信息 <br>
     <%=request.getParameter("username")%>
    </body>
    
    运行结果:
    JSP - 图15
    (3) 动态包含的底层原理:
    JSP - 图16