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拦截即可。