- @ControllerAdvice 注解定义全局异常处理类
@ControllerAdvice public class GlobalExceptionHandler { }
- @ExceptionHandler 注解声明异常处理方法
方法handleException()会处理所有Controller层抛出的Exception及其子类的异常,Controller层就不需要单独处理异常了。@ControllerAdvice public class GlobalExceptionHandler{ @ExceptionHandler(Exception.class) @ResponseBody public String handleException() { ex.printStackTrace(); return "fail"; } }
但如上代码只能处理 Controller 层的异常,对于未进入Controller的异常,如Interceptor(拦截器)层的异常,Spring 框架层的异常无效,还是会将错误直接返回给用户。对此,只需要在配置文件中添加:spring.mvc.throw-exception-if-no-handler-found=true spring.resources.add-mappings=false
- 被 @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 层也不需要在手动记录异常日志了。