Before:

Don’t read for the sake of reading. Read with questions and thinking.

In Web development, we often need to verify various parameters, which is a tedious and important thing, for many people, when doing parameter verification, there will be the following types of processing.

Jilt pot type

If the caller sends the error, it is the caller’s problem, not the service’s problem. Throw 500 errors and let them reflect on it:

A model type

I write as many if statements as there are parameters to check, and write a friendly message if the check fails, such as:

Tool type

Write a general tool for parameter verification, and then call the tool method for verification for each parameter received in the request. If the verification fails, the verification result will be returned to the caller:

Semi-automatic type

To understand, the SpringMVC comprehensive friends all know that it supports Bean Validation, so you can through the use of the javax.mail. Validation. The annotation under constraints package, such as @ NotNull @ @ Max Min, To realize data verification by the framework.

First, add hibernate-Validator dependencies (SpringBoot has already added them automatically for us).

<dependency> <groupId> org.hibernate.validator </groupId> <artifactId> hibernate-validator </artifactId> <version> 6.0.10. Final < / version > < / dependency >Copy the code

Then, annotate the fields of the parameter object:

Finally, add the @valid annotation to the parameter object in the Controller and process the validation result:

Tip: If your parameter is not an object, be sure to annotate Controller with @Validated!

This way, each Controller method has to process the result, which is also a hassle.

Project analysis

All of the above methods have disadvantages:

First of all, parameter verification is a very important thing, the client should hold the first line of defense, and the server should take a mistrustful attitude, do parameter verification. Otherwise, if the parameters of illegal request are small, the user experience will be affected or garbage data will be generated. If large, it will drag across the whole system!

Secondly, checking all the parameters manually is rather tedious, error-prone and So boring

Finally, it’s better to do it with tools, but you have to make the tools elegant.

So, is there a better solution? The answer is: yes!

Best practices

In fact, the above semi-automatic solution, as long as further, you can achieve full automatic!

What if, in the semi-automatic example above, we did not process the validation results in the Controller method? The answer is, it throws an exception:

So, if we do global uniform exception handling, wouldn’t we be able to implement automatic verification and return the results we want? So we can do this:

@controllerAdvice public class GlobalExceptionHandler {/** Handle exception exception */ @ExceptionHandler @responseBody public ResultBean <? > handleValidationException (BindException e) {/ / get the String MSG = um participant etBindingResult () getAllErrors () stream (). The map ( DefaultMessageSourceResolvable ::getDefaultMessage) .collect( Collectors .joining(","
));
        log.warn(
"MSG: {}"
, msg);
        returnResultBean .fail(msg); }}Copy the code

However, if you only handle the exception BindException, you will find that sometimes this scheme works and sometimes it “breaks.” Why is that? Spring will throw different exceptions for different parameter parsing methods, and these exceptions have no inheritance relationship, and the way to obtain verification results from exceptions is different.

To sum up, there are the following exceptions to handle:

The object parameter receives the RequestBody, RequestBody:

MethodArgumentNotValidException

Request parameters bind to object parameters:

BindException

Common parameters:

ConstraintViolationException required parameters are missing: ServletRequestBindingException so complete processing method should be like this:  @ExceptionHandler ({ ConstraintViolationException .class, MethodArgumentNotValidException .class, ServletRequestBindingException .class, BindException .class}) @ResponseBody public ResultBean <? > handleValidationException( Exception e) { String msg =""
;
    if (e instanceof 
MethodArgumentNotValidException
) {
        
MethodArgumentNotValidException
 t = (
MethodArgumentNotValidException
) e;
        msg = t.getBindingResult().getAllErrors().stream()
               .map(
DefaultMessageSourceResolvable
::getDefaultMessage)
               .collect(
Collectors
.joining(
","
));
    } else if (e instanceof 
BindException
) {
        
BindException
 t = (
BindException
) e;
        msg = t.getBindingResult().getAllErrors().stream()
               .map(
DefaultMessageSourceResolvable
::getDefaultMessage)
               .collect(
Collectors
.joining(
","
));
    } else if (e instanceof 
ConstraintViolationException
) {
        
ConstraintViolationException
 t = (
ConstraintViolationException
) e;
        msg = t.getConstraintViolations().stream()
                .map(
ConstraintViolation
::getMessage)
                .collect(
Collectors
.joining(
","
));
    } else if (e instanceof 
MissingServletRequestParameterException
) {
        
MissingServletRequestParameterException
 t = (
MissingServletRequestParameterException
) e;
        msg = t.getParameterName() + 
"Can't be empty."
;
    } else if (e instanceof 
MissingPathVariableException
) {
        
MissingPathVariableException
 t = (
MissingPathVariableException
) e;
        msg = t.getVariableName() + 
"Can't be empty."
;
    } else {
        msg = 
"Required parameter missing"
;
    }
    log.warn(
"MSG: {}"
, msg);
    return 
ResultBean
.fail(msg);
}Copy the code

With the addition of this global exception handler, parameter verification can be done automatically! Experience the feeling of flying ~~

However, if the user accesses a page from a browser and the parameter verification fails, the unified exception handler returns json text. The average user would be confused by this text.

So how do you make a request to open a page return an error page and an Ajax request return JSON? My example code has been shown, interested can understand.


———————

Copyright notice: This article is the blogger’s original article, reprint please attach the blog link!