小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
前面我们提到了代码工程的分层,传统的MVC分层和现在流行的DDD领域模型分层,我们对外暴露的都是一些接口API或者REST http接口服务,接口线程调用的过程种可能会出现各种各样的异常,比如说数据库异常, Redis缓存异常, 第三服务接口调用异常等等。
这些异常如何处理呢? 常见的作法主要有三种, 1. 在入口controller或者facade层,写try catch捕获代码里面的异常,封装不同的错误码 2. 通过拦截器AOP自己封装异常拦截的切面 3. 利用Spring 框架提供的异常处理的方法。
本文主要介绍一下Spring框架提供的异常处理方法
Spring统一异常处理
2.1 @ExceptionHandler
Spring的@ExceptionHandler可以用来统一处理方法抛出的异常,@ExceptionHandler注解中可以添加参数,参数是某个异常类的class,代表这个方法专门处理该类异常, 比如下面就是专门处理nacos异常的处理的方法。
@ExceptionHandler(NacosException.class)
public ResponseEntity<String> handleNacosException(NacosException ex) throws IOException {
MetricsMonitor.getNacosException().increment();
return ResponseEntity.status(ex.getErrCode()).body(ExceptionUtil.getAllExceptionMsg(ex));
}
2.2 实现 HandlerExceptionResolver 接口
可以通过不同的错误类型跳转到不同的页面,
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
return null;
}
}
2.3 @ControllerAdvice+@ExceptionHandler
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgumentException(Exception ex) throws IOException {
MetricsMonitor.getIllegalArgumentException().increment();
return ResponseEntity.status(400).body(ExceptionUtil.getAllExceptionMsg(ex));
}
@ExceptionHandler(NacosException.class)
public ResponseEntity<String> handleNacosException(NacosException ex) throws IOException {
MetricsMonitor.getNacosException().increment();
return ResponseEntity.status(ex.getErrCode()).body(ExceptionUtil.getAllExceptionMsg(ex));
}
}
最后
Spring异常处理比较,主要从三个方面比较
3.1. 优先级
@Controller+@ExceptionHandler优先级最高, 其次是@ControllerAdvice+@ExceptionHandler 最最后是HandlerExceptionResolver,三种方式并存的情况 优先级越高的越先选择,而且被一个捕获处理了就不去执行其他的.
3.2. 返回值类型
@Controller+@ExceptionHandler 和 @ControllerAdvice+@ExceptionHandler 两种异常处理方式使用Spring支持的@ResponseBody、ResponseEntity返回。 HandlerExceptionResolver方法声明返回值类型只能是 ModelAndView,如果需要返回JSON、xml等需要自己实现.
3.3. 缓存
@Controller+@ExceptionHandler 和 @ControllerAdvice+@ExceptionHandler缓存信息ExceptionHandlerExceptionResolver的exceptionHandlerAdviceCache中。 HandlerExceptionResolver接口不缓存。