SpringMVC統一異常處理
在開發中,不管是dao層、service層還是controller層,都有可能拋出異常,在springmvc中,能將所有類型的異常處理從各處理過程解耦出來,既保證了相關處理過程的功能較單一,也實現了異常信息的統一處理和維護。我總結SpringMVC中統一處理異常的兩種常見方式。
使用@ ExceptionHandler 注解
@Controller
public class GlobalController {
/**
* 用於處理異常的
* @return
*/
@ExceptionHandler({MyException.class})
public String exception(MyException e) {
System.out.println(e.getMessage());
e.printStackTrace();
return "exception";
}
@RequestMapping("test")
public void test() {
throw new MyException("出錯了!");
}
}
可以看到,這種方式最大的缺陷就是不能全局控制異常。每個Controller類都要寫一遍。當然還可以通過繼承的方式,進行優化。這樣只需要寫一個父類,其他Controller繼承這個父類。
public class AbstractController {
@ExceptionHandler(BizException.class)
@ResponseBody
public Response<?> handleException(BizException ex) {
log.error(Utils.getExceptionInfo(ex, Utils.KERY_PACKAGE_PRE, 1));
Response response = ex.getResponse();
response.setMessageId(MDCUtils.getMsgId());
return response;
}
@ExceptionHandler(DuplicateKeyException.class)
@ResponseBody
public Response<?> handleException(DuplicateKeyException ex) {
Response<?> response = new Response<>(CodeMessage.DATA_ERROR);
logError(response, ex);
return response;
}
}
使用 @ControllerAdvice 注解
@ControllerAdvice,這是 Spring 3.2 帶來的新特性。 使用@controlleradvice + @ ExceptionHandler 也可以實現全局的異常捕捉。
public class BusinessExceptionControllerAdvice {
private Logger logger = LoggerFactory.getLogger("ErrorFile");
public ResultVO<Object> initResp() {
ResultVO<Object> vo = new ResultVO<>();
vo.setStatus(Status.FAIL.getCode());
vo.setMsg(Status.FAIL.getMessageKey());
return vo;
}
/**
* 業務異常
*
* @param exception
* @return
*/
@ExceptionHandler(BusinessException.class)
@ResponseBody
@ResponseStatus(value = HttpStatus.OK)
public Object businessErrorHandler(BusinessException exception) {
ResultVO<Object> vo = initResp();
vo.setStatus(exception.getErrorCode().getCode());
vo.setMsg(StringUtils.isEmpty(exception.getErrorMsg()) ? exception.getErrorCode().getMsg()
: exception.getErrorMsg());
Object resp = vo.build();
logger.error("Excpetion Handler || Error Response Body: [ {} ]", resp, exception);
return resp;
}
/**
* Spring validation
*
* @param e
* @return
*/
@ExceptionHandler(value = {ConstraintViolationException.class})
@ResponseStatus(value = HttpStatus.OK)
public Object validException(ConstraintViolationException e) {
Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
StringBuilder strBuilder = new StringBuilder();
for (ConstraintViolation<?> violation : violations) {
strBuilder.append(violation.getMessage() + "\n");
}
ResultVO<Object> vo = initResp();
vo.setMsg(strBuilder.toString());
Object resp = vo.build();
logger.error("Excpetion Handler || Error Response Body: [ {} ]", resp, e);
return resp;
}
}
