一 声明式异常处理
在web.xml中对声明对各种异常的处理方法。
通过 <error-page>元素来声明。 此元素的结构如下:
+------<error-code> or <exception-type>
|
<error-page> ----+
|
+------<location>
1 HTTP错误代码的处理
4**代码表示客户端错误:请求有语法错误或者请求无法实现。
例:为404错误指定相应的错误处理页面
在web.xml中
<error-page>
<error-code>404</error-code>
<location>/FileNotFound.html</location>
</error-page>
编写FileNotFound.html
同时 也可以编写一个专门处理HTTP错误代码的HttpErrorHandlerServlet类来进行响应
package servlet;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HttpErrorHandlerServlet extends HttpServlet
{
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException
{
resp.setContentType("text/html;charset=GB2312");
PrintWriter out = resp.getWriter();
Integer status_code=(Integer)req.getAttribute("javax.servlet.error.status_code");
out.println("<html><head><title>错误页面</title></head>");
out.println("<body>");
//如果你的JDK版本低于1.5,那么你应该按照如下方式调用
//int status=status_code.intValue();
//switch(status){…}
switch(status_code)
{
case 401:
break;
case 404:
out.println("<h2>HTTP状态代码:"+status_code+"</h2>");
out.println("你所访问页面并不存在,或者已经被移动到其它位置。");
out.println("
如有其它问题,请<a href=mailto:admin@sunxin.org>联系管理员</a>。");
break;
default:
break;
}
out.println("</body></html>");
out.close();
}
}
重写HttpServlet类的service()方法。调用请求对象getAttribute()方法得到javax.servlet.error.status_code属性的值,当发生HTTP错误的时候,
Servlet容器会自动将HTTP的错误代码作为javax.servlet.error.status_code
属性的值,保存在请求的对象中。
部署好这个servlet。location修改为servlet的location
2 Java异常的处理
例:一个Servlet从文件中读取配置信息,如果文件不存在的,就会抛出java.io.FileNotFoundException异常。
====第一步:FileExceptionServlet.java
package org.sunxin.ch06.servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FileExceptionServlet extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException,IOException
{
FileInputStream fis=new FileInputStream("config.inc");
Properties pps=new Properties();
pps.load(fis);
//读取属性的代码,省略。[nextpage]
fis.close();
}
}
如果找不到config.inc文件,FileExceptionServlet就会抛出java.io.FileNotFoundException异常
========第二步:异常处理Servlet类。ExceptionHandlerServlet.java
package servlet;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ExceptionHandlerServlet2 extends HttpServlet
{
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException
{
resp.setContentType("text/html;charset=GB2312");
PrintWriter out = resp.getWriter();
out.println("<html><head><title>错误页面</title></head>");
out.println("<body>");
String uri=(String)req.getAttribute("javax.servlet.error.request_uri");
Object excep=req.getAttribute("javax.servlet.error.exception");
out.println(uri+" 运行错误。");
out.println("<p>错误原因:"+excep);
out.println("</body></html>");
out.close();
}
}
========第三步:web.xml文件中声明Servlet
<error-page>
<exception-type>java.io.FileNotFoundException</exception-type>
<location>/ExcepHandler</location>
</error-page>
<exception-type>子元素指定了Java异常类的名字
<locaiton>子元素指定了对异常处理的Servlet类
二 程序式异常处理
程序式异常处理就是在Web程序中利用try-catch语句进行捕获异常,并对捕获异常进行响应的处理。
1 在try-catch语句中处理异常
catch(SQLException se)
{
getServletContext()。log("ServletContext.log(): 数据库操作失败!"+
se.toString());
log("GenericServlet.log(): 数据库操作失败!"+se.toString());
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"数据库操作出现问题,请联系管理员。");
}
[1] 捕捉到异常时,分别用ServletContext接口的log()方法和GenericServlet抽象类的log()方法记录数据库操作失败的原因。
区别:
如果调用GenericServlet类的log()方法 它会在日志消息的前面加上Servlet的名字
而调用ServletContext接口的log()方法 则只记录消息本身
这两个log()方法会把日志信息写入到日志文件中。 在tomcat6 产生的日志文件名以及文件存放的位置是
%CATALINA_HOME%logslocalhost.当前日期。log。
[2] 调用响应对象的sendError()方法发送HTTP错误代码,Servlet容器会发送一个包含了这些信息的错误页面到浏览器
2 使用RequestDispatcher来处理异常
产生异常的Servlet
try
{
int a=5;
int b=0;
int c=a/b;
}
catch(ArithmeticException ae)
{
req.setAttribute("javax.servlet.error.exception",ae);
req.setAttribute("javax.servlet.error.request_uri",req.getRequestURI());
RequestDispatcher rd=req.getRequestDispatcher("ExcepHandler2");
rd.forward(req,resp);
}
处理异常的Servlet
package servlet;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ExceptionHandlerServlet2 extends HttpServlet
{
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException
{
resp.setContentType("text/html;charset=GB2312");
PrintWriter out = resp.getWriter();
out.println("<html><head><title>错误页面</title></head>");
out.println("<body>");
String uri=(String)req.getAttribute("javax.servlet.error.request_uri");
Object excep=req.getAttribute("javax.servlet.error.exception");
out.println(uri+" 运行错误。");
out.println("<p>错误原因:"+excep);
out.println("</body></html>");
out.close();
}
}
说明:
[1] 将异常对象和抛出异常的servlet的位置作为HttpServletRequest对象的属性保存到请求对象中。
[2] 通过请求对象的getRequestDispatcher()方法得到RequestDispatcher对象 调用RequestDispatcher对象的forward()方法将请求转发给 ExcepHandler2
[3] ExcepHandler2可以从请求对象中取出javax.servlet.error.exception和javax.servlet.error.request_uri属性