Spring 統一異常處理有 3 種方式,分別爲:java
使用該註解有一個很差的地方就是:進行異常處理的方法必須與出錯的方法在同一個Controller裏面。使用以下:web
1 @Controller 2 public class GlobalController { 3 4 /** 5 * 用於處理異常的 6 * @return 7 */ 8 @ExceptionHandler({MyException.class}) 9 public String exception(MyException e) { 10 System.out.println(e.getMessage()); 11 e.printStackTrace(); 12 return "exception"; 13 } 14 15 @RequestMapping("test") 16 public void test() { 17 throw new MyException("出錯了!"); 18 } 19 }
能夠看到,這種方式最大的缺陷就是不能全局控制異常。每一個類都要寫一遍。spring
這種方式能夠進行全局的異常控制。例如:json
1 @Component 2 public class ExceptionTest implements HandlerExceptionResolver{ 3 4 /** 5 * TODO 簡單描述該方法的實現功能(可選). 6 * @see org.springframework.web.servlet.HandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception) 7 */ 8 public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, 9 Exception ex) { 10 System.out.println("This is exception handler method!"); 11 return null; 12 } 13 }
上文說到 @ ExceptionHandler 須要進行異常處理的方法必須與出錯的方法在同一個Controller裏面。那麼當代碼加入了 @ControllerAdvice,則不須要必須在同一個 controller 中了。這也是 Spring 3.2 帶來的新特性。從名字上能夠看出大致意思是控制器加強。 也就是說,@controlleradvice + @ ExceptionHandler 也能夠實現全局的異常捕捉。app
請確保此WebExceptionHandle 類能被掃描到並裝載進 Spring 容器中。spa
1 @ControllerAdvice 2 @ResponseBody 3 public class WebExceptionHandle { 4 private static Logger logger = LoggerFactory.getLogger(WebExceptionHandle.class); 5 /** 6 * 400 - Bad Request 7 */ 8 @ResponseStatus(HttpStatus.BAD_REQUEST) 9 @ExceptionHandler(HttpMessageNotReadableException.class) 10 public ServiceResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException e) { 11 logger.error("參數解析失敗", e); 12 return ServiceResponseHandle.failed("could_not_read_json"); 13 } 14 15 /** 16 * 405 - Method Not Allowed 17 */ 18 @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) 19 @ExceptionHandler(HttpRequestMethodNotSupportedException.class) 20 public ServiceResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) { 21 logger.error("不支持當前請求方法", e); 22 return ServiceResponseHandle.failed("request_method_not_supported"); 23 } 24 25 /** 26 * 415 - Unsupported Media Type 27 */ 28 @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE) 29 @ExceptionHandler(HttpMediaTypeNotSupportedException.class) 30 public ServiceResponse handleHttpMediaTypeNotSupportedException(Exception e) { 31 logger.error("不支持當前媒體類型", e); 32 return ServiceResponseHandle.failed("content_type_not_supported"); 33 } 34 35 /** 36 * 500 - Internal Server Error 37 */ 38 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 39 @ExceptionHandler(Exception.class) 40 public ServiceResponse handleException(Exception e) { 41 if (e instanceof BusinessException){ 42 return ServiceResponseHandle.failed("BUSINESS_ERROR", e.getMessage()); 43 } 44 45 logger.error("服務運行異常", e); 46 e.printStackTrace(); 47 return ServiceResponseHandle.failed("server_error"); 48 } 49 }
若是 @ExceptionHandler 註解中未聲明要處理的異常類型,則默認爲參數列表中的異常類型。因此還能夠寫成這樣:.net
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler() @ResponseBody String handleException(Exception e){ return "Exception Deal! " + e.getMessage(); } }
參數對象就是 Controller 層拋出的異常對象!code
繼承 ResponseEntityExceptionHandler 類來實現針對 Rest 接口 的全局異常捕獲,而且能夠返回自定義格式:server
1 @Slf4j 2 @ControllerAdvice 3 public class ExceptionHandlerBean extends ResponseEntityExceptionHandler { 4 5 /** 6 * 數據找不到異常 7 * @param ex 8 * @param request 9 * @return 10 * @throws IOException 11 */ 12 @ExceptionHandler({DataNotFoundException.class}) 13 public ResponseEntity<Object> handleDataNotFoundException(RuntimeException ex, WebRequest request) throws IOException { 14 return getResponseEntity(ex,request,ReturnStatusCode.DataNotFoundException); 15 } 16 17 /** 18 * 根據各類異常構建 ResponseEntity 實體. 服務於以上各類異常 19 * @param ex 20 * @param request 21 * @param specificException 22 * @return 23 */ 24 private ResponseEntity<Object> getResponseEntity(RuntimeException ex, WebRequest request, ReturnStatusCode specificException) { 25 26 ReturnTemplate returnTemplate = new ReturnTemplate(); 27 returnTemplate.setStatusCode(specificException); 28 returnTemplate.setErrorMsg(ex.getMessage()); 29 30 return handleExceptionInternal(ex, returnTemplate, 31 new HttpHeaders(), HttpStatus.OK, request); 32 } 33 34 }
以上就是 Spring 處理程序統一異常的三種方式。對象