摘要:本文介绍了JSP的基本概念、生命周期、语法、指令和动作,以及常用的九个隐式对象和四个域对象。
环境
Windows 10 企业版 LTSC 21H2
Java 1.8
Tomcat 8.5.50
1 概述
1.1 简介
JSP(Java Server Pages)就是运行在Java服务器中的动态页面,其本质是一个Servlet应用。
JSP是一种跨平台的动态网页技术标准,其主要构成有HTML网页代码、Java代码片段、JSP指令、JSP动作等几部分。
相比于HTML页面,JSP最直观的功能是可以在页面中使用变量,这些变量一般都是从域对象中获取,变量可以使页面动态的显示信息。
JSP更加善于处理显示页面,Servlet更擅长处理业务逻辑,两种技术各有专长,所以一般我们会将Servlet和JSP结合使用,Servlet负责业务,JSP负责显示。
1.2 本质
JSP页面本质上是一个Servlet程序,在第一次访问页面的时候,Servlet容器会将JSP页面转换为Servlet文件,然后再将Java文件编译为字节码文件。
对于index.jsp页面,在Tomcat的工作目录下能看到转换后的文件:
jsp
├── index_jsp.class
└── index_jsp.java
打开Java文件:
1 | public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase |
可以看到JSP页面生成的Servlet继承自HttpJspBase抽象类,然后HttpJspBase抽象类继承了HttpServlet抽象类。
2 生命周期
JSP生命周期就是从创建到销毁的整个过程,类似于Servlet生命周期,区别在于JSP生命周期还包括将JSP文件编译成Servlet的过程。
2.1 编译阶段
JSP页面第一次被访问时,容器会将JSP页面转换为Servlet文件,然后再编译为字节码文件。
包括三个步骤:
- 解析JSP页面。
- 将JSP页面转换为Servlet文件。
- 将Servlet文件编译为字节码文件。
2.2 初始化阶段
容器载入JSP文件后,会在执行服务前调用jspInit()方法。如果需要执行自定义的JSP初始化任务,可以重写jspInit()方法。
在JSP页面重写初始化方法:
1 | <%! |
2.3 执行阶段
容器在执行JSP页面时,会调用_jspService()方法。
2.4 销毁阶段
当容器销毁JSP页面时,会调用jspDestroy()方法。如果需要执行自定义的JSP销毁任务,可以重写jspDestroy()方法。
在JSP页面重写销毁方法:
1 | <%! |
3 语法
3.1 声明
声明中的内容会被直接写到类中,因此可以在声明中定义方法和变量。
示例:
1 | <%! |
3.2 脚本片段
脚本片断中的Java代码将被原封不动地搬移进转换后的_jspService()方法中,因此需要遵循方法的书写规范。
也可以直接使用JSP提供的隐式对象来完成Web应用程序特有的功能。
示例:
1 | <% |
3.3 表达式
表达式会被转为成String字符串,然后插入到表达式出现的位置。
示例:
1 | <%= "test" %> |
3.4 注释
注释的内容只在当前JSP页面中可见,在转换后的Servlet中以及浏览器端显示的页面中都是不可见的。
示例:
1 | <%-- 注释 --%> |
4 指令
指令用于设置JSP页面的属性,并不直接产生可见的输出,只是告诉引擎如何处理JSP页面。
语法:
1 | <%@ 指令名称 属性1="值1" 属性2="值2" ... %> |
4.1 page
用于告诉JSP引擎如何解析当前页面,同一个页面可以有多个page指令,通常位于JSP页面的顶端。
属性:
- language:设置JSP页面使用的脚本语言,默认值为java。
- import:设置页面程序代码使用的类,用
,分隔,无默认值。 - contentType:设置类型和编码方式,是服务器发给客户端的内容编码,默认值为
text/html; ISO-8859-1。 - pageEncoding:设置JSP页面的字符编码,默认值为
ISO-8859-1。 - session:设置当前页面的session内置对象是否可用,默认值为
true。 - errorPage:设置当前页面出错处理页面地址,跳转时地址栏不改变,无默认值。
- isErrorPage:表明当前页面是错误处理页面,设置当前页面的exception内置对象是否可用,默认值为
false。 - isELIgnored:设置是否忽略EL表达式,默认值为
false。 - isThreadSafe:设置当前页面是否是线程安全的,默认值为
true。 - autoFlush:设置当前页面是否自动刷新,默认值为
true。 - buffer:设置out对象的缓冲区的大小,默认值为
8KB。
4.2 include
用于包含其他JSP页面。
这种方式称为静态引入,Java虚拟机不会单独编译包含的JSP页面,而是将整个页面作为整体进行编译,最终生成一个Java文件。
属性:
- file:设置包含的JSP页面路径,可以是绝对路径或相对路径。
4.3 taglib
用于引入自定义标签库。
属性:
- url:设置标签库的名称空间。
- prefix:设置标签库的前缀,用于在JSP页面中使用标签。
5 动作
JSP动作与HTML标签不同,HTML标签由浏览器来解析,而JSP动作需要服务器来运行。
语法:
1 | <jsp:动作名称 属性1="值1" 属性2="值2" ... /> |
5.1 jsp:include
用于把另外JSP页面的输出内容插入进当前JSP页面的输出内容之中。
这种方式称为动态引入,Java虚拟机会单独编译包含的JSP页面,最终生成多个Java文件。
属性:
- page:指定被引入资源的相对路径,可以通过表达式获取。
- flush:指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
5.2 jsp:forward
用于将请求转发到其他资源。
属性:
- page:指定被转发的资源的相对路径,可以通过表达式获取。
5.3 jsp:param
用于设置请求参数。
属性:
- name:指定参数名称。
- value:指定参数值,可以通过表达式获取。
5.4 jsp:useBean
用于在指定的域范围中获取指定类型的JavaBean对象。
属性:
- id:指定JavaBean对象的名称。
- class:指定JavaBean对象的类型,必须是全限定类名。
- scope:指定JavaBean对象的域范围,默认值为page。
5.5 jsp:getProperty
用于获取JavaBean对象的属性值。
属性:
- name:指定JavaBean对象的名称,与
jsp:useBean动作的id属性相同。 - property:指定JavaBean对象的属性名称。
5.6 jsp:setProperty
用于设置JavaBean对象的属性值。
属性:
- name:指定JavaBean对象的名称,与
jsp:useBean动作的id属性相同。 - property:指定JavaBean对象的属性名称。
- value:指定JavaBean对象的属性值,可以通过表达式获取。
- param:指定使用哪个请求参数作为JavaBean对象的属性值。
指定JavaBean对象的属性值时,只能在value属性和param属性中选择一种,并且只有在新建JavaBean对象时才执行jsp:setProperty动作。
6 隐式对象
隐式对象是JSP容器为每个页面提供的Java对象,开发者可以直接使用它们而不用显式声明。隐式对象也被称为内置对象。
JSP内置的九大隐式对象:
- request:HttpServletRequest接口的实例,用于封装客户端请求信息。
- response:HttpServletResponse接口的实例,用于封装服务器响应信息。
- session:HttpSession接口的实例,用于封装用户会话信息。
- application:ServletContext接口的实例,用于封装Web应用程序的信息。
- out:JspWriter接口的实例,用于向客户端输出内容。
- pageContext:PageContext接口的实例,用于封装当前页面的信息。
- config:ServletConfig接口的实例,用于封装当前页面的配置信息。
- page:Object类型的实例,用于封装当前页面的信息。
- exception:Throwable类型的实例,用于封装当前页面的异常信息。
7 域对象
域对象可以在不同的Web资源之间共享数据。
域对象有四个:
- page域:当前页面范围的域对象,对应的是pageContext对象。
- request域:请求范围的域对象,对应的是request对象。
- session域:会话范围的域对象,对应的是session对象。
- application域:应用程序范围的域对象,对应的是application对象。
域对象都有以下三个方法:
1 | // 设置属性名和属性对象 |
条