“This article has participated in the call for good writing activities, click to view: the back end, the big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!”

preface

You can guess from the title that I’m not analyzing SpringBoot autoloader from a source code perspective. It’s boring to analyze the source code again, it’s very troublesome to write an article, and it’s even more troublesome to write an article that many people have written (but I still recommend understanding the principle first, and then looking for the opportunity to apply it to the project).

What I want to record is that I inadvertently used SpringBoot automatic assembly in the project and made a practical case of SpringBoot automatic assembly.

Let’s talk about the background of this “unintentional” incident. As a back end programmer, regarding the interface into the field calibration of the is the norm, so comments @ NotNull is commonly used for calibration is not empty, the field is empty throws MethodArgumentNotValidException is unusual, is the following a long list.

{
	"timestamp": "The 2021-07-02 T02: kindred. 868 + 0000"."status": 400."error": "Bad Request"."errors": [{"codes": [
				"NotNull.loginDTO.password"."NotNull.password"."NotNull.java.lang.String"."NotNull"]."arguments": [{"codes": [
						"loginDTO.password"."password"]."arguments": null."defaultMessage": "password"."code": "password"}]."defaultMessage": "Password cannot be empty."."objectName": "loginDTO"."field": "password"."rejectedValue": null."bindingFailure": false."code": "NotNull"}]."message": "Validation failed for object='loginDTO'. Error count: 1"."path": "/v1/test/login"
}
Copy the code

But my fixer partner only wants the message content of @notnull (message= “custom exception”); So I always in the project to define a global exception handling, in case of abnormal MethodArgumentNotValidException, capture, such as the following way:

{
	"code": 400."msg": "Password: Password cannot be empty"."data": 0
}
Copy the code

I used to have to write this global exception handler for every project. It was so annoying! As I was building a Maven private server recently, I decided to include this feature in my Maven private server. In the future, AS long as I rely on my Maven file, I don’t need to write it.

Here are my implementation steps, and see how I was forced to use SpringBoot autowage step by step.

Project construction and release

The creation of the repository and the setup of the Maven project were covered in the previous article and skipped here! To learn more, check out “Building Maven Private Server with Github.”

First a global exception handling is added in the maven project class ValidParamExceptionHandler, responsible for the interface into the non-empty validation exception handling.

@ControllerAdvice
public class ValidParamExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ApiResponse handlerMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder errorMessage = new StringBuilder(bindingResult.getFieldErrors().size() * 16);
        for (int i = 0; i < bindingResult.getFieldErrors().size(); i++) {
            if (i > 0) {
                errorMessage.append(",");
            }
            FieldError fieldError = bindingResult.getFieldErrors().get(i);
            errorMessage.append(fieldError.getField());
            errorMessage.append(":");
            errorMessage.append(fieldError.getDefaultMessage());
        }
        return new ApiResponse(400,errorMessage.toString(),0); }}Copy the code

If I had just packaged the release and introduced this Maven dependency in a new project, do you think global exception handling would have been done in the new project? I first time is intact operation again, the result is not good!! So I was thinking, because ValidParamExceptionHandler classes were not scan to Spring? Can’t I just add an @Component annotation? But when I opened the @ControllerAdvice annotation, I knew I was thinking shit because @ControllerAdvice already included the @Component annotation.

Finally I searched online for a solution and came across the following solution: Create a new Spring. factories file in meta-INF under the Resources folder and write the following

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.xinmachong.exception.ValidParamExceptionHandler
Copy the code

The first line is fixed, and the second line is obviously the path to the global exception handling class.

Finally packaged and released.

Global exception testing

Creating a SpringBoot project and importing dependencies, which is skipped here, can be found in “Building Maven Private Server with Github”.

Write a test interface as shown below:

Where LoginDTO is:

@Data
public class LoginDTO {
    @notnull (message = "account cannot be empty ")
    private String account;
    @notnull (message = "password cannot be empty ")
    private String password;
}
Copy the code

The process and results of testing the interface are shown below:

The input parameter has only one account. After a request, the following information is returned: Password: The password cannot be empty. At that time the heart is two words – hold grass; Because this global exception handling actually works in the new project.

conclusion

“I didn’t really think about it, but after I implemented it, I definitely wanted to figure it out. But why is the spring.factories file so awesome? Spring. Factories (” Spring-factories “, “Spring-factories”)

The global exception handling class is implemented by SpringBoot auto assembly. Suddenly all was clear.

I have followed a good article on the blog before read the source code of the entire auto assembly, also understand the way to achieve, but to tell the truth, ha, read and can use there is still a practical project. The gap between self aware.

One last quick question,

This global exception handler class must be in effect all the time, absolutely007But the boss I want to give it a holiday on the first day of the year how to do? As the boss, if I want it to work, it has to work. If I want it to rest, it has to be nonexistent. Why?Copy the code