JavaWeb之Jsp技术
JSP技术
JSP(Java Server Page)是web开发中一个重要组成部分。可以接收客户端的请求,并对请求作出响应,在MVC开发模式中,通常用做展示层。
JSP组成
指令
以<%@开始%>结束的就是指令。在JSP中常用的指令有三个page指令、taglib指令、import指令
page指令
属性 | 属性值 |
---|---|
language | 开发JSP所使用的语言 |
contentType | 设置JSP向客户端浏览器响应的内容以及字符编码 |
pageEncoding | JSP页面的编码格式 |
isErrorPage | 设置该页面是否是异常信息页面,当值为true时,即可在页面中使用exception内置对象 |
errorPage | 用于指定错误页面,当页面中发生异常时则web容器自动跳转到该属性指定的页面 |
buffer | 设置out对象缓冲区大小,默认8kb |
taglib指令
taglib指令允许页面使用JSTL和用户定制的标签。taglib指令的语法如下:
1 | <%@ taglib uri="" prefix="" %> |
注释
注释以“<%–”以“–%>”结束,中间则是注释的内容,在JSP中注释有两种,一种是JSP注释,一种是HTML注释,其中JSP注释不会响应的浏览器,但是HTML注释会响应到客户端浏览器。
1 | <%--这是JSP注释--%> |
脚本
以<%开始,以%>结束,中间则是我们要书写的Java代码或者业务逻辑。
1 | //Java代码都可以编写在<% %>中 |
声明
以“<%!”开始,以“%>”结束,中间则可以定义方法、类等内容
1 | <%! |
表达式
<%=%>则是向页面中输出变量,等价于out对象的write()方法。
1 | <% |
模板
模板其实就是在JSP中的HTML
动作元素
动作元素为请求处理阶段提供信息。动作元素遵循XML元素的语法,有一个包含元素名的开始标签,可以有属性、可选的内容、与开始标签匹配的结束标签。动作元素也可以是一个空标签,可以有属性。与XML和XHTML一样,JSP的标签也是区分大小写的。但是在现行软件开发过程中,动作元素几乎不使用。
JSP 2.0规范中定义了20个标准的动作元素:
- <jsp:useBean>、<jsp:setProperty>和<jsp:getProperty>:这三个动作元素用于访问JavaBean
- <jsp:param>:这个动作元素被用来以“名-值对”的形式为其他标签提供附加信息。
- <jsp:include>:这个动作元素用于在当前页面中包含静态和动态的资源,一旦被包含的页面执行完毕,请求处理将在调用页面中继续进行。
- <jsp:forward>:这个动作允许在运行时将当前的请求转发给一个静态的资源、JSP页面或者Servlet,请求被转向到的资源必须位于同JSP发送请求相同的上下文环境中。
- <jsp:plugin>、<jsp:params>和<jsp:fallback>:<jsp:plugin>动作用于产生与客户端浏览器相关的HTML标签(<OBJECT>或<EMBED>),从而导致在需要时下载Java插件(Plug-in)软件,并在插件中执行指定的JavaBean。
- <jsp:element>:这个动作用于动态定义一个XML元素的标签。在<jsp:element>中,可以包含<jsp:attribute>和<jsp:body>。
- <jsp:attribute>:<jsp:attribute>动作主要有两个用途:一是用于在XML元素的内容中定义一个动作属性的值。二是在<jsp:element>动作中使用,指定输出元素的属性。
- <jsp:body>:这个动作用于定义元素的内容
- <jsp:text>:这个动作用于封装模板数据,它可以在模板数据允许出现的任何地方使用。<jsp:text>元素的作用和在JSP页面中直接书写模板数据一样。
- <jsp:output>:<jsp:output>动作只能在JSP文档和以XML语法编写的标签文件中使用,主要用于输出XML声明和文档类型声明
- <jsp:invoke>和<jsp:doBody>:<js:invoke>和<jsp:doBody>动作元素只能在标签文件中使用
JSP生命周期
JSP容器管理JSP页面生命周期的两个阶段:转换阶段(translation phase)和执行阶段(execution phase)。当有一个对JSP页面的客户请求到来时,JSP容器将JSP页面转换为Servlet源文件,然后编译Servlet源文件生成字节码文件,这一阶段是转换阶段。接下来,加载转换后的Servlet类,实例化一个对象处理客户端的请求,在请求处理完成后,响应对象被JSP容器接收,容器将HTML格式的响应信息发送到客户端,这一阶段是执行阶段。
当第一次加载JSP页面时,因为要将JSP文件转换为Servlet类,所以响应速度较慢。当再次请求时,JSP容器就会直接执行第一次请求时产生的Servlet,而不会再重新转换JSP文件,所以其执行速度和原始的Servlet执行速度几乎相同。在JSP执行期间,JSP容器会检查JSP文件,看是否有更新或修改。如果有更新或修改,JSP容器会再次编译JSP或Servlet;如果没有更新或修改,就直接执行前面产生的Servlet,这也是JSP相对于Servlet的好处之一。
JSP内置对象
JSP内置对象是指在JSP中不需要实例化即可直接使用的对象。
内置对象 | 描述 |
---|---|
application | ServletContext的实例 |
config | ServletConfig的实例 |
exception | 获取出现异常时的信息 |
out | jsp的输出流对象 |
page | 指向当前jsp的对象 |
pageContext | jsp的上下文路径 |
request | HttpServletRequest的实例,请求对象 |
response | HttpServletResponse的实例,响应对象 |
session | HttpSession的实例,会话 |
application
JSP application 对象是 javax.servlet.ServletContext 类的实例,这有助于查找有关 Servlet 引擎和 Servlet 环境的信息。它的生命周期从服务器启动到关闭。在此期间,对象将一直存在。这样,在用户的前后连接或不同用户之间的连接中,可以对此对象的同一属性进行操作。在任何地方 对此对象属性的操作,都会影响到其他用户的访问。
config
config 对象是 javax.servlet.ServletConfig 类的实例,表示 Servlet 的配置信息。
当一个 Servlet 初始化时,容器把某些信息通过此对象传递给这个 Servlet,这些信息包括 Servlet 初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个 ServletContext 对象),config 对象的应用范围是本页。
exception
该内置对象的作用主要是为了获取程序运行过程中的发生异常的信息。并且只有当JSP中page指令设置isErrorPage=”true”时,才可以使用该对象,并且表明该页面是异常处理页面,JSP中可以设置page指令errorPage属性的值来指定异常信息页面,也就是说当指定了异常信息页面后,如果JSP中发生了异常,则跳转到指定的异常信息页面
异常的处理有以下两种方式:
方式一:
- 编写异常页面,并且设置page执行的属性isErrorPage=”true”
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> |
- 为页面指定异常页面
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" errorPage="error.jsp"%> |
方式二:
web.xml中配置全局异常信息:
1 |
|
以上两种方式都可以处理在web开发中发生异常的情形,区别在于,方式一只能处理JSP中发生异常的情况,如果Servlet中发生异常则不会自动跳转到错误页面,方式二则是全局异常处理的方式,不管是JSP还是Servlet中发生异常,只有符合配置条件,则都会跳转到错误页面,并且JSP中无需指定errorPage.
out
out 对象是一个输出流,用来向客户端输出数据,可以是各种数据类型的内容,同时,它还可以管理应用服务器上的输出缓冲区,缓冲区的默认值是 8KB,可以通过页面指令 page 来改变默认大小。
out 对象是一个继承自抽象类 javax.servlet.jsp.JspWriter 的实例,在实际应用中,out 对象会通过 JSP容器变换为 java.io.PrintWriter 类的对象。
在使用 out 对象输出数据时,可以对数据缓冲区进行操作,及时清除缓冲区中的残余数据,为其他的输出让出缓冲空间。数据输出完毕后要及时关闭输出流。
方法 | 描述 |
---|---|
public abstract void clear() throws java.io.IOException | 清除缓冲区中的内容。如果缓冲区已经被刷新,clear()方法将抛出IOException异常。 |
public abstract void clearBuffer() throws java.io.IOException | 清除缓冲区中的当前内容。这个方法和clear()方法的区别是,如果缓冲区已经被刷新,这个方法不会抛出IOException异常。 |
public abstract void close() throws java.io.IOException | 刷新缓冲区,关闭输出流。注意,我们在编写JSP页面时,不需要显式地去调用这个方法,因为在JSP容器所生成的代码中会自动包含对close()方法的调用。 |
public abstract void flush() throws java.io.IOException | 刷新缓冲区。 |
public int getBufferSize() | 获得out对象使用的缓冲区的大小。 |
public boolean isAutoFlush() | 判断out对象是否是自动刷新。 |
out对象针对不同的数据类型,提供了多个重载的print()和println()方法,用于输出数据。要注意的是,虽然println()方法会输出一个换行,但是客户端的浏览器在显示页面时会忽略输出的换行。
page
page对象是当前页面转换后的Servlet类的实例。从转换后的Servlet类的代码中,可以看到这种关系。也可以把对象理解为this。
pageContext
获取页面上下文的pageContext对象,是一个比较特殊的对象,通过它可以获取JSP页面的request、response、session、out、exception等对象。pageContext对象的创建和初始化都是由容器来完成的,JSP页面中可以直接使用pageContext对象。
- public abstract javax.servlet.ServletRequest getRequest()
- public abstract javax.servlet.ServletResponse getResponse()
- public abstract javax.servlet.http.HttpSession getSession()
- public abstract javax.servlet.ServletContext getServletContext()
- public abstract JspWriter getOut()
- public abstract javax.servlet.ServletConfig getServletConfig()
- public abstract java.lang.Object getPage()
- public abstract java.lang.Exception getException()
在pageContext对象中,可以使用下面两个方法来保存和获取属性。
- public abstract void setAttribute(java.lang.String name,java.lang.Object value)
- public abstract java.lang.Object getAttribute(java.lang.String name)
删除指定范围内名字为name的属性。
- public abstract void removeAttribute(java.lang.String name)
在pageContext对象中保存的属性,只能在当前页面中去获取,也就是说,在pageContext中保存的数据库相当于保存在了page中。
request
客户端可通过 HTML 表单或在网页地址后面提供参数的方法提交数据,然后通过 request 对象的相关方法来获取这些数据。request 对象封装了客户端的请求信息,包括用户提交的信息以及客户端的一些信息,服务端通过 request 对象可以了解到客户端的需求,然后做出响应。
request 对象是 HttpServletRequest(接口)的实例。请求信息的内容包括请求的标题头(Header)信息(如浏览器的版本信息语言和编码方式等),请求的方式(如 HTTP 的 GET 方法、POST 方法等),请求的参数名称、参数值和客户端的主机名称等。
response
response对象和 request 对象相对应,用于响应客户请求,向客户端输出信息。response 是 HttpServletResponse 的实例,封装了 JSP产生的响应客户端请求的有关信息,如回应的 Header,回应本体(HTML 的内容)以及服务器端的状态码等信息,提供给客户端。请求的信 息可以是各种数据类型的,甚至是文件。
session
客户与服务器之间的通信是通过 HTTP 协议完成的。HTTP 是一种无状态的协议,当客户向服务器发出请求,服务器接收请求并返回响应后,该连接就被关闭了。此时,服务器端不保留连接的有关信息,要想记住客户的连接信息,可以使用 JSP提供的 session 对象。
用户登录网站时,系统将为其生成一个独一无二的 session 对象,用以记录该用户的个人信息。一旦用户退出网站,那么,所对应的 session 对象将被注销。session 对象可以绑定若干个用户信息或者 JSP 对象,不同的 session 对象的同名变量是不会相互干扰的。
当用户首次访问服务器上的一个 JSP 页面时,JSP 引擎便产生一个 session 对象,同时分配一个 String 类型的 ID 号,JSP 引擎同时将这个 ID 号发送到客户端,存放在 Cookie 中,这样,session 对象和客户端之间就建立了一一对应的关系。
当用户再次访问该服务器的其他页面时,不再分配给用户新的 session 对象,直到用户关闭浏览器,或者在一定时间(系统默认在 30 分钟内,但可在编写程序时,修改这个时间限定值或者显式地结束一个会话)客户端不向服务器发出应答请求,服务器端就会取消该用户的 session 对象,与用户的会话对应关系消失。当用户重新打开浏览器,再次连接到该服务器时,服务器为该用户再创建一个新的 session 对象。
关于Session的内容,将在会话跟踪中详细讲解。
JSP作用域
在JSP页面中的对象,包括用户创建的对象(例如,JavaBean对象)和JSP的隐含对象,都有一个范围属性。范围定义了在什么时间内,在哪一个JSP页面中可以访问这些对象。在JSP中,有4种范围,如下所示。
- page:具有page范围的对象被绑定到javax.servlet.jsp.PageContext对象中。在这个范围内的对象,只能在创建对象的页面中访问。可以调用pageContext这个隐含对象的getAttribute()方法来访问具有这种范围类型的对象(pageContext对象还提供了访问其他范围对象的getAttribute方法),可以调用pageContext对象的setAttribute()方法将对象保存到page范围中,pageContext对象本身也属于page范围。当Servlet类的_jspService()方法执行完毕,属于page范围的对象的引用将被丢弃。page范围内的对象,在客户端每次请求JSP页面时创建,在页面向客户端发送回响应或请求被转发(forward)到其他的资源后被删除。
- request:具有request范围的对象被绑定到javax.servlet.http.HttpServletRequest对象中,可以调用request这个隐含对象的getAttribute()方法来访问具有这种范围类型的对象,可以调用request对象的setAttribute()方法将对象保存到request范围中。在调用forward()方法转向的页面或者调用include()方法包含的页面中,都可以访问这个范围内的对象。要注意的是,因为请求对象对于每一个客户请求都是不同的,所以对于每一个新的请求,都要重新创建和删除这个范围内的对象。
- session:具有session范围的对象被绑定到javax.servlet.http.HttpSession对象中,可以调用session这个隐含对象的getAttribute()方法来访问具有这种范围类型的对象,可以调用session对象的setAttribute()方法将对象保存到session范围中。JSP容器为每一次会话,创建一个HttpSession对象,在会话期间,可以访问session范围内的对象。
- 具有application范围的对象被绑定到javax.servlet.ServletContext中,可以调用application这个隐含对象的getAttribute()方法来访问具有这种范围类型的对象,可以调用application对象的setAttribute()方法将对象保存到application范围中。在Web应用程序运行期间,所有的页面都可以访问在这个范围内的对象。
这4个作用域的范围从大到小,依次如下:
名称 | 作用域 |
---|---|
application | 在所有应用程序中有效 |
session | 在当前会话中有效 |
request | 在当前请求中有效 |
page | 在当前页面有效 |
请求转发和重定向
请求转发和重定向的作用都是用于跳转web资源,但是二者是存在区别的。
下面的两个示例分别演示的用请求转发和重定向跳转资源:
1 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
在请求转发中,客户端浏览器请求JSP或者Servlet,当JSP或者Servlet接收到请求后,将请求转发给其他的JSP或者Servlet,最终由转发后的资源对客户端进行响应。在整个过程中只有1次请求。
在重定向中,客户端浏览器请求JSP或者Servlet,当JSP或者·Servlet接收到请求后会先向客户端响应302状态码及重定向地址,当客户端浏览器接收到该302响应码以后,重新发起一次请求,请求的地址就是服务端伴随这302响应的地址,因此在整个过程中发生了2次请求。
接下来我们学习两者的区别:
- 请求转发时浏览器地址栏不会发生变化,重定向时浏览器地址会发生
- 请求转发是服务器内部行为,而重定向则是客户端行为,当客户端接收到302响应状态码后,会发出新的请求,去请求目标页面。因此请求转发的效率要高于重定向。
- 请求转发只能跳转当前应用内的资源,重定向则可以跳转外部资源。
- 请求转发过程是1次请求,而重定向过程中有2次请求, 因此在请求转发的过程中可以使用request对象传递数据,重定向则不行。
EL表达式
EL的语法简单,使用方便。所有的EL表达式都是以“${”开始,以“}”结束,在JSP开发中有着大量的使用,通常情况下和JSTL搭配使用。关于JSTL的内容会在下一章节中讲解。
基本运算
操作符 | 描述 |
---|---|
. | 访问一个Bean属性 |
[] | 访问一个数组元素 |
( ) | 组织一个子表达式以改变优先级 |
+ | 加 |
- | 减或负 |
* | 乘 |
/ or div | 除 |
% or mod | 取模 |
== or eq | 测试是否相等 |
!= or ne | 测试是否不等 |
< or lt | 测试是否小于 |
> or gt | 测试是否大于 |
<= or l | 测试是否小于等于 |
>= or ge | 测试是否大于等于 |
&& or and | 测试逻辑与 |
|| or or | 测试逻辑或 |
! or not | 测试取反 |
empty | 测试是否空值 |
下面,通过示例学习EL表达式的用法:
1 | ${5+2} //结果:7 |
EL内置对象
内置对象 | 描述 |
---|---|
pageScope | page 作用域 |
requestScope | request 作用域 |
sessionScope | session 作用域 |
applicationScope | application 作用域 |
param | Request 对象的参数,字符串 |
paramValues | Request对象的参数,字符串集合 |
header | HTTP 信息头,字符串 |
headerValues | HTTP 信息头,字符串集合 |
initParam | 上下文初始化参数 |
cookie | Cookie值 |
pageContext | 当前页面的pageContext |
下面,通过示例来学习EL表达式内置对象的用法:
1 | <% |
1 | //例如我们要取得用户请求参数时,可以用下面方法: |
1 | //例如我们要获取用户浏览器的版本 |
1 | //获取设定web站点的环境参数,一般的方法: |
1 | //要获取cookie中有一个设定名称为userCountry的值, |
1 | //pageContext获取其他有关用户要求或页面的详细信息 |
JSTL
JSTL(JSP Standard Tag Library),规范由Sun公司制定,Apache的Jakoarta小组负责实现,JSTL的目标是为了简化JSP页面的设计。JTSL包括了5个不同作用的标签库,除了核心标签库以为其他4个标签库在开发中很少使用。接下来,详细学习JSTL核心标签库。
核心标签
set标签
属性 | 描述 |
---|---|
var | 存储在作用域中的键名称 |
value | 存在作用域中的值或者被修改对象的值 |
scope | 保存的作用域,默认保存在page中 |
target | 被修改属性的所属对象 |
property | 被修改属性的名称 |
示例:
1 | <%import="cn.bytecollege.model.Student"%> |
out标签
属性 | 描述 |
---|---|
value | 要输出的内容 |
default | 输出的默认值 |
escapeXml | 是否忽略特殊字符 |
示例:
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
remove标签
<c:remove>标签用于移除一个变量,可以指定这个变量的作用域,若未指定,则默认为变量第一次出现的作用域。
这个标签不是特别有用,不过可以用来确保JSP完成清理工作。
属性 | 描述 |
---|---|
var | 要移除的变量名 |
scope | 变量所属作用域 |
示例:
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
foreach标签
属性 | 描述 |
---|---|
items | 被遍历的对象 |
begin | 开始的元素索引 |
end | 结束的元素索引 |
step | 每一次迭代的步长 |
var | 当前元素的变量名称 |
varStatus | 循环变量的变量名称 |
1 | 我们常会用c标签来遍历需要的数据,为了方便使用,varStatus属性可以方便我们实现一些与行数相关的功能,如:奇数行、偶数行差异;最后一行特殊处理等等。先就varStatus属性常用参数总结下: |
if choose when标签
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |