SpringMVC统一异常处理
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;
}
}