Spring Boot unified exception handling and parameter verification

Automatic calibration of parameters

In general we have two ways of passing parameters from the front to the back: JSON or form submission

So this article describes how JSON submission parameter validation and form submission parameter validation work in Spring Boot, and how validation failures are collectively referred to the exception handling class.

The Api design is as follows:

Form: http://localhost:8080/get-args-valid? username=xxx&password=xxx

JSON: http://localhost:8080/post-args-valid

{
    "username":"123"."password":"123"
}

Copy the code

The submission mode is JSON. Therefore, set the content-type as follows:

Content-Type: application/json

Create a new Spring Boot project

The Api is designed as follows:


/ * * *@author: hujiansong
 * @email: [email protected]
 * @since: 2019/1/29 16:53 * /
@RestController
public class ValidController {

    @GetMapping("/get-args-valid")
    public String getArgsValid(String username, String password) {
        return null;
    }

    @PostMapping("/post-args-valid")
    public String postArgsValid(@RequestBody User user) {
        return null;
    }

    @Data
    class User { String username; String password; }}Copy the code

First, how to verify parameters in JSON mode

JSON:

@RestController
public class ValidController {


    @PostMapping("/post-args-valid")
    public String postArgsValid(@Valid<1> @RequestBody User user) {
        return null;
    }

    @Data
    static class User {
        @NotNull(message = "User name cannot be empty") <2>
        String username;

        @NotNull(message = "Password cannot be empty.") String password; }}Copy the code

Note: The internal User class must be static, otherwise the json will not parse

<1>: @valid indicates that this entity parameter is given to Spring for verification

<2>: @notnull Verification rule

The above two steps can complete parameter verification:

You can see how the password is not passed, spring has done the parameter verification for us, let’s look at the form mode

Form mode:

@RestController @Validated<1> public class ValidController { @GetMapping("/get-args-valid") public String GetArgsValid (@notnull (message = "username cannot be empty ")<2> String username, @notnull (message = "password cannot be empty ") String password) {return null; }}Copy the code

Again, 2 steps

<1>: @Validated, and give it to Spring for verification

<2>: @notnull Verification rule

See what is returned if the password is not passed:

As you can see, Spring has done the parameter verification for us

Spring also includes many validation rules as follows:

annotations explain
@Null The annotated element must be NULL
@NotNull The annotated element must not be NULL
@AssertTrue The annotated element must be true
@AssertFalse The annotated element must be false
@Min(value) The annotated element must be a number whose value must be greater than or equal to the specified minimum
@Max(value) The annotated element must be a number whose value must be less than or equal to the specified maximum
@DecimalMin The annotated element must be a number whose value must be greater than or equal to the specified minimum
@DecimalMax The annotated element must be a number whose value must be less than or equal to the specified maximum
@Size(max=, min=) The size of the annotated element must be within the specified range
@Digits The annotated element must be a number and its value must be within an acceptable range
@Past The annotated element must be a past date
@Future The annotated element must be a future date
@Pattern(regex=) The annotated element must conform to the specified regular expression

Unified exception handling

Above, we showed you how to get Spring to validate our arguments, and you can see that the JSON validation returns a long string of results, which are not very elegant. The result of parameter verification can be returned elegantly with unified exception handling.

JSON: check failed, throws a MethodArgumentNotValidException

Form: check failed, throws a ConstraintViolationException

Therefore, you only need to handle these two exceptions in the unified exception handling class.

ExceptionHanlder

Form mode:

@RestControllerAdvice
public class ExceptionHandler {

    @org.springframework.web.bind.annotation.ExceptionHandler(ConstraintViolationException.class)
    public Map<String, Object> methodArgNotValidException(ConstraintViolationException cve, HttpServletRequest httpServletRequest) { Set<ConstraintViolation<? >> cves = cve.getConstraintViolations(); StringBuffer errorMsg =new StringBuffer();
        cves.forEach(ex -> errorMsg.append(ex.getMessage()));
        Map<String, Object> respMap = new HashMap<>(4);
        respMap.put("code", -1);
        respMap.put("msg", errorMsg);
        returnrespMap; }}Copy the code

Recall:

JSON:

@RestControllerAdvice
public class ExceptionHandler {

    @org.springframework.web.bind.annotation.ExceptionHandler({MethodArgumentNotValidException.class})
    public Map<String, Object> methodDtoNotValidException(Exception ex, HttpServletRequest request) {
        MethodArgumentNotValidException c = (MethodArgumentNotValidException) ex;
        List<ObjectError> errors = c.getBindingResult().getAllErrors();
        StringBuffer errorMsg = new StringBuffer();
        errors.stream().forEach(x -> {

            errorMsg.append(x.getDefaultMessage()).append(";");
        });
        Map<String, Object> respMap = new HashMap<>(4);
        respMap.put("code", -1);
        respMap.put("msg", errorMsg);
        returnrespMap; }}Copy the code

Again, try this time if username is empty:

Complete code