Servlet&JSP的那些事儿(九)

我们难保自己写的程序不会出错,所以需要一些错误处理机制来帮我们更好的解决异常,处理错误。在浏览网页的时候,如果访问的页面不存在,那么会收到一个HTTP 404错误信息。这个问题的发生,可能是因为用户输入了错误的URL,但更多的情况是服务器端的链接出现了错误,页面移动了位置或者删除了,却忘记修改原来的链接。另外一种情况就是,我们开发的web应用程序本身有bug,在运行时出现了异常。

所以,这就要求我们在开发web应用时,对于可能出现的错误或异常,提前做好处理,即使错误不可避免,也应该提供一些友好的信息。在servlet中,有两种服务器处理机制:声明式异常处理(declarative exception handling)和程序式异常处理(programmatic exception handling)。

声明式异常处理

这种异常处理方式是在web.xml文件中声明对各种异常的处理方法。其格式如下:

<?xml version='1.0' encoding='utf-8'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">
	<error-page>
		<error-code>404</error-code>
		<location>/FileNotFound.html</location>
	</error-page>
</web-app>
可以看出来,<error-code>指定HTTP的错误代码,<location>制定了错误出现时的页面路径。还有一种格式如下:

<?xml version='1.0' encoding='utf-8'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">
	<error-page>
		<error-type>java.io.FileNotFoundException</error-type>
		<location>/ExceptionHandle</location>
	</error-page>
</web-app>
其中<error-type>指定了java异常类的完整限定名,而<location>指定了处理异常的处理类(Servlet类)。在上面的那中格式中,<location>也可以这样指定。

HTTP常见的错误代码详见HTTP解析,文章有对HTTP的详细说明。

一个异常处理类的详细代码如下所示:

package com.shan.web;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;


public class HttpErrorHandleServlet extends HttpServlet{
	public void service(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		Integer status_code = (Integer)request.getAttribute("javax.servlet.error.status_code");
		out.println("<html><head><title>");
		out.println("错误页面");
		out.println("</title></head>");
		out.println("<body>");
		switch(status_code) {
		case 401: break;
		case 404:
			out.println("HTTP状态码:"+status_code);
			out.println("您访问的页面不存在,或者已被移动到其他位置。");
			break;
		default:
			break;
		}
		out.println("</body></html>");
		out.close();
	}
}
为了帮助进行错误处理的servlet分析问题,以及生成详细的响应,servlet容器在将请求转发给错误页面之前,会在请求中设置某些有用的属性,如表1所示:

属性的名字 属性的类型 属性说明
javax.servlet.error.status_code java.lang.Integer HTTP协议的状态代码
javax.servlet.error.exception_type java.lang.Class 未捕获异常的Class类的对象
javax.servlet.error.message java.lang.String 传递给sendError()方法的消息,或者是在未捕获异常中的消息
javax.servlet.error.exception java.lang.Throwable 调用错误页面的未捕获异常
javax.servlet.error.request_uri java.lang.String 当前请求的URI
javax.servlet.error.servlet_name java.lang.String 导致错误页面被调用的servlet的名字

表1 servlet容器在请求对象中设置的属性
针对上面错误处理类的完整web.xml配置如下所示:

<?xml version='1.0' encoding='utf-8'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">
	<servlet>
		<servlet-name>HttpErrorHandleServlet</servlet-name>
		<servlet-class>com.shan.web.HttpErrorHandleServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>HttpErrorHandleServlet</servlet-name>
		<url-pattern>/ExceptionHandle</url-pattern>
	</servlet-mapping>

	<error-page>
		<error-code>401</error-code>
		<location>/ExceptionHandle</location>
	</error-page>

	<error-page>
		<error-code>404</error-code>
		<location>/ExceptionHandle</location>
	</error-page>
</web-app>
程序式异常处理

这种异常处理方式利用try-catch来捕获异常,并对捕获的异常进行相应的处理。可在catch块中利用如下语句将异常信息输出到log日志中。

getServletContext().log("ServletContext.log():异常信息"+ex.toString());
log("GenericServlet.log():异常信息"+ex.toString());
这两句话都可以将异常信息记录到log日志中,他们的区别在于:如果调用GenericServlet类的log()方法,它会在日志消息前面加上servlet的名字,而调用ServletContext的log()方法,则只记录消息本身。

也可以使用response的sendError()方法将错误消息发送到错误页面。

利用RequestDispatcher来处理异常

之前介绍过页面转发机制,所以也可以将异常封装到一个请求中,然后利用ServletContext.log()转发一个异常处理servlet进行统一的处理。

转载请注明出处:http://blog.csdn.net/iAm333

你可能感兴趣的:(Servlet&JSP的那些事儿(九))