preface
It doesn’t work today when using @ControllerAdvice for a unified exception handling class. First post the code for the exception handling class
package com.fxt.common.exception;
@Slf4j
// The new annotation used here is equivalent to a combination of @controllerAdvice and @@responseBody.
@RestControllerAdvice
public class GlobalExceptionAdvice {
/** * Check failure exception processing *@paramE Exception class *@return com.fxt.common.utils.R
* @author fuxintong
* @date2021/1/26 therefore * /
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R validHander(MethodArgumentNotValidException e){
log.error("Exception information {}, exception class: {}",e.getMessage(),e.getClass());
BindingResult result = e.getBindingResult();
Map<String,Object> resMap = new HashMap<>(10);
if (result.hasErrors()) {
result.getFieldErrors().forEach(fieldError -> {
resMap.put("Field."+fieldError.getField(),"Exception:"+fieldError.getDefaultMessage());
});
}
return R.error(ExceptionCodeEnum.VAILID.getCode(),ExceptionCodeEnum.VAILID.getMessage()).put("data",resMap); }}Copy the code
process
After discovering that the unified exception handling class didn’t work, I started to look for the reason. At first, I thought it was because the @RestControllerAdvice annotation was not used properly, but baidu found that there was nothing wrong.
Since my exception handling class is placed separately under common in the public service, I put this exception handling class under the business service for testing. A test using ==Postman== returns the following
Based on the results, the exception handling class works well in business services, but not in public services, which was confusing at the time
Just as I was messing around with the code, I made an important discoveryThe diagram below:
The exception handler class is missing a small icon in the red box. That icon means that the class is registered with the Spring container. This little icon appears when a class is registered with the Spring container using @Component. Because SpringBoot itself is going to annotate the boot class with @SpringBootApplication which is a boot class, and it’s going to scan all the components that are in the path of the boot class. The source code for @springBootApplication is as follows:
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
// Scan all components in the startup classpath.
@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 {};
}
Copy the code
After discovering the above problem, I searched my project and found that the path of my unified exception handling class is different from the path of the service startup class. As a result, when the service is not detected, the unified exception class @RestControllerAdvice will not work. The path is shown below.
To solve
There are two solutions:
- Change the hierarchy of the unified exception handling class to the same as the business service, both
com.fxt.mall.xxxxx
(Recommended) - Define the path to scan packages on the startup class
// Here is the path of the packet to scan
@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); }}Copy the code
A lone walker on a yard road
Wechat search “Java Ape”