SpringWeb工程统一异常处理方法

699 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

前面我们提到了代码工程的分层,传统的MVC分层和现在流行的DDD领域模型分层,我们对外暴露的都是一些接口API或者REST http接口服务,接口线程调用的过程种可能会出现各种各样的异常,比如说数据库异常, Redis缓存异常, 第三服务接口调用异常等等。

这些异常如何处理呢? 常见的作法主要有三种, 1. 在入口controller或者facade层,写try catch捕获代码里面的异常,封装不同的错误码 2. 通过拦截器AOP自己封装异常拦截的切面 3. 利用Spring 框架提供的异常处理的方法。

Spring统一异常处理.png

本文主要介绍一下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接口不缓存。