spring mvc 異常處理(轉)
連結:http://gaojiewyh.iteye.com/blog/1297746 (附原始碼)
連結:http://zywang.iteye.com/blog/983801
連結:http://www.cnblogs.com/xguo/p/3163519.html
連結:http://fuliang.iteye.com/blog/947191
連結:http://blog.csdn.net/FansUnion/article/details/17038103
連結:http://cgs1999.iteye.com/blog/1547197(附原始碼)
Spring3.0對異常的處理通過HandlerExceptionResolver來實現。HandlerExceptionResolver有4個實現類DefaultHandlerExceptionResolver、AnnotationMethodExceptionResolver、ResponseStatusExceptionResolver、SimpleMappingExceptionResolver。
Spring3.0對異常的處理主要可通過這兩種方式:一種是使用HandlerExceptionResolver介面;一種是在@Controller處理器內部使用@ExceptionHandler註解。使用第一種方式可以實現全域性異常控制,並且Spring已經提供了一個預設的實現類SimpleMappingExceptionResolver;使用第二種方式可以在Controller內部實現更個性化異常處理方式。
---方式一:HandlerExceptionResolver介面,複寫resolveException()方法
springmvc通過HandlerExceptionResolver處理程式的異常,該介面僅有一個方法ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)。我們可複寫該方法實現全域性異常的處理。
當發生異常時,springmvc會呼叫resolveException()方法,並返回一個ModelAndView物件。如果該方法返回了null,Spring會搜尋所有註冊在其環境中的實現了HandlerExceptionResolver介面的Bean,逐個執行,直到返回一個ModelAndView物件,最後轉到ModelAndView對應的檢視作為一個異常報告頁面!
- /**
- * 基於HandlerExceptionResolver介面的異常處理類
- * 這個類必須宣告到Spring中去,讓Spring管理它,你可以使用@Component標籤:
- * <context:component-scan base-package="test.*" />
- * 或者使用在配置檔案通過<bean/>節點配置:
- * <bean id="exceptionResolver" class="test.CustomExceptionHandler "/>
- */
- @Component
- public class CustomExceptionHandler implements HandlerExceptionResolver {
- @Override
- public ModelAndView resolveException(HttpServletRequest request,
- HttpServletResponse response, Object object, Exception exception) {
- if(exception instanceof IOException){
- return new ModelAndView("ioexp");
- }else if(exception instanceof SQLException){
- return new ModelAndView("sqlexp");
- }
- return null;
- }
- }
---區分ajax請求和普通http請求進行異常處理返回:
- /**
- * 程式碼2:
- * 說明:當在系統應用中出現普通異常時,根據是系統異常還是應用異常,跳到相應的介面,
- * 當ajax異常時,在ajax的error中可直接獲得異常。普通的異常我們都配置好了介面,系統會自動跳轉。
- */
- public class CustomSimpleMappingExceptionResolver extends SimpleMappingExceptionResolver {
- @Override
- protected ModelAndView doResolveException(HttpServletRequest request,
- HttpServletResponse response, Object handler, Exception ex) {
- // Expose ModelAndView for chosen error view.
- String viewName = determineViewName(ex, request);
- if (viewName != null) {// JSP格式返回
- if (!(request.getHeader("accept").indexOf("application/json") > -1 || (request
- .getHeader("X-Requested-With")!= null && request
- .getHeader("X-Requested-With").indexOf("XMLHttpRequest") > -1))) {
- // 如果不是非同步請求
- // Apply HTTP status code for error views, if specified.
- // Only apply it if we're processing a top-level request.
- Integer statusCode = determineStatusCode(request, viewName);
- if (statusCode != null) {
- applyStatusCodeIfPossible(request, response, statusCode);
- }
- return getModelAndView(viewName, ex, request);
- } else {// JSON格式返回
- try {
- PrintWriter writer = response.getWriter();
- writer.write(ex.getMessage());
- writer.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- } else {
- return null;
- }
- }
- }
---方式二:@ExceptionHandler
AnnotationMethodExceptionResolver:springmvc也預設配置了AnnotationMethodExceptionResolver,它允許通過@ExceptionHandler指定處理特定異常的方法。@ExceptionHandler:處理同一個類內觸發的區域性異常(如果要讓其處理多個需攔截異常的處理器,則可另其他類繼承此類!)
- @Controller
- //可以被其他處理器繼承
- public class MyExceptionFilter {
- ...
- //該處理器類中的所有方法丟擲的異常都可由此方法捕獲並處理
- //該註解也可制定多個異常類,如@ExceptionHandler(value={IOException.class,SQLException.class})
- @ExceptionHandler(Exception.class)
- public String handleException(Exception e, HttpServletRequest req) {
- System.out.println("exception name: " + e.getClass().toString());//異常名
- System.out.println("exception cause: " + e.getCause());
- System.out.println("exception msg: " + e.getLocalizedMessage());
- //e.printStackTrace();
- StackTraceElement[] ste = e.getStackTrace();
- StringBuffer sb_e = new StringBuffer();
- for(int j=0;j<ste.length;j++){
- if(ste[j].toString().contains("xxxx")) {
- sb_e.append(ste[j].toString()+", ");
- }
- }
- System.out.println("Exception detail: ");//異常詳細資訊
- System.out.println(sb_e.toString());
- StringBuffer sbUrl = new StringBuffer();//拼url
- System.out.println("request method: "+req.getMethod());//get,post
- System.out.println("request encode: " + req.getCharacterEncoding());//編碼
- System.out.println("request mapping: "+req.getRequestURL().toString());//請求url方法
- sbUrl.append(req.getRequestURL().toString());
- Enumeration en = req.getParameterNames();//請求引數-值
- for(int i=0; en.hasMoreElements(); i++){
- String arg = en.nextElement().toString();
- if(i==0){
- sbUrl.append("?");
- }else{
- sbUrl.append("&");
- }
- sbUrl.append(arg + "=" + req.getParameterValues(arg)[0]);
- }
- System.out.println("request url: " + sbUrl.toString());
- // if(ex instanceof BusinessException) {
- // return "error-business";
- // }else if(ex instanceof ParameterException) {
- // return "error-parameter";
- // } else {
- // return "error";
- // }
- return "forward:error.jsp";
- }
- }
---方式三:SimpleMappingExceptionResolver
SimpleMappingExceptionResolver:可對全域性異常進行統一處理。
- <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
- <!--設定日誌輸出級別,不定義則預設不輸出警告等錯誤日誌資訊。連結:http://elf8848.iteye.com/blog/875830 -->
- <property name="warnLogCategory" value="WARN" />
- <!-- 預設錯誤頁面,就是不在exceptionMappings指定範圍內 -->
- <property name="defaultErrorView" value="error"></property>
- <!-- 定義需要特殊處理的異常,如當發生IOException異常時跳轉到error/ioexp檢視-->
- <property name="exceptionMappings"><span style="font-family: Arial, Helvetica, sans-serif;"><!—key為異常類,可以是全路徑,錯誤頁面或Controller路徑!會自動跳轉到對應url --></span>
- <props>
- <prop key="IOException">redirect:/login</prop>
- <prop key="java.sql.SQLException">error/sqlexp</prop>
- </props>
- </property>
- </bean>
---方式四:<error-page>
DefaultHandlerExceptionResolver:Springmvc預設裝配了DefaultHandlerExceptionResolver,它會將springmvc的異常轉換成對應的響應狀態碼(500,404等)。對於Unchecked Exception而言,由於程式碼不強制捕獲,往往被忽略,如果執行期產生了Unchecked Exception,而程式碼中又沒有進行相應的捕獲和處理,則我們可能不得不面對尷尬的404、500……等伺服器內部錯誤提示頁面。
我們需要一個全面而有效的異常處理機制。目前大多數伺服器也都支援在web.xml中通過<error-page>(Websphere/Weblogic)或者<error-code>(Tomcat)節點配置特定異常情況的顯示頁面。(springmvc)操作如下:
1.在web.xml中配置響應狀態碼對應的頁面,如:
- <error-page>
- <error-code>500</error-code>
- <location>/WEB-INF/pages/error/500.jsp</location>
- </error-page>
- <!-- 未捕獲的錯誤,同樣可指定其它異常類,或自定義異常類 -->
- <error-page>
- <exception-type>java.lang.Exception</exception-type>
- <location>/uncaughtException</location>
- </error-page>
2. applicationContext.xml中配置
- <!-- 錯誤路徑和錯誤頁面,注意指定viewResolver -->
- <mvc:view-controller path="/404" view-name="404"/>
- <mvc:view-controller path="/500" view-name="500"/>
- <mvc:view-controller path="/uncaughtException" view-name="uncaughtException"/>
附:https://www.google.com.hk/search?newwindow=1&safe=strict&espv=210&es_sm=93&q=error+page%E4%B8%8D%E8%B5%B7%E4%BD%9C%E7%94%A8&revid=601630396&sa=X&ei=ORwOU7K_INKbiQeTjIG4BA&ved=0CIcBENUCKAE&biw=1440&bih=737
---方式五:Spring3.2新註解@ControllerAdvice
連結:http://jinnianshilongnian.iteye.com/blog/1866350
@ControllerAdvice,是spring3.2提供的新註解。會把@ControllerAdvice註解內部使用@ExceptionHandler、@InitBinder、@ModelAttribute註解的方法應用到所有的 @RequestMapping註解的方法(全域性的)
有一次發現springmvc3.2.x的@ControllerAdvice註解不起作用,參考連結http://www.07net01.com/linux/spring3_2_mvc__ControllerAdvice_buqizuoyong_554229_1375786240.html加上@EnableWebMvc後就可以了。但是,後來又發現會導致這個原因是因為專案的springmvc配置檔案中沒有配置<mvc:annotation-driven />,於是將其配置上。但是配置上<mvc:annotation-driven />後問題就來了,啟動的時候就報異常,看了下原因,感覺是@EnableWebMvc註解導致的,於是將該註解刪除掉,果然就正常啟動了。不過,至於其中的原理還是理解不深刻,不知道內部是怎麼呼叫的,只是發現當配置上<mvc:annotation-driven />的時候不應該用@EnableWebMvc修飾@ControllerAdvice。(待研究)附連結:http://hahalq.iteye.com/blog/1738599。http://www.yulezhandian.com/?p=196。
測試後發現,當全域性異常和區域性異常都存在時,全域性異常處理會被區域性異常處理覆蓋。
- /**
- * 全域性異常
- */
- //@EnableWebMvc
- @ControllerAdvice
- public class MyExceptionHandler {
- @ExceptionHandler(Exception.class)
- public String handleException(Exception re, HttpServletRequest request) {
- System.out.println("error.......");
- return "forward:error.jsp";
- }
- }