使用@ControllerAdvice + @ExceptionHandler建立全局异常拦截

  1. @ControllerAdvice 注解定义全局异常处理类
    @ControllerAdvice
    public class GlobalExceptionHandler {
    }
    
  2. @ExceptionHandler 注解声明异常处理方法
    @ControllerAdvice
    public class GlobalExceptionHandler{
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public String handleException() {
            ex.printStackTrace(); 
            return "fail";
        }
    }
    
    方法handleException()会处理所有Controller层抛出的Exception及其子类的异常,Controller层就不需要单独处理异常了。
    但如上代码只能处理 Controller 层的异常,对于未进入Controller的异常,如Interceptor(拦截器)层的异常,Spring 框架层的异常无效,还是会将错误直接返回给用户。对此,只需要在配置文件中添加:
    spring.mvc.throw-exception-if-no-handler-found=true
    spring.resources.add-mappings=false
    
  3. 被 @ExceptionHandler 注解的方法还可以声明很多种参数类型,具体可以参考文档:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html
    这里我选择了httpServletRequest, HttpServletResponse httpServletResponse, Exception ex三个参数,应用如下:
    @ControllerAdvice
    public class GlobalExceptionHandler{
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public CommonReturnType handleException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Exception ex) {
            ex.printStackTrace(); // 线上环境替换为对应的log
            Map<String,Object> responseData = new HashMap<>();
            if( ex instanceof BusinessException){
                BusinessException businessException = (BusinessException)ex;
                responseData.put("errCode",businessException.getErrCode());
                responseData.put("errMsg",businessException.getErrMsg());
            }else if(ex instanceof ServletRequestBindingException){
                responseData.put("errCode",BusinessError.UNKNOWN_ERROR.getErrCode());
                responseData.put("errMsg","url绑定路由问题");
            }else if(ex instanceof NoHandlerFoundException){
                responseData.put("errCode",BusinessError.UNKNOWN_ERROR.getErrCode());
                responseData.put("errMsg","没有找到对应的访问路径");
            }else{
                responseData.put("errCode", BusinessError.UNKNOWN_ERROR.getErrCode());
                responseData.put("errMsg", BusinessError.UNKNOWN_ERROR.getErrMsg());
            }
            return CommonReturnType.create(responseData,"fail");
        }
    }
    

如此,所有的 Controller 层的异常日志都可以通过GlobalExceptionHandler 记录。Controller 层也不需要在手动记录异常日志了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章