版本:html
Servlet有两个缺点是没法克服的:
1,写在Servlet中的全部HTML标签必须包含Java字符串,这使得处理HTTP响应报文的工做十分烦琐;
2,全部的文本和HTML标记是硬编码,致使即便是表现层的微小变化,如改变背景颜色,也须要从新编译。
JavaServer Pages(JSP)解决了上述两个问题。同时,JSP不会取代Servlet,相反,它们具备互补性。
一个JSP页面不一样于一个Servlet的另外一个方面是:前者不须要添加注解或在部署描述符中配置映射URL。
补充:java
能够用标准语法或XML语法编写JSP。
用XML语法编写的JSP页面被称为JSP文档。
但不多用XML语法编写JSP,不详述。
JSP页面本质上是一个Servlet。
JSP页面在JSP容器中运行,一个Servlet容器一般也是JSP容器。
例如,Tomcat就是一个Servlet/JSP容器。
当一个JSP页面第一次被请求时,Servlet/JSP容器主要作如下两件事情:express
(1)转换JSP页面到JSP页面实现类,
该实现类是一个实现javax.servlet.jsp.JspPage接口或子接口javax.servlet.jsp.HttpJspPage的Java类。
JspPage是javax.servlet.Servlet的子接口,这使得每个JSP页面都是一个Servlet。 该实现类的类名由Servlet/JSP容器生成。若是出现转换错误,则相关错误信息将被发送到客户端。 (2)若是转换成功,Servlet/JSP容器随后编译该Servlet类,并装载和实例化该类,像其余正常的Servlet同样执行生命周期操做。
ps:总结:apache
jsp页面转换为servlet过程: 1,jsp转换为了servlet接口的子接口JspPage的子接口HttpJspPage的java类(即servlet类)。 2,编译该HttpJspPage类型的servlet。
jsp页面重复被请求时:json
对于同一个JSP页面的后续请求,Servlet/JSP容器会先检查JSP页面是否被修改过。 若是是,则该JSP页面会被从新翻译、编译并执行。 若是不是,则执行已经在内存中的JSP Servlet。
解决:一个JSP页面的第一次调用的很耗时问题:api
1,配置应用程序,使全部的JSP页面在应用程序启动时被调用,而不是在第一次请求时调用。 2,预编译JSP页面,并将其部署为Servlet。
JSP自带的API包含4个包:浏览器
1,javax.servlet.jsp。 包含用于Servlet/JSP容器将JSP页面翻译为Servlet的核心类和接口。
其中的两个重要成员是JspPage和HttpJspPage接口。 全部的JSP页面实现类必须实现JspPage或HttpJspPage接口。 在HTTP环境下,实现HttpJspPage接口是显而易见的选择。 2,javax.servlet.jsp.tagext。包括用于开发自定义标签的类型。 3,javax.el。提供了统一表达式语言的API。 4,javax.servlet.jsp.el。提供了一组必须由Servlet/JSP容器支持,以便在JSP页面中使用表达式语言的类
jsp api: https://docs.oracle.com/javaee/7/api/index.html?javax/servlet/jsp/package-summary.html
注意:通常不多直接使用jspAPI,而是让容器自动调用tomcat
ps:总结:安全
减小jsp第一次请求编译过程的方式: 1,启动服务器编译jsp 2,主动将jsp直接编译成servlet
1,语法元素是一些具备特殊意义的JSP转换符。 3个语法元素(指令、脚本元素和动做) 2,除去语法元素外的一切是模板数据。 模板数据会原样发送给浏览器。 例如,JSP页面中的HTML标记和文字都是模板数据。
补充:经常使用模板引擎服务器
JSP ,velocity,freemark
一个名为welcome.jsp的JSP页面
<html>
<head><title>Welcome</title></head>
<body>
Welcome
</body>
</html>
welcome.jsp页面在第一次请求时被翻译成名为welcome_jsp的Servlet。
你能够在Tomcat工做目录下的子目录中找到生成的Servlet,
该Servlet继承自org.apache.jasper. runtime.HttpJspBase,
(这是一个抽象类,
继承自javax.servlet.http.HttpServlet并实现javax.servlet.jsp.HttpJspPage)
package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class welcome_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent{
private static final javax.servlet.jsp.JspFactory _jspxFact ory =javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long>、getDependants() { return _jspx_dependants; }
public void _jspInit() { _el_expressionfactory =_jspxFactory.getJspApplicationContext(getServletConfig().getServletContext())
.getExpressionFactory();
_jsp_instancemanager =org.apache.jasper.runtime.InstanceManagerFactory .getInstanceManager(getServletConfig()); }
public void _jspDestroy() {}
public void _jspService(final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException {
final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; //当前页面 javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null;
try { response.setContentType("text/html"); pageContext = _jspxFactory.getPageContext(this, request,response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out;
out.write("<html>\n"); out.write("<head><title>Welcome</title></head>\n"); out.write("<body>\n"); out.write("Welcome\n"); out.write("</body>\n"); out.write("</html>"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { out.clearBuffer(); } catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
} } finally { _jspxFactory.releasePageContext(_jspx_page_context); }}}
(ps:有点奇怪,为何有重复的对象引用好比:out 和 _jspx_out ???)
补充:
JSP页面的主体是_jspService方法。 这个方法被定义在HttpJspPage,并被HttpJspBase的service方法调用。 下面的代码来自HttpJspBase类: public final void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException { _jspService(request, response); }
JSP支持两种不一样的注释格式:
1)JSP注释。该注释记录页面中作了什么。
2)HTML/XHTML注释。这些注释将会发送到浏览器上。
JSP注释以“<%--”开始,以“--%>”结束。
下面是一个例子:<%-- retrieve products to display --%> JSP注释不会被发送到浏览器端,也不会被嵌套。 HTML/XHTML注释语法以下: <!-- [comments here] --> 一个HTML/XHTML注释不会被容器处理,会原样发送给浏览器。
HTML/XHTML注释的一个用途是用来肯定JSP页面自己。 <!-- this is /jsp/store/displayProducts.jspf --> 尤为是在运行有多个JSP片断的应用时,会特别有用。 是哪个JSP页面或片断产生了相应的HTML片断。
Servlet容器会传递几个对象给它运行的Servlet。
例如,能够经过Servlet的service方法拿到HttpServletRequest和HttpServletResponse对象,
以及能够经过init方法访问到ServletConfig对象。
能够经过调用HttpServletRequest对象的getSession方法访问到HttpSession对象。
JSP隐式对象(9个):
对象 类型
request javax.servlet.http.HttpServletRequest
response javax.servlet.http.HttpServletResponse
out javax.servlet.jsp.JspWriter
session javax.servlet.http.HttpSession
application javax.servlet.ServletContext
config javax.servlet.ServletConfig
pageContext javax.servlet.jsp.PageContext
page javax.servlet.jsp.HttpJspPage (表示当前页面,通常用不到)
exception java.lang.Throwable
该隐式对象表明Servlet/JSP容器传递给Servlet服务方法的HttpServlet Request对象。 <% String userName = request.getParameter("userName"); %>
pageContext用于javax.servlet.jsp.PageContext。 它提供了有用的上下文信息,并经过其自说明的方法来访问各类Servlet相关对象,
如getRequest、getResponse、getServletContext、getServletConfig和getSession。
但在脚本中不是很是有用的,由于能够更直接地经过隐式对象来访问request、response、session和application。 PageContext中提供了另外一组有趣的方法: 用于获取和设置属性的方法,即getAttribute方法和setAttribute方法。
属性值可被存储在4个范围之一: 页面、请求、会话和应用程序。 页面范围是最小范围,这里存储的属性只在同一个JSP页面可用。 请求范围是指当前的ServletRequest中。 会话范围指当前的HttpSession中。 应用程序范围指应用的ServletContext中。 PageContext的setAttribute方法签名以下: public abstract void setAttribute(java.lang.String name, java.lang.Object value, int scope) 其中,scope的取值范围为PageContext对象的最终静态int值:
PAGE_SCOPE、REQUEST_ SCOPE、SESSION_SCOPE和APPLICATION_SCOPE。 若要保存一个属性到页面范围,能够直接使用setAttribute重载方法: public abstract void setAttribute(java.lang.String name, java.lang.Object value)
以下脚本将一个属性保存到ServletRequest中: <% //product is a Java object pageContext.setAttribute("product", product,PageContext.REQUEST_SCOPE); %>
一样效果的Java代码以下: <% request.setAttribute("product", product); %>
隐式对象out引用了一个javax.servlet.jsp.JspWriter对象,
这相似于你在调用HttpServlet Response的getWriter方法时获得java.io.PrintWriter。
能够经过调用它的print方法将消息发送到浏览器。
例如:
out.println("Welcome");
implicitObjects.jsp页面 <%@page import="java.util.Enumeration"%> <html> <head><title>JSP Implicit Objects</title></head> <body> <b>Http headers:</b><br/> <% for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements(); ){ String header = e.nextElement(); out.println(header + ": " + request.getHeader(header) + "<br/>"); } %> <hr/> <% out.println("Buffer size: " + response.getBufferSize() + "<br/>"); out.println("Session id: " + session.getId() + "<br/>"); out.println("Servlet name: " + config.getServletName() + "<br/>"); out.println("Server info: " + application.getServerInfo()); %> </body> </html>
该页面产生了以下内容: Http headers: host: localhost:8080 user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.50.2 (KHTML, like Gecko) Version/5.0.6 Safari/533.22.3 accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8 accept-language: en-us accept-encoding: gzip, deflate connection: keep-alive Buffer size: 8192 Session id: 561DDD085ADD99FC03F70BDEE87AAF4D Servlet name: jsp Server info: Apache Tomcat/7.0.14
注意,在默认状况下,JSP编译器会将JSP页面的内容类型设为text/html。
若是要使用不一样的类型,则须要经过调用response.setContentType()或者使用页面指令来设置内容类型。 例如,下面就是将内容类型设置为text/json: response.setContentType("text/json");
指令是JSP语法元素的第一种类型。 它们指示JSP转换器如何翻译JSP页面为Servlet。 JSP 2.2定义了多个指令,但page和include最重要,其余 taglib、tag、attribute以及variable。
可使用page指令来控制JSP转换器转换当前JSP页面的某些方面。
例如,能够告诉JSP用于转换隐式对象out的缓冲器的大小、内容类型,以及须要导入的Java类型,等等。
page指令的语法以下:
<%@ page attribute1="value1" attribute2="value2" ... %>
@和page间的空格不是必须的,attribute一、attribute2等是page指令的属性。
以下是page指令属性列表:
import:定义一个或多个本页面中将被导入和使用的java类型。 例如:import="java.util.List"将导入List接口。 可使用通配符“*”来引入整个包,相似import="java.util.*"。 能够经过在两个类型间加入“,”分隔符来导入多个类型,如 import="java.util.ArrayList、java.util.Calendar、java.io.PrintWriter"。 此外,JSP默认导入以下包:java.lang、javax.servlet、javax.servlet.http、javax.servlet.jsp。 session:值为True,本页面加入会话管理;值为False则相反。 默认值为True,访问该页面时,若当前不存在javax.servlet.http.HttpSession实例,则会建立一个。 buffer:以KB为单位,定义隐式对象out的缓冲大小。 必须以KB后缀结尾。 默认大小为8KB或更大(取决于JSP容器)。 该值能够为none,这意味着没有缓冲,全部数据将直接写入PrintWriter。
autoFlush:默认值为True。 若值为True,则当输出缓冲满时会自写入输出流。 而值为False,则仅当调用隐式对象的flush方法时,才会写入输出流。所以,若缓冲溢出,则会抛出异常。 isThreadSafe:定义该页面的线程安全级别。 不推荐使用 JSP 参数,由于使用该参数后,会生成一些Servlet容器已过时的代码。 info:返回调用容器生成的Servlet类的getServletInfo方法的结果。 errorPage:定义当出错时用来处理错误的页面。 isErrorPage:标识本页是一个错误处理页面。 contentType:定义本页面隐式对象response的内容类型,默认是text/html。 pageEncoding:定义本页面的字符编码,默认是ISO-8859-1。 isELIgnored:配置是否忽略EL表达式。EL是Expression Language的缩写。 language:定义本页面的脚本语言类型,默认是Java,这在JSP 2.2中是惟一的合法值。 extends:定义JSP实现类要继承的父类。这个属性的使用场景很是罕见,仅在很是特殊理由下使用。 deferredSyntaxAllowedAsLiteral:定义是否解析字符串中出现“#{”符号,默认是False。 “{# ”是一个表达式语言的起始符号。 trimDirectiveWhitespaces:定义是否不输出多余的空格/空行,默认是False。
可使用include指令将其余文件中的内容包含到当前JSP页面。
一个页面中能够有多个include指令。
若存在一个内容会在多个不一样页面中使用或一个页面不一样位置使用的场景,则将该内容模块化到一个include文件很是有用。
include指令的语法以下:
<%@ include file="url"%>
其中,@和include间的空格不是必须的,URL为被包含文件的相对路径, 若URL以一个斜杠(/)开始,则该URL为文件在服务器上的绝对路径,不然为当前JSP页面的相对路径。
JSP转换器处理include指令时,将指令替换为指令所包含文件的内容。 换句话说,若是编写在清单3.4的copyright.jspf文件,以及主文件清单3.5的main.jsp页面: 清单3.4 copyright.jspf文件 <hr/> ©2015 BrainySoftware <hr/> 清单3.5 main.jsp页面 <html> <head><title>Including a file</title></head> <body> This is the included content: <hr/> <%@ include file="copyright.jspf"%> </body> </html> 则在main.jsp页面中应用include指令和以下页面的效果是同样的: <html> <head><title>Including a file</title></head> <body> This is the included content: <hr/> <hr/> ©;2015 BrainySoftware <hr/> </body> </html> 如上示例中,为保证include指令能正常工做,copyright.jspf文件必须同main.jsp位于相同的目录。 按照惯例,以JSPF为扩展名的文件表明JSP fragement。 虽然JSP fragement如今被称为JSP segment,但为保证一致性,JSPF后缀名依然被保留。
注意,include指令也能够包含静态HTML文件。
一个脚本程序是一个Java代码块,以<%符号开始,以%>符号结束。
使用脚本程序(scriptletTest.jsp)
<%@page import="java.util.Enumeration"%> <html> <head><title>Scriptlet example</title></head> <body> <b>Http headers:</b><br/> <%-- first scriptlet --%> <% for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements(); ){ String header = e.nextElement(); out.println(header + ": " + request.getHeader(header) + "<br/>"); } String message = "Thank you."; %> <hr/> <%-- second scriptlet --%> <% out.println(message); %> </body> </html>
定义在一个脚本程序中的变量能够被其后续的脚本程序使用。
每一个表达式都会被JSP容器执行,并使用隐式对象out的打印方法输出结果。 表达式以“<%=”开始,并以“%>”结束。
Today is <%=java.util.Calendar.getInstance().getTime()%>
注意,表达式无须分号结尾。
JSP容器首先执行java.util.Calendar.getInstance().getTime(),并将计算结果传递给out.print(),
这与以下脚本程序的效果同样: Today is <% out.print(java.util.Calendar.getInstance().getTime()); %>
能够声明能在JSP页面中使用的变量和方法。
声明以“<%!”开始,并以“%>”结束。
declarationTest.jsp声明了一个getTodaysDate的方法
<%! public String getTodaysDate() { return new java.util.Date(); } %> <html> <head><title>Declarations</title></head> <body> Today is <%=getTodaysDate()%> </body> </html>
在JSP页面中,一个声明能够出如今任何地方,而且一个页面能够有多个声明。
可使用声明来重写JSP页面,实现类的init和destroy方法
经过声明jspInit方法,来重写init方法。
经过声明jspDestroy方法,来重写destory方法。
这两种方法说明以下:
jspInit。这种方法相似于 javax.servlet.Servlet 的 init方法。
JSP 页面在初始化时调用jspInit。
不一样于init方法,jspInit没有参数。
还能够经过隐式对象config访问ServletConfig对象。
jspDestroy。这种方法相似于Servlet的destroy方法,在JSP页面将被销毁时调用。
lifeCycle.jsp页面演示了如何重写jspInit和jspDestroy
<%! public void jspInit() { System.out.println("jspInit ..."); } public void jspDestroy() { System.out.println("jspDestroy ..."); } %> <html> <head><title>jspInit and jspDestroy</title></head> <body> Overriding jspInit and jspDestroy </body> </html>
lifeCycle.jsp页面会被转换成以下Servlet:
package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class lifeCycle_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { public void jspInit() { System.out.println("jspInit ..."); }
public void jspDestroy() { System.out.println("jspDestroy ..."); }
private static final javax.servlet.jsp.JspFactory _jspxFact ory =javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; }
public void _jspInit() { _el_expressionfactory =_jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).
getExpressionFactory(); _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); }
public void _jspDestroy() { }
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)throws java.io.IOException, javax.servlet.ServletException { final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try {
response.setContentType("text/html"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\n"); out.write("<html>\n"); out.write("<head><title>jspInit and jspDestroy" + "</title></head>\n"); out.write("<body>\n"); out.write("Overriding jspInit and jspDestroy\n"); out.write("</body>\n"); out.write("</html>"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) { } if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context) ;}}}
注意生成的Servlet类中的jspInit和jspDestroy方法。
如今能够用以下URL访问lifeCycle.jsp:
http://localhost:8080/app03a/lifeCycle.jsp
第一次访问页面时,能够在控制台上看到“jspInit...”,
以及在Servlet/JSP容器关闭时看到“jspDestory...”。
随着JSP 2.0对表达式语言的增强, 推荐:在JSP页面中用EL访问服务器端对象且不写Java代码。 所以,从JSP 2.0起,
能够经过在部署描述符中的<jsp-property-group>定义一个scripting-invalid元素,来禁用脚本元素。
<jsp-property-group> <url-pattern>*.jsp</url-pattern> <scripting-invalid>true</scripting-invalid> </jsp-property-group>
动做是第三种类型的语法元素,它们被转换成Java代码来执行操做,如访问一个Java对象或调用方法。
本节仅讨论全部JSP容器支持的标准动做。
除标准外,还能够建立自定义标签执行某些操做。
useBean将建立一个关联Java对象的脚本变量。
这是早期分离的表示层和业务逻辑的手段。
随着其余技术的发展,如自定义标签和表达语言,如今不多使用useBean方式。
useBeanTest.jsp页面是一个示例, 它建立一个java.util.Date实例,并赋值给名为today的脚本变量,而后在表达式中使用。 useBeanTest.jsp页面 <html> <head> <title>useBean</title> </head> <body> <jsp:useBean id="today" class="java.util.Date"/> <%=today%> </body> </html>
在Tomcat中,上述代码会被转换为以下代码:
java.util.Date today = null; today = (java.util.Date) _jspx_page_context.
getAttribute("today",javax.servlet.jsp.PageContext.REQUEST_SCOPE);
if (today == null) { today = new java.util.Date(); _jspx_page_context.setAttribute("today", today,javax.servlet.jsp.PageContext.REQUEST_SCOPE); }
setProperty动做可对一个Java对象设置属性,而getProperty则会输出Java对象的一个属性。
getSetPropertyTest.jsp展现如何设置和输出定义在Employee类实例的firstName属性。
Employee类 package app03a; public class Employee { private String id; private String firstName; private String lastName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } getSetPropertyTest.jsp页面 <html> <head> <title>getProperty and setProperty</title> </head> <body> <jsp:useBean id="employee" class="app03a.Employee"/> <jsp:setProperty name="employee" property="firstName" value="Abigail"/> First Name:
<jsp:getProperty name="employee" property="firstName"/> </body> </html>
include动做用来动态地引入另外一个资源。
能够引入另外一个JSP页面,也能够引入一个Servlet或一个静态的HTML页面。
jspIncludeTest.jsp页面使用include动做来引入menu.jsp页面。
jspIncludeTest.jsp页面 <html> <head> <title>Include action</title> </head> <body> <jsp:include page="jspf/menu.jsp"> <jsp:param name="text" value="How are you?"/> </jsp:include> </body> </html>
对于include指令,资源引入发生在页面转换时,即当JSP容器将页面转换为生成的Servlet时。
而对于include动做,资源引入发生在请求页面时。
所以,使用include动做是能够传递参数的,而include指令不支持。
第二个不一样是,include指令对引入的文件扩展名不作特殊要求。
但对于include动做,若引入的文件需以JSP页面处理,则其文件扩展名必须是JSP。
若使用.jspf为扩展名,则该页面被看成静态文件。
forward将当前页面转向到其余资源。
下面代码将从当前页转向到login.jsp页面:
<jsp:forward page="jspf/login.jsp"> <jsp:param name="text" value="Please login"/> </jsp:forward>
JSP提供了很好的错误处理能力。
除了在Java代码中可使用try语句,还能够指定一个特殊页面。
当应用页面遇到未捕获的异常时,用户将看到一个精心设计的网页解释发生了什么,而不是一个用户没法理解的错误信息。
page指令的isErrorPage属性(属性值必须为True)来标识一个JSP页面是错误页面
<%@page isErrorPage="true"%> <html> <head><title>Error</title></head> <body> An error has occurred. <br/> Error message: <% out.println(exception.toString()); %> </body> </html>
其余须要防止未捕获的异常的页面使用page指令的errorPage属性来指向错误处理页面。
buggy.jsp页面就使用了错误处理程序。 buggy.jsp页面 <%@page errorPage="errorHandler.jsp"%> Deliberately throw an exception <% Integer.parseInt("Throw me"); %>
运行的buggy.jsp页面会抛出一个异常,不会看到由Servlet/JSP容器生成错误消息。
相反,会看到errorHandler.jsp页面的内容。
ps:总结:3个语法元素:指令、脚本元素和动做
指令:至关于一种配置的参数
脚本:至关于拼接进入java类
动做:至关于方法的占位符