前言
今天在使用@ControllerAdvice
进行统一异常处理类时,没有起作用。先贴一下异常处理类的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package com.fxt.common.exception; @Slf4j
@RestControllerAdvice public class GlobalExceptionAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class) public R validHander(MethodArgumentNotValidException e){ log.error("异常信息{},异常类:{}",e.getMessage(),e.getClass()); BindingResult result = e.getBindingResult(); Map<String,Object> resMap = new HashMap<>(10); if (result.hasErrors()) { result.getFieldErrors().forEach(fieldError -> { resMap.put("字段:"+fieldError.getField(),"异常:"+fieldError.getDefaultMessage()); }); } return R.error(ExceptionCodeEnum.VAILID.getCode(),ExceptionCodeEnum.VAILID.getMessage()).put("data",resMap); } }
|
过程
在发现统一异常处理类不起作用后,开始寻找原因,一开始以为是@RestControllerAdvice
注解的使用方法不对造成的,但百度了一波发现,并没有任何问题。
因为我的异常处理类是单独放在了公共服务中common
下,所以我将这个异常处理类,放到业务服务下进行测试。使用==Postman==进行测试返回如下
根据结果来看,放在业务服务下,异常处理类好用的,但放在公共服务时却不好用,当时就很疑惑
就在我疑惑中瞎点代码时候,有个重大发现 如下图:
以上两图比对,会发现画红框的地方异常处理类的地方缺少一个小图标,那个图标意思是 该类注册到了Spring 容器中;使用 @Component将类中注册到Spring 容器后的就会出现这个小图标。因为 SpringBoot 本身在启动类上会使用 @SpringBootApplication 进行标注这是个启动类,并且会扫描启动类所在路径下的所有组件信息。@SpringBootApplication 源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Inherited @SpringBootConfiguration @EnableAutoConfiguration
@ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { @AliasFor( annotation = EnableAutoConfiguration.class ) Class<?>[] exclude() default {}; }
|
发现以上问题后,查找我的项目发现,我的统一异常处理类所在路径和业务服务启动类所在的路径不同,导致当业务服务启动时没有扫描到,统一异常类才会出现 @RestControllerAdvice
的不起作用;路径如下图
解决
两种方法解决:
- 将统一异常处理类的层级改成跟业务服务一样,都改成
com.fxt.mall.xxxxx
(推荐此方法)
- 在启动类上定义扫描包的路径
1 2 3 4 5 6 7 8 9 10 11 12
| @SpringBootApplication(scanBasePackages = {"com.fxt.mall","com.fxt.common"}) @MapperScan("com.fxt.mall.product.dao") @EnableDiscoveryClient @EnableFeignClients public class SmallMallProductApplication {
public static void main(String[] args) { SpringApplication.run(SmallMallProductApplication.class, args); }
}
|
一个在码农道路上孤独行走的人
微信搜索【Java猿记】