Web.xml配置Error Page不能够转发的问题分析及解决

1.      web.xml的配置

自定义的异常类

1 <error-page>
2           <exception-type>com.service.Exception.MyException</exception-type>
3           <location>/my_exception.jsp</location>
4 </error-page>

   定义HTTP消息状态码

<error-page>
         <error-code>404</error-code>
         <location>/404.html</location>
</error-page>

2.      出错原因分析

1)  IE将出错页面响应状态码200,告诉浏览器是成功消息,显示该页面,如下:

1 <%
2     response.setStatus(200); // 200 = HttpServletResponse.SC_OK
3 %>

2)  如果是上面的错误相信Google很容易得到,但是对于JSP页面中抛出的异常(RuntimeException),还有可能是如下原因:

a.当通过request分发请求my.jsp页面,my.jsp页面中的某个方法会抛出MyException,代码如下:getRequestDispatcher(“/my.jsp”).forward(request, response);在这里,整个程序执行的流程为:分发dispather时,Tomcat容器会生成一个my.jsp的包装类,实际就是JspServletWrapper通过getServlet方法得到myServlet.java执行service方法,抛出异常,在这里自定义的异常MyException将会被HandleException方法处理,最后抛出JasperException,而不是我们自己定义的异常。如下代码

JspServletWrapper类中:

 

  1  
  2 
  3 servlet = getServlet();
  4 
  5           try {
  6 
  7             /*
  8 
  9              * (3) Service request
 10 
 11              */
 12 
 13             if (servlet instanceof SingleThreadModel) {
 14 
 15                // sync on the wrapper so that the freshness
 16 
 17                // of the page is determined right before servicing
 18 
 19                synchronized (this) {
 20 
 21                    servlet.service(request, response);
 22 
 23                 }
 24 
 25             } else {
 26 
 27 //这里调用my.jsp生成的Servlet.service,执行抛出自定义的异常,最后被catch转换成JasperException
 28 
 29                 servlet.service(request, response);
 30 
 31             }
 32 
 33  
 34 
 35         } catch (UnavailableException ex) {
 36 
 37             String includeRequestUri = (String)
 38 
 39                 request.getAttribute("javax.servlet.include.request_uri");
 40 
 41             if (includeRequestUri != null) {
 42 
 43                 // This file was included. Throw an exception as
 44 
 45                 // a response.sendError() will be ignored by the
 46 
 47                 // servlet engine.
 48 
 49                 throw ex;
 50 
 51             } else {
 52 
 53                 int unavailableSeconds = ex.getUnavailableSeconds();
 54 
 55                 if (unavailableSeconds <= 0) {
 56 
 57                     unavailableSeconds = 60;        // Arbitrary default
 58 
 59                 }
 60 
 61                 available = System.currentTimeMillis() +
 62 
 63                     (unavailableSeconds * 1000L);
 64 
 65                 response.sendError
 66 
 67                     (HttpServletResponse.SC_SERVICE_UNAVAILABLE,
 68 
 69                      ex.getMessage());
 70 
 71             }
 72 
 73         } catch (ServletException ex) {
 74 
 75             if(options.getDevelopment()) {
 76 
 77                 throw handleJspException(ex);
 78 
 79             } else {
 80 
 81                 throw ex;
 82 
 83             }
 84 
 85         } catch (IOException ex) {
 86 
 87             if(options.getDevelopment()) {
 88 
 89                 throw handleJspException(ex);
 90 
 91             } else {
 92 
 93                 throw ex;
 94 
 95             }
 96 
 97         } catch (IllegalStateException ex) {
 98 
 99             if(options.getDevelopment()) {
100 
101                 throw handleJspException(ex);
102 
103             } else {
104 
105                 throw ex;
106 
107             }
108 
109         } catch (Exception ex) {
110 
111             if(options.getDevelopment()) {
112 
113                 throw handleJspException(ex);
114 
115             } else {
116 
117                 throw new JasperException(ex);
118 
119             }
120 
121         }

所以当用Dispather分发页面时,如果页面中有异常抛出,最终将被转换成JasperException,如果通过Web.xml去handle,必须拦截JasperException才能够正确跳转。

b.当通过重定向跳转到my.jsp页面,代码如下,response.sendRedirect(“/my.jsp”)或者直接在浏览器地址栏上输入URL,实际上是JspServlet执行my_jsp.java的service方法,代码片段如下:

 1 try {
 2 
 3             boolean precompile = preCompile(request);
 4 
 5             serviceJspFile(request, response, jspUri, null, precompile);
 6 
 7 //这里对于RuntimeException直接抛出
 8 
 9         } catch (RuntimeException e) {
10 
11             throw e;
12 
13         } catch (ServletException e) {
14 
15             throw e;
16 
17         } catch (IOException e) {
18 
19             throw e;
20 
21         } catch (Throwable e) {
22 
23             throw new ServletException(e);
24 
25         }

3.      解决办法

最后解决办法,是在web.xml中配置对应的Handle自定义的Exception,还需要加如下代码,如下:

 1 try{
 2 
 3 getRequestDispatcher(“/my.jsp”).forward(request, response);
 4 
 5 }catch(Exception e){
 6 
 7 if(e.getCause() instanceof  MyException){
 8 
 9                 response.sendRedirect(“/error.jsp”);
10 
11 }
12 
13 }

如果改为response.sendRedirect(“/my.jsp”),直接在web.xml拦截即可。

posted @ 2012-05-16 21:30  Wbang Ting  阅读(2231)  评论(0编辑  收藏  举报