目录
5.2.1 <jsp:include>标签与include指令的区别
一、认识JSP
-
1.1 什么是Java Server Pages
- JSP全称Java Server Pages,是建立在Servlet之上的动态网页开发技术。它使用JSP标签在HTML网页中插入Java代码。标签通常<%开头以%>结束。
- JSP文件中,HTML代码和Java代码共存。HTML代码实现网页静态内容显示,Java代码实现网页中动态内容显示。
- JSP是一种Java servlet,主要用于实现Java web应用程序的用户界面部分。网页开发者们通过结合HTML代码、XHTML代码、XML元素以及嵌入JSP操作和命令来编写JSP
- JSP通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页。
- JSP标签有多种功能,比如访问数据库、记录用户选择信息、访问JavaBeans组件等,还可以在不同的网页中传递控制信息和共享信息。
- Eg: 输出当前网页访问时间
<!--simple.jsp-->
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
</head>
<body>
当前访问时间是:
<%
out.print(new java.util.Date().toLocaleString());
%>
</body>
</html>
-
1.2 JSP运行原理
① 客户端向带有JSP引擎的web服务器(即tomcat)发送资源请求,该请求包括资源的路径,服务器通过该路径获取被请求的内容。
② 服务器根据客户端请求加载相应的JSP文件。
③ 服务器中的JSP引擎将加载的JSP文件转化成servlet。
④ 服务器中的JSP引擎将servlet编译成class文件。
⑤ 服务器执行class文件。
⑥ 服务器将执行结果响应给客户端(浏览器)
-
1.2.1 JSP相关配置
- Tomcat服务器的web.xml文件中实现了JSP的相关配置
- 也可像Servlet程序一样,在web.xml文件中进行注册和映射虚拟路径(以上述simple.jsp为例,配置信息如下)
<servlet>
<servlet-name>SimpleJspServlet</servlet-name>
<jsp-file>/simple.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>SimpleJspServlet</servlet-name>
<url-pattern>/mei</url-pattern>
</servlet-mapping>
1.3 分析JSP所生成的Servlet代码
- JSP页面翻译成的Servlet继承了org.apache.jasper.runtime.HttpJspBase类,HttpJspBase类是HttpServlet的一个子类,因此JSP页面翻译成的Servlet是HttpServlet的一个孙子类。
- HttpJspBase类实现了javax.servlet.jsp.HttpJspPage接口中的部分方法,因此,HttpJspBase类是抽象的。
- SUN公司为JSP的WEB容器开发商和JSP页面开发人员提供了一套专门应用于开发JSP程序的Java类,这套Java类被称为JSP API。
- HttpJspPage接口和JspPage接口属于JSP API,在HttpJspPage接口中只定义了一个_jspService方法,但它继承了JspPage接口,JspPage接口中定义了两个方法:jspInit()和jspDestroy()。
- HttpJspBase的init方法调用了jspInit和_jspInit方法,destroy方法内部调用了jspDestroy和_jspDestroy方法,service方法内部调用了_jspService方法。在HttpJspBase中实现的init、service和destroy方法都被声明成了final类型。
1.4 JSP结构
- 网络服务器需要一个 JSP 引擎,也就是一个容器来处理 JSP 页面。容器负责截获对 JSP 页面的请求。本教程使用内嵌 JSP 容器的 Apache 来支持 JSP 开发。
- JSP 容器与 Web 服务器协同合作,为JSP的正常运行提供必要的运行环境和其他服务,并且能够正确识别专属于 JSP 网页的特殊元素。
- JSP 网页就是用另一种方式来编写 Servlet 而不用成为 Java 编程高手
- 以下步骤表明了 Web 服务器是如何使用JSP来创建网页的:
- 就像其他普通的网页一样,您的浏览器发送一个 HTTP 请求给服务器。
- Web 服务器识别出这是一个对 JSP 网页的请求,并且将该请求传递给 JSP 引擎。通过使用 URL或者 .jsp 文件来完成。
- JSP 引擎从磁盘中载入 JSP 文件,然后将它们转化为 Servlet。这种转化只是简单地将所有模板文本改用 println() 语句,并且将所有的 JSP 元素转化成 Java 代码。
- JSP 引擎将 Servlet 编译成可执行类,并且将原始请求传递给 Servlet 引擎。
- Web 服务器的某组件将会调用 Servlet 引擎,然后载入并执行 Servlet 类。在执行过程中,Servlet 产生 HTML 格式的输出并将其内嵌于 HTTP response 中上交给 Web 服务器。
- Web 服务器以静态 HTML 网页的形式将 HTTP response 返回到您的浏览器中。
- 最终,Web 浏览器处理 HTTP response 中动态产生的HTML网页,就好像在处理静态网页一样。
1.5 JSP 生命周期
- JSP生命周期中所走过的几个阶段:
- 编译阶段:servlet容器编译servlet源文件,生成servlet类
- 初始化阶段:加载与JSP对应的servlet类,创建其实例,并调用它的初始化方法
- 执行阶段:调用与JSP对应的servlet实例的服务方法
- 销毁阶段:调用与JSP对应的servlet实例的销毁方法,然后销毁servlet实例
二、JSP 基本语法
2.1 JSP模板元素
- jsp页面中静态的html内容称之为模板元素。在静态的html内容中可以嵌套JSP的其他各种元素来产生动态内容和执行业务逻辑。
- jsp模板元素定义了网页的基本框架,即定义了页面的结构和外观
2.2 JSP表达式
- 语法格式:<%=expression %>
- jsp表达式中的变量或者表达式的计算结果将被转换成一个字符串,然后被插入进整个JSP页面输出结果的相应位置处。
- jsp表达式中的变量或者表达式后面不能有分号(;)
- 服务器会将其解释为Servlet中_jspService()中:out.print(expression);
- Eg:
2.3 JSP脚本片段
- 语法格式:
<%
语句1;
语句2;
%>
- JSP脚本片段(scriptlet)是指嵌套在<% %>之中的一条或多条java程序代码。
- 在JSP脚本片段中,可以定义变量,执行基本的程序运算,调用其他的java类,访问数据库,访问文件系统等普通java程序所能实现的功能。
- 在JSP脚本中可以直接使用jsp隐式对象来完成web程序所能实现的功能。
- 一个jsp页面可以有多个脚本片段,脚本片段可以互相访问。
- JSP脚本片段中的java代码将原封不动的搬移进由jsp页面所翻译的Servlet的JSPService中。因此必须严格遵守java规范。
- Eg1: 服务器会解释时将其原封不动地放在Servlet中_jspService()中
- Eg2: JSP脚本中嵌入JSP代码
运行结果:
2.4 JSP声明
- 语法格式:
<%!
java代码
%>
- 将其翻译到Servlet的_jspService()之外,定义的都是成员方法、成员变量、静态方法、静态变量、静态代码块等。不能使用局部变量。(开发中很少使用,面试的时候常问)
- Eg1:
- Eg2:因为x是类的成员变量,在JSP脚本中也可使用(且JSP声明的顺序在JSP脚本前后都可以)
2.5 JSP注释
- 语法格式:<%--注释 --%> 该注释信息不会发送到客户端
- 由于JSP页面存在HTML代码,因此可使用HTML注释”<!--注释-->“ ,该注释内容会被当作普通文本发送到客户端。
- Eg1:
三、JSP指令
- JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。
- JSP中的三种指令标签:
指令 | 描述 |
---|---|
<%@ page 属性名=“属性值”%> | 定义网页依赖属性,比如脚本语言、error页面、缓存需求等等 |
<%@ include file="文件相对url地址"%> | 包含其他文件 |
<%@ taglib uri="uri" prefix="prefixOfTag"%> | 引入标签库的定义 |
3.1 page指令
- page用来声明指令名称,属性用来指定JSP页面的某些特性
- contentType属性
例:<@page contentType=”text/html;charset=utf-8” %>
将会解释成java中的response.setContentType(“text/html;charset=utf-8”);
- Page指令相关的属性:
属性 | 描述 | 取值范围 |
---|---|---|
buffer | 指定out对象使用缓冲区的大小 | none或者数字+kb |
autoFlush | 控制out对象的缓存区,指明是否运行缓存 | true、false |
contentType | 指定当前JSP页面的MIME类型和字符编码。客户端浏览器根据该属性判断文档类型 | 有效的文档类型 eg: HTML格式为 text/html 纯文本格式为 text/plain JPG图像为 image/jpeg GIF图像为 image/gif Word文档为 application/msword |
errorPage | 指定当JSP页面发生异常时需要转向的错误处理页面 | 某个jsp页面的相对路径 |
isErrorPage | 指定当前页面是否可以作为另一个JSP页面的错误处理页面 | true、false |
extends | 指定servlet从哪一个类继承;JSP为Servlet,因此当指明继承普通类时需要实现Servlet的init()、destroy()等方法 | 任何类的全名 |
import | 导入要使用的Java类 | 任何包名、类名 |
info | 定义JSP页面的描述信息; 指明JSP的信息,该信息可通过Servlet.getServletInfo()方法获取 | 任意字符串 |
isThreadSafe | 指定对JSP页面的访问是否为线程安全 | true、false |
language | 定义JSP页面所用的脚本语言,默认是Java | java |
session | 指定JSP页面是否使用session;默认为true; 注意:JSP引擎自动导入以下四个包: java.lang.* javax.servlet.* javax.servlet.jsp.* javax.servlet.http.* | true、false |
isELIgnored | 指定是否执行EL表达式 | true、false |
isScriptingEnabled | 确定脚本元素能否被使用 | true、false |
- Eg1:errorPage为当前页面的出现异常时指定一跳转到的页面
Index.jsp
Error.jsp
运行index.jsp,会自动跳转到error.jsp
通过查看发送头与响应头,可以看到状态码是200,而不是真正的错误代码。
- Eg2:在error.jsp的page指令中添加 isErrorPage属性
- Eg3:修改simple.jsp与error.jsp,如果设定了isErrorPage指令,可在其页面中调用exception内置对象
运行
- 也可在web.xml文件中设置通用的错误页面修改web.xml
新建e.jsp页面
新建404.jsp页面
新建500.jsp页面
运行e.jsp:
将e.jsp写为E.jsp运行结果:
- 也可在web.xml中指定具体错误的处理页面
修改index.jsp,去掉errorPage属性
运行:
3.2 include指令
- Eg1:
<!--include.jsp-->
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>欢迎你</title>
</head>
<body>
你好呀,现在时间是:
<%@include file="date.jsp" %>
</body>
</html>
<!--date.jsp-->
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
</head>
<body>
<%out.println(new java.util.Date().toLocaleString()); %>
</body>
</html>
- Eg2:
1.创建a.jsp
2.创建b.jsp
3.运行
4.a_java中内容
四、JSP隐式对象
4.1 隐式对象表
- JSP隐式对象是JSP容器为每个页面提供的Java对象,开发者可以直接使用它们而不用显式声明。JSP隐式对象也被称为预定义变量。
对象 | 描述 | 类型 |
---|---|---|
request | 得到用户请求 | javax.servlet.http.HttpServletRequest |
response | 服务器向客户端的回应信息 | javax.servlet.http.HttpServletResponse |
out | 用于页面输出 | javax.servlet.jsp.JspWriter |
session | 用来保存用户信息 | javax.servlet.http.HttpSession |
application | ServletContext类的实例,与应用上下文有关;所有用户的共享信息 | javax.servlet.ServletContext |
config | 服务器配置,可以取得初始化参数 | javax.servlet.ServletConfig |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问;JSP的页面容器 | javax.servlet.jsp.PageContext |
page | 类似于Java类中的this关键字;指当前页面转换后的Servlet类的实例 | java.lang.Object |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象 | java.lang.Throwable |
4.2 out对象
- out对象是javax.servlet.jsp.JspWriter类的实例对象,它的作用与ServletResponse.getWriter()方法返回的PrintWriter对象非常相似,都是用来向客户端发送文本形式的实体内容。不同的是,out对象的类型为JspWriter,它相当于一种带缓存功能的PrintWriter。
-
JSP 页面通过指令的autoFlush属性和buffer属性配置缓冲区参数:
- autoFlush属性表示是否自动刷新,默认值为true;
- buffer属性表示缓冲区大小,默认值为8kb。在此配置下,out对象在输出缓冲区内容每达到8kb后,会自动刷新输出而不会产生异常
- out对象的方法可以分为两类:
(1)数据的输出
数据输出方法及描述 | |
out.print/println(基本数据类型) | 输出一个基本数据类型的值 |
out.print/println(Object ibj) | 输出一个对象的引用地址 |
out.print/println(String str) | 输出一个字符串的值 |
out.newLine() | 输出一个换行符 |
out.print/println(基本数据类型) | 输出一个基本数据类型的值 |
(2)缓冲区的处理
out对象缓冲区的处理方法及描述 | |
void clear() | 清除输出缓冲区的内容。若缓冲区为空,则产生IOException异常 |
void clearBuffer() | 清除输出 缓冲区的内容。若缓冲区为空,无异常出现 |
void flush() | 直接将目前暂存于缓冲区的数据刷新输出 |
void close() | 关闭输出流。流一旦被关闭,则不能再使用out对象做任何操作 |
int getBufferSize() | 获取目前缓冲区的大小(KB) |
int getRemaining() | 获取目前使用后还剩下的缓冲区大小(KB) |
boolean isAutoFlush() | 返回true表示缓冲区满时会自动刷新输出;flase表示缓冲区满时不会自动清除并产生异常处理 |
- 在JSP页面中,通过out隐式对象写入数据相当于将数据插入到JspWriter对象的缓冲区中,只有调用了ServletResponse.getWriter()方法,缓冲区中的数据才能真正写入到Servlet引擎所提供的缓冲区中。
- Eg:
- 由运行结果可知,尽管out.println语句位于response.getWriter().println语句之前,但输出内容却在后面。由此可说明,out对象通过print语句写入数据后,直到整个JSP页面结束,out对象中输入缓冲区中的数据(即:first line)才真正写入到Servlet引擎提供的缓冲区中,而response.getWriter().println语句则是直接把内容(即:second line)写入Servlet引擎提供的缓冲区中,Servlet引擎按照缓冲区中的数据存放顺序输出内容。
- 可通过page指令操作缓冲区的buffer属性来实现将out对象数据写入Servlet引擎提供的缓冲区中
- Eg:
- 由此可见,out对象中的数据直接写入了Servlet引擎提供的缓冲区中。此外,当写入到out对象中的内容充满了out对象的缓冲区时,out对象中输入缓冲区的数据也会真正写入到Servlet引擎提供的缓冲区中。
4.2 pageContext对象
- JSP页面中,使用pageContext对象可以获取JSP的其他8个隐式对象。pageContext对象是javax.servlet.jsp.PageContext类的实例对象,它代表当前JSP页面的运行环境,并提供了一系列用于获取其他隐式对象的方法。
- 当传递一个pageContext对象后就可以通过以下方法轻松获取其他8个隐式对象
- 需要注意的是:虽然在JSP页面中可以直接使用隐式对象,但通过pageContext对象获取其他隐式对象的功能也是必不可少的。例如,在之后标签的学习中,需要将java代码从JSP页面移除,这时JSP隐式对象也需要传递给java类中定义的方法。通常情况下,为方便,只传递一个pageContext对象,然后通过调用如下表所示方法来获取其他隐式对象。
-
4.2.1 获取隐式对象的方法
pageContext获取隐式对象的方法 | |
方法名 | 功能描述 |
JspWriter getOut() | 获取Out隐式对象 |
Object getPage() | 获取Page隐式对象 |
ServeletRequest getRequest() | 获取Request隐式对象 |
ServeletResponse getResponse() | 获取Response隐式对象 |
HttpSession getSession() | 获取exception隐式对象 |
Exception getException() | 获取exception隐式对象 |
ServletConfig getServletConfig() | 获取config隐式对象 |
ServletContext getServletContext() | 获取application隐式对象 |
- Eg: 通过一个案列来演示如何使用pageContext获取request对象
-
4.2.2 操作属性的相关方法
- pageContext还提供存储数据的功能,该功能通过操作属性来实现
pageContext操作属性的相关方法 | |
方法名称 | 功能描述 |
void setAttribute(String name, Object value, int scope) | 在指定范围中添加数据;用于设置pageContext对象的属性 |
Object getAttribute(String name, int scope) | 获取指定范围的数据;用于获取pageContext对象的属性 |
void removeAttribute(String name, int scope) | 移除指定范围的数据;删除指定范围内名为name的属性;若没有int scope部分则说明删除所有范围内名为name的属性; |
Object findAttribute(String name) | 从4个域对象中查找名称为name的属性 |
- 参数name指定的是属性的名称,参数scope指定的是属性的作用范围,pageContext对象的作用范围有四个值,如下:
-
4.2.3 pageContext对象的作用范围
pageContext对象的作用范围 | |
PageContext.PAGE_SCOPE | 表示页面范围 |
PageContext.REQUEST_SCOPE | 表示请求范围 |
PageContext.SESSION_SCOPE | 表示会话范围 |
PageContext.APPLICATION_SCOPE | 表示Web应用程序范围 |
- 需要注意的是:当使用findAttribute()方法查找名称为name属性的时候,会按照page、request、session、application的顺序依次进行查找,如果找到,则返回属性的名称,否则返回null。
- Eg: 通过一个案列,来看看如何使用pageContext存储数据
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<%
pageContext.setAttribute("student","mei mei",pageContext.PAGE_SCOPE);
Object name=pageContext.getAttribute("student",pageContext.PAGE_SCOPE);
out.println("学生的名字为:"+name);
%>
</body>
</html>
4.3 exception对象
- exception对象用来处理JSP文件执行时发生的所有错误和异常,只有在page指令中设置为isErrorPage属性值为true的页面中才可以被使用,在一般的JSP页面中使用该对象将无法编译JSP文件。
- exception对象几乎定义了所有的异常情况,在Java程序中,可以使用try...catch关键字来处理异常情况,如果在JSP页面中出现没有捕捉到的异常,就会生成exception对象,并把exception对象传送到在page指令中设定的错误页面中,然后在错误页面中处理相应的exception对象
-
4.3.1 exception对象的常用方法:
exception对象的常用方法 | |
方 法 | 说 明 |
getMessage() | 返回exception对象的异常信息字符串 |
getLocalizedmessage() | 返回本地化的异常错误 |
toString() | 返回关于异常错误的简单信息描述 |
fillInStackTrace() | 重写异常错误的栈执行轨迹 |
- Eg: 通过以下案例,学习exception对象的使用
将request.setAttribute("price", "aaa");改为request.setAttribute("price", "123");
五、JSP标签
- 可以理解为jsp页面中出现的java代码越少,对jsp的掌握就越好,更利于美工调试和维护,而替换掉java代码的重要方式就是使用jsp标签。这些标签可以完成各种通用的JSP页面功能
5.1 常用jsp标签:
常用jsp标签 | |
标签 | 描述 |
<jsp:include page="页面"> | 包含 |
<jsp:param name="name" value="value"> | 传参 |
<jsp:foward page="页面"> | 转发 |
<jsp:useBean> | 相当于实例化类 |
<jsp:setProperty> | 给useBean属性设置值 |
<jsp:getProperty> | 取值 |
5.2 <jsp:include>标签
- <jsp:include>标签,可将其他资源的输出内容插入到当前JSP页面的输出内容中,动态包含,程序执行时包含。
- <jsp:include>标签具体语法:
- <jsp:include page="relativeURL" flush="true/false"/>
- page属性用于指定被引入资源的相对路径;flush属性用于指定是否将当前页面的输出内容刷新到客户端,默认情况下,flush属性为false
- 用以下示例学习<jsp:include>标签(创建3个jsp文件,分别为a.jsp、b.jsp、c.jsp)
运行结果如下:
5.2.1 <jsp:include>标签与include指令的区别
- <jsp:include>标签中要引入的资源和当前JSP页面是两个彼此独立的执行实体,即被动态引入的资源必须能够被Web容器独立执行。 而include指令只能引入遵循JSP格式的文件,被引入文件与当前JSP文件需要共同合并才能翻译成一个Servlet源文件。
- <jsp:include>标签引入的资源是在运行时才包含的,而且只包含运行结果。 而include指令是在编译时期包含的,包含的是源代码。
- <isp:include>标签运行原理与RequestDispatcher.include方法类似,即被包含的页面不能改变响应状态码或者设置响应头,而include指令没有这方面的限制。
5.3 <jsp:forward>标签
-
不同于servlet中我们使用request对象进行请求转发,在JSP中我们直接使用forward标签进行转发操作使用该标签能将请求继续交给其它jsp或servlet进行进一步的操作。
-
语法格式:<jsp:forward page="relativeURL"/>
-
page属性用于指定请求转发到的资源的相对路径,该路径是相当于当前JSP页面的URL
- <jsp:forward>标签,若a.jsp转发到b.jsp,则a.jsp内容看不到,且a.jsp转发下的内容不会执行
- Eg:
通过查看jspforward.jsp页面翻译的Servlet源文件,发现<jsp:forward>标签被翻译成了如下一段代码。(<jsp:forward>标签被翻译成了调用pageContext.forward方法的语句,并在调用该方法后使用return语句结束了service()方法执行流程,从而不在执行<jsp:forward>标签后的语句)
注意:如果在JSP页面中直接调用pageContext.forward()方法,当forward()方法后还有语句需要执行时,程序会发生IllegalStateException异常。但如果在JSP页面使用<jsp:forward>标签,则会避免程序报错,原因如上面程序段代码(使用了return语句终止执行后面的语句)