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;
  }


}
posted @ 2018-03-06 17:40  Mr-blue  阅读(1468)  评论(0编辑  收藏  举报