2.6.3 exception对象

2.6.3 exception对象

exception对象是Throwable的实例,代表JSP脚本中产生的错误和异常,是JSP页面异常机制的一部分。
JSP脚本中无须处理异常,即使该异常是checked异常。事实上,JSP脚本包含的所有可能出现的异常都可交给错误处理页面处理。
看如图2.21所示的异常处理结构,这是典型的异常捕捉处理块。在JSP页面中,普通的JSP脚本只执行第一个部分——代码处理段,而异常处理页面负责第二个部分——异常处理段。在异常处理段中,可以看到有个异常对象,该对象就是内置对象exception
exception对象仅在异常处理页面中才有效,通过前面的异常处理结构,读者可以非常清晰地看出这点

_jspService方法中已经有异常处理代码

打开普通JSP页面所生成的Servlet类,将可以发现如下代码片段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void _jspService(final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
......
try {
response.setContentType("text/html; charset=UTF-8");
......
out.write("<!DOCTYPE html>\r\n");
out.write("<html>\r\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 {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {
}
if (_jspx_page_context != null)
_jspx_page_context.handlePageException(t);
else
throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}

从上面代码的粗体字代码中可以看出,JSP脚本和静态HTML部分都将转换成_jspService方法里的执行性代码这就是JSP脚本无须处理异常的原因:因为这些脚本已经处于try块中。一旦try块捕捉到JSP脚本的异常,并且_jspx_page_context不为null,就会由该对象来处理该异常。
_jspx_page_context对异常的处理也非常简单:如果该页面的page指令指定了errorPage属性,则将请求forwarderrorPage属性指定的页面,否则使用系统页面来输出异常信息。

由于只有JSP脚本、输出表达式才会对应于_jspService方法里的代码,所以这两个部分的代码无须处理checked异常。但JSP的声明部分依然需要处理checked异常,JSP的异常处理机制对JSP声明不起作用
JSP的异常处理机制中,一个异常处理页面可以处理多个JSP页面脚本部分的异常。异常处理页面通过page指令的errorPage属性确定。

throwEx.jsp

下面的页面再次测试了JSP脚本的异常机制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 通过errorPage属性指定异常处理页面 -->
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="error.jsp" %>
<!DOCTYPE html>
<html>
<head>
<title> JSP脚本的异常机制 </title>
</head>
<body>
<%
int a = 6;
int c = a / 0;
%>
</body>
</html>

以上页面的粗体字代码将抛出一个ArithmeticEception,则JSP异常机制将会转发到error.jsp页面.

error.jsp

error.jsp页面代码如下。

<%@ page contentType="text/html; charset=UTF-8" language="java" isErrorPage="true" %>



     异常处理页面 


异常类型是:<%=exception.getClass()%>
异常信息是:<%=exception.getMessage()%>

以上页面page指令的isErrorPage属性被设为true,则可以通过exception对象来访间上一个页面所出现的异常。

测试

在浏览器中请求throwEx.jsp页面,将看到如图2.22所示的界面

_jspService方法

打开error.jsp页面生成的Servlet类,在_jspService()方法中发现如下代码片段

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;
    java.lang.Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);
    if (exception != null) {
        response.setStatus(javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
    ......
}

从以上代码片段的粗体字代码中可以看出,当JSP页面page指令的isErrorPagetrue时,该页面就会提供exception内置对象。

在异常处理页面才能访问exception内置对象

应将异常处理页面中page指令的isErrorPage属性设置为true。只有当isErrorPage属性设置为true时才可访问exception内置对象.