满屏的try-catch,不瘆得慌?( 二 )


  1. 新建一个统一异常处理的一个类
  2. 类上标注@RestControllerAdvice这一个注解 , 或者同时标注@ControllerAdvice和@ResponseBody这两个注解 。
  3. 在方法上标注@ExceptionHandler注解 , 并且指定需要捕获的异常 , 可以同时捕获多个 。
下面是作者随便配置一个demo , 如下:
/** * 全局统一的异常处理 , 简单的配置下 , 根据自己的业务要求详细配置 */@RestControllerAdvice@Slf4jpublic class GlobalExceptionHandler {/*** 重复请求的异常* @param ex* @return*/@ExceptionHandler(RepeatSubmitException.class)public ResultResponse onException(RepeatSubmitException ex){//打印日志log.error(ex.getMessage());//todo 日志入库等等操作//统一结果返回return new ResultResponse(ResultCodeEnum.CODE_NOT_REPEAT_SUBMIT);}/*** 自定义的业务上的异常*/@ExceptionHandler(ServiceException.class)public ResultResponse onException(ServiceException ex){//打印日志log.error(ex.getMessage());//todo 日志入库等等操作//统一结果返回return new ResultResponse(ResultCodeEnum.CODE_SERVICE_FAIL);}/*** 捕获一些进入controller之前的异常 , 有些4xx的状态码统一设置为200* @param ex* @return*/@ExceptionHandler({HttpRequestMethodNotSupportedException.class,HttpMediaTypeNotSupportedException.class, HttpMediaTypeNotAcceptableException.class,MissingPathVariableException.class, MissingServletRequestParameterException.class,ServletRequestBindingException.class, ConversionNotSupportedException.class,TypeMismatchException.class, HttpMessageNotReadableException.class,HttpMessageNotWritableException.class,MissingServletRequestPartException.class, BindException.class,NoHandlerFoundException.class, AsyncRequestTimeoutException.class})public ResultResponse onException(Exception ex){//打印日志log.error(ex.getMessage());//todo 日志入库等等操作//统一结果返回return new ResultResponse(ResultCodeEnum.CODE_FAIL);}}注意:上面的只是一个例子 , 实际开发中还有许多的异常需要捕获 , 比如TOKEN失效、过期等等异常 , 如果整合了其他的框架 , 还要注意这些框架抛出的异常 , 比如Shiro , Spring Security等等框架 。
异常匹配的顺序是什么?有些朋友可能疑惑了 , 如果我同时捕获了父类和子类 , 那么到底能够被哪个异常处理器捕获呢?比如Exception和ServiceException 。
满屏的try-catch,不瘆得慌?文章插图
此时可能就疑惑了 , 这里先揭晓一下答案 , 当然是ServiceException的异常处理器捕获了 , 精确匹配 , 如果没有ServiceException的异常处理器才会轮到它的父亲 , 父亲没有才会到祖父 。 总之一句话 , 精准匹配 , 找那个关系最近的 。
为什么呢?这可不是凭空瞎说的 , 源码为证 , 出处org.springframework.web.method.annotation.ExceptionHandlerMethodResolver#getMappedMethod , 如下:
@Nullable private Method getMappedMethod(Class exceptionType) {List> matches = new ArrayList<>();//遍历异常处理器中定义的异常类型for (Class mappedException : this.mappedMethods.keySet()) {//是否是抛出异常的父类 , 如果是添加到集合中if (mappedException.isAssignableFrom(exceptionType)) {//添加到集合中matches.add(mappedException);}}//如果集合不为空 , 则按照规则进行排序if (!matches.isEmpty()) {matches.sort(new ExceptionDepthComparator(exceptionType));//取第一个return this.mappedMethods.get(matches.get(0));}else {return null;} }


推荐阅读