最近學習Spring時,認識到Spring異常處理的強大。以前處理工程異常,代碼中最多見的就是try-catch-finally,有時一個try,多個catch,覆蓋了核心業務邏輯:html
1 try{ 2 .......... 3 }catch(Exception1 e){ 4 .......... 5 }catch(Exception2 e){ 6 ........... 7 }catch(Exception3 e){ 8 ........... 9 }
Spring可以較好的處理這種問題,核心以下,文章主要關注前兩個:java
源碼以下:spring
1 @Target({ElementType.METHOD}) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 public @interface ExceptionHandler { 5 Class<? extends Throwable>[] value() default {}; 6 }
該註解做用對象爲方法,而且在運行時有效,value()能夠指定異常類。由該註解註釋的方法能夠具備靈活的輸入參數(詳細參見Spring API):api
。
Model
方法返回值能夠爲:spring-mvc
源碼以下:mvc
1 @Target({ElementType.TYPE}) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Component 5 public @interface ControllerAdvice { 6 @AliasFor("basePackages") 7 String[] value() default {}; 8 9 @AliasFor("value") 10 String[] basePackages() default {}; 11 12 Class<?>[] basePackageClasses() default {}; 13 14 Class<?>[] assignableTypes() default {}; 15 16 Class<? extends Annotation>[] annotations() default {}; 17 }
該註解做用對象爲TYPE,包括類、接口和枚舉等,在運行時有效,而且能夠經過Spring掃描爲bean組件。其能夠包含由@ExceptionHandler、@InitBinder 和@ModelAttribute標註的方法,能夠處理多個Controller類,這樣全部控制器的異常能夠在一個地方進行處理。app
異常類:jsp
1 public class CustomGenericException extends RuntimeException{ 2 private static final long serialVersionUID = 1L; 3 4 private String errCode; 5 private String errMsg; 6 7 public String getErrCode() { 8 return errCode; 9 } 10 11 public void setErrCode(String errCode) { 12 this.errCode = errCode; 13 } 14 15 public String getErrMsg() { 16 return errMsg; 17 } 18 19 public void setErrMsg(String errMsg) { 20 this.errMsg = errMsg; 21 } 22 23 public CustomGenericException(String errCode, String errMsg) { 24 this.errCode = errCode; 25 this.errMsg = errMsg; 26 } 27 }
控制器:學習
1 @Controller 2 @RequestMapping("/exception") 3 public class ExceptionController { 4 5 @RequestMapping(value = "/{type}", method = RequestMethod.GET) 6 public ModelAndView getPages(@PathVariable(value = "type") String type) throws Exception{ 7 if ("error".equals(type)) { 8 // 由handleCustomException處理 9 throw new CustomGenericException("E888", "This is custom message"); 10 } else if ("io-error".equals(type)) { 11 // 由handleAllException處理 12 throw new IOException(); 13 } else { 14 return new ModelAndView("index").addObject("msg", type); 15 } 16 } 17 }
異常處理類:測試
1 @ControllerAdvice 2 public class ExceptionsHandler { 3 4 @ExceptionHandler(CustomGenericException.class)//能夠直接寫@ExceptionHandler,不指明異常類,會自動映射 5 public ModelAndView customGenericExceptionHnadler(CustomGenericException exception){ //還能夠聲明接收其餘任意參數 6 ModelAndView modelAndView = new ModelAndView("generic_error"); 7 modelAndView.addObject("errCode",exception.getErrCode()); 8 modelAndView.addObject("errMsg",exception.getErrMsg()); 9 return modelAndView; 10 } 11 12 @ExceptionHandler(Exception.class)//能夠直接寫@EceptionHandler,IOExeption繼承於Exception 13 public ModelAndView allExceptionHandler(Exception exception){ 14 ModelAndView modelAndView = new ModelAndView("generic_error"); 15 modelAndView.addObject("errMsg", "this is Exception.class"); 16 return modelAndView; 17 } 18 }
JSP頁面:
正常頁面index.jsp:
1 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 2 <html> 3 <body> 4 <h2>Spring MVC @ExceptionHandler Example</h2> 5 6 <c:if test="${not empty msg}"> 7 <h2>${msg}</h2> 8 </c:if> 9 10 </body> 11 </html>
異常處理頁面generic_error.jsp
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <body> <c:if test="${not empty errCode}"> <h1>${errCode} : System Errors</h1> </c:if> <c:if test="${empty errCode}"> <h1>System Errors</h1> </c:if> <c:if test="${not empty errMsg}"> <h2>${errMsg}</h2> </c:if> </body> </html>
測試運行以下:
正常狀況:
CustomGenericException異常狀況:
IOException異常狀況: