前面學習過struts2的異常處理,今天來看下spring mvc4的異常處理:
一、Servlet配置文件修改
1 <bean id="exceptionResolver" 2 class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 3 <property name="defaultErrorView" value="errors/error" /> 4 <property name="exceptionMappings"> 5 <props> 6 <prop key="java.lang.Throwable">errors/error</prop> 7 </props> 8 </property> 9 </bean>
增加上面這一節,大意是:只要有異常就跳到/WEB-INF/views/errors/error.jsp這個頁面,當然如果要實現個性化的錯誤處理,比如:業務錯誤跳到頁面A,SQL錯誤跳到頁面B...,直接在props節點下,根據不同的異常類型,自行擴充 (注:404之類的錯誤,仍然參考struts2異常處理中的做法,在web.xml中配置解決)
二、創建一個BaseController基類,里面放一個以下方法:
1 @ExceptionHandler 2 public String exp(HttpServletRequest request, Exception ex) { 3 String resultViewName = "errors/error"; 4 5 // 記錄日志 6 logger.error(ex.getMessage(), ex); 7 8 // 根據不同錯誤轉向不同頁面 9 if (ex instanceof BusinessException) { 10 resultViewName = "errors/biz-error"; 11 } else { 12 // 異常轉換 13 ex = new Exception("系統太累了,需要休息!"); 14 } 15 request.setAttribute("ex", ex); 16 return resultViewName; 17 }
記錄異常日志、根據不同的異常類型轉到不同的處理頁面、友好異常轉換(如果需要的話),都在上面的方法中處理了
三、所有Controller都繼承自BaseController
這個,就不解釋了
四、error.jsp頁面
1 <%@ page contentType="text/html;charset=UTF-8" language="java"%> 2 <% 3 Exception e = (Exception) request.getAttribute("ex"); 4 %> 5 <html> 6 <head> 7 <title>師傅,有妖怪:error</title> 8 </head> 9 <body> 10 <H2> 11 錯誤:<%=e.getClass().getSimpleName()%></H2> 12 <hr /> 13 <P> 14 <strong>錯誤描述:</strong><%=e.getMessage()%> 15 </P> 16 17 <P> 18 <strong>詳細信息:</strong> 19 </P> 20 <pre> 21 <% 22 e.printStackTrace(new java.io.PrintWriter(out)); 23 %> 24 </pre> 25 </body> 26 </html>
上面的內容只是示意,大家可以根據需要自行美化
另:前文struts2的異常處理中,采用的是攔截器思想,spring mvc中也有攔截器,而且攔截的點更靈活:
1 package com.cnblogs.yjmyzz.interceptor; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 6 import org.apache.logging.log4j.LogManager; 7 import org.apache.logging.log4j.Logger; 8 import org.springframework.web.servlet.ModelAndView; 9 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 10 11 public class ExcpetionInterceptor extends HandlerInterceptorAdapter { 12 13 protected Logger logger = LogManager.getLogger(); 14 15 @Override 16 public boolean preHandle(HttpServletRequest request, 17 HttpServletResponse response, Object handler) throws Exception { 18 System.out.println("ExcpetionInterceptor.preHandle"); 19 // 演示:限制僅允許從本機訪問 20 if (request.getLocalAddr().equals("127.0.0.1") 21 || request.getLocalAddr().equals("0.0.0.0")) { 22 return true; 23 } 24 logger.error("非法入侵:" + request.getLocalAddr()); 25 return false; 26 } 27 28 @Override 29 public void postHandle(HttpServletRequest request, 30 HttpServletResponse response, Object handler, 31 ModelAndView modelAndView) throws Exception { 32 System.out.println("ExcpetionInterceptor.postHandle"); 33 } 34 35 @Override 36 public void afterCompletion(HttpServletRequest request, 37 HttpServletResponse response, Object handler, Exception ex) 38 throws Exception { 39 System.out.println("ExcpetionInterceptor.afterCompletion"); 40 if (ex != null) { 41 logger.error(handler); 42 logger.error(ex.getMessage(), ex); 43 } 44 } 45 46 @Override 47 public void afterConcurrentHandlingStarted(HttpServletRequest request, 48 HttpServletResponse response, Object handler) throws Exception { 49 System.out 50 .println("ExcpetionInterceptor.afterConcurrentHandlingStarted"); 51 } 52 53 }
攔截器創建后,依然要在servlet配置文件中注冊:
<mvc:interceptors> <bean class="com.cnblogs.yjmyzz.interceptor.ExcpetionInterceptor"></bean> </mvc:interceptors>
spring mvc的攔截器提供了4個處理方法:
preHandle在Controller被調用前,先執行,可以在這里執行一些安全檢查(上面示意了如何對IP做限制)
postHandle在Controller調用后執行,這時,可以修改ModelAndView,比如轉到其它view之類
afterCompletion在Controller調用全部完成后執行,如果ex變量不為空,表示有異常了,這里可以記錄異常日志
afterConcurrentHandlingStarted這個沒怎么研究過,暫時不做評價
值得一提的是:spring-mvc中的攔截器,雖然可以在afterCompletion中記錄異常日志,但如果按前面的baseController配合@ExceptionHandler做了處理,這里的ex就變成了null,因為異常在前面已經得到了處理,所以這二種方法不推薦混用,另外afterCompletion方法中,如果要根據不同的異常類型轉到不同處理頁面,并不方便。
附:ajax的統一異常處理,請移步 Struts2、Spring MVC4 框架下的ajax統一異常處理
文章列表