大可制作:QQ群:31564239(asp|jsp|php|mysql)

JSP/Servlet: 错误处理

刚开始撰写JSP时,总是会被JSP的除错讯息所困扰,如果没有稍微了解JSP与Servlet之间运作关系的初学者,所看到的只是一堆除错讯息,甚至异常发生的讯息,这些讯息虽然包括详细的错误讯息,但对于初学者而言却是不友善、不易阅读理解的。基本上,只要了解JSP与Servlet之间的运作关系, 并了解Java编译讯息与异常处理,要了解在撰写JSP网页时,因错误而产生的错误报告页面就不是件难事。

JSP终究会转译为Servlet,所以运行时真正动作的是Servlet类,所以错误可能发生在两个时候:一个是JSP转换为 Servlet原始码时,因为JSP语法错误而导致无法生成Servlet原始码,或已转换为Servlet程序码,但编译时编译器检查出错误,这称之为Translation Time Processing Errors;第二个错误发生的时期在于客户请求执行Servlet时,因为程序逻辑或运行时未考虑到的错误而产生异常,这称之为Client Request Time Processing Errors

如何在JSP运行时判别错误发生的种类?如果错误报告页面出现"....encountered an internal error....",就有可能是转换时期错误,或是"Generated servlet error: [javac] Compiling 1 source file....",就有可能是编译器在编译Servlet程序码时发现错误,这个时候您必须检查一下JSP语法是否有错误,或是程序逻辑有明显可让编译器检查出的错误。

什么是程序逻辑有明显让编译器检查出的错误?一个初学者较常犯但不容易检查出的错误可能是“多余的断行”,例如:

  • errorDemo.jsp
 <%@page contentType="charset=Big5" 
errorPage="errorHandler.jsp"%>
<%
throw new Exception("这是一个假装的错误,纯綷丢出异常");
%>


这个JSP程序乍看之下没有错误,程序只是丢出一个异常而已,但注意到它最底下空了一行,在转换为Servlet之后,这一行会实际转换为 out.write('\r');,而在这行之前,由于直接丢出了一个异常,换句话说,out.write('\r');这行永远不会被执行到,这个逻辑 错误,编译器是可以检查的出的,因而错误页面会回报"unreachable statement",改正这个错误的方式,是将JSP页面中多余的断行删掉。

如果编译过后的Servlet在使用者请求之后,在运行过程中产生了错误而丢出异常,这个异常如果没有被处理,则最后会由容器处理,而容器再将讯息交由Server传回给客户端,基本上也是会出现"....encountered an internal error....",不过在回报页面中还会出现异常的堆追踪讯息,依此您可以判断应该是Client Request Time Processing Errors

您也可以自订异常发生时的处理方式,只要使用page指令元素时,设定属性errorPage指定错误处理的JSP页面,而错误处理的JSP页面则设定 isErrorPage属性为true即可,例如示范页面errorDemo.jsp是:

  • errorDemo.jsp
<%@page contentType="charset=Big5"  
errorPage="errorHandler.jsp"%>
<%
throw new Exception("这是一个假装的错误,纯綷丢出异常");
%>

这个页面只是纯綷丢出一个我们自订的异常,注意我们设定异常的处理页面是errorHandler.jsp,它的内容是:
  • errorHandler.jsp
<%@page contentType="text/html;charset=Big5" 
isErrorPage="true"%>
<%@page import="java.io.PrintWriter"%>
<html>
<head><title>错误处理页面</title></head>
<body>
<H1>网页发生错误:</H1><%=exception%>
<H2>显示异常堆追踪:</H2>
<%
exception.printStackTrace(new PrintWriter(out));
%>
</body>
</html>

exception对象是JSP的隐含对象,由errorDemo.jsp丢出的异常对象讯息就包括在exception之中,您先简单的显示 toString()之后的讯息,也就是<%=exception%>显示的内容;另外您也可以将异常堆追踪显示出来, printStackTrace()接受一个PrintWriter对象作为参数,所以您将out隐含对象(它是JspWriter)装饰为 PrintWriter对象,如此使用exception的printStackTrace()方法来显示异常堆追踪。