gogoWebsite

@Validated annotation explained, grouped checks, nested checks, @Valid and @Validated difference, Spring Boot @Validated

Updated to 8 hours ago

Tech Stack:

spring boot 2.3.

hibernate-validator

Project source code at the end of the article

 

catalogs

summarize

Project dependencies

Global Exception Handling Class

Basic parameter calibration

entity class

control type

beta (software)

Nested parameter validation

entity class

control type

beta (software)

Grouping parameter validation

interface class

entity class

control type

beta (software)

Difference between @Valid and @Validated


summarize

@Validation is a set of annotations that help us to continue data validation of transmitted parameters, which can be easily accomplished by configuring Validation to constrain the data.

@Validated acts on classes, methods and parameters

@Target({, , })
@Retention()
@Documented
public @interface Validated {
    Class<?>[] value() default {};
}

error status code

The recommended response code to return is 400 bad request.

Meaning of all parameter annotations

Project dependencies

Maven dependency coordinates:

Note: In the demo project all entity classes are in package ENTITY and the control layer is in package CONTROLLER.

Global Exception Handling Class

Note: Without exception handling, the default exception message for the @Validated annotation is as follows (example):

2020-09-05 21:48:38.106 WARN 9796 --- [nio-8080-exec-3] . : Resolved [: Validation failed for argument [0] in public .validatedDemo1(): [Field error in object 'useDto' on field 'username': rejected value [null]; codes [,,,NotBlank]; arguments [: codes [,username]; arguments []; default message [username]]; default message [User name cannot be empty!]] ]

So we make a global exception handling class here to handle exceptions thrown when parameter validation fails, along with logging output.

package ;

import ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

/**
 * @author He Changjie on 2020/9/5
 */
@Slf4j
@ControllerAdvice
public class ValidatedExceptionHandler {

    /**
     * deal with@ValidatedParameter validation failure exception
     * @param exception exception class
     * @return responsive
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler()
    public Result exceptionHandler(MethodArgumentNotValidException exception){
        BindingResult result = ();
        StringBuilder stringBuilder = new StringBuilder();
        if (()) {
            List<ObjectError> errors = ();
            if (errors != null) {
                (p -> {
                    FieldError fieldError = (FieldError) p;
                    ("Bad Request Parameters: dto entity [{}],field [{}],message [{}]",(), (), ());
                    (());
                });
            }
        }
        return (());
    }
}

Basic parameter calibration

entity class

package ;

import ;
import ;

import .*;

/**
 * user entity
 * Data Transfer Objects
 * @author He Changjie on 2020/9/5
 */
@Data
public class User1Dto {
    /**
     * user ID
     */
    @NotBlank(message = "user ID不能为空!")
    private String username;
    /**
     * distinguishing between the sexes
     */
    @NotBlank(message = "distinguishing between the sexes不能为空!")
    private String gender;
    /**
     * (a person's) age
     */
    @Min(value = 1, message = "(a person's) age有误!")
    @Max(value = 120, message = "(a person's) age有误!")
    private int age;
    /**
     * address
     */
    @NotBlank(message = "address不能为空!")
    private String address;
    /**
     * inbox
     */
    @Email(message = "inbox有误!")
    private String email;
    /**
     * mobile telephone number
     */
    @Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "mobile telephone number有误!")
    private String mobile;
}

control type

package ;

import .Use1Dto;
import ;
import ;
import ;
import ;
import ;

/**
 * @author He Changjie on 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {

    @PostMapping("/insert")
    public String validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){
        (use1Dto);
        return "success";
    }
}

beta (software)

1. Parameter calibration passed:

2. Parameter calibration failed:

Nested parameter validation

Validate other collections of objects in the entity that need to be validated or other objects

entity class

package ;

import ;

import ;
import ;
import ;
import ;

/**
 * The queue entity
 * Data transfer object
 * @author He Changjie on 2020/9/5
 */
@Data
public class Team1Dto {
    /**
     * Team name
     */
    @NotBlank(message = "Team name cannot be empty!")
    private String name;
    /**
     * Team Personnel
     */
    @NotNull(message = "Team personnel cannot be null!")
    @Valid
    private List<User1Dto> userList.

    /**
     * The person in charge of the team.
     */
    @NotNull(message = "Team leader cannot be null!")
    @Valid
    private User1Dto user;
}

control type

package ;

import ;
import .Team1Dto;
import .Use1Dto;
import ;
import ;
import ;
import ;
import ;
import ;

/**
 * @author He Changjie on 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {

    @PostMapping("/insert")
    public Result validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){
        return (use1Dto);
    }

    @PostMapping("/insert2")
    public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){
        return (team1Dto);
    }
}

test (machinery etc)

1. Parameter validation is passed:

2. Parameter validation failed:

Grouping parameter validation

Distribute different checksum rules to different groups and specify different checksum rules when using the

interface class

package ;

/**
 * calibration group1
 * @author He Changjie on 2020/9/5
 */
public interface Group1 {
}

 

package ;

/**
 * calibration group2
 * @author He Changjie on 2020/9/5
 */
public interface Group2 {
}

entity class

package ;

import .Group1;
import .Group2;
import ;

import .*;

/**
 * @author He Changjie on 2020/9/5
 */
@Data
public class User2Dto {
    /**
     * user ID
     */
    @NotBlank(message = "user ID不能为空!", groups = {})
    private String username;
    /**
     * distinguishing between the sexes
     */
    @NotBlank(message = "distinguishing between the sexes不能为空!")
    private String gender;
    /**
     * (a person's) age
     */
    @Min(value = 1, message = "(a person's) age有误!", groups = {})
    @Max(value = 120, message = "(a person's) age有误!", groups = {})
    private int age;
    /**
     * address
     */
    @NotBlank(message = "address不能为空!")
    private String address;
    /**
     * inbox
     */
    @Email(message = "inbox有误!", groups = {})
    private String email;
    /**
     * mobile telephone number
     */
    @Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "mobile telephone number有误!", groups = {})
    private String mobile;
}

control type

package ;

import ;
import .Team1Dto;
import .User1Dto;
import .User2Dto;
import .Group1;
import .Group2;
import ;
import ;
import ;
import ;
import ;
import ;

/**
 * @author He Changjie on 2020/9/5
 */
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {

    @PostMapping("/insert")
    public Result validatedDemo1(@Validated @RequestBody User1Dto user1Dto){
        return (user1Dto);
    }

    @PostMapping("/insert2")
    public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){
        return (team1Dto);
    }

    @PostMapping("/insert3")
    public Result validatedDemo3(@Validated @RequestBody User2Dto user2Dto){
        return (user2Dto);
    }

    @PostMapping("/insert4")
    public Result validatedDemo4(@Validated() @RequestBody User2Dto user2Dto){
        return (user2Dto);
    }

    @PostMapping("/insert5")
    public Result validatedDemo5(@Validated() @RequestBody User2Dto user2Dto){
        return (user2Dto);
    }
}

beta (software)

1. Passed without group calibration:

2. The ungrouped parameter calibration does not pass:


3. Subgroup 1 parameter calibration passed

4. Subgroup 1 parameter calibration failed

5. Subgroup 2 parameter calibration adopted

6. Subgroup 2 parameter calibration failed

7. Using the default grouping, the parameter checksum passes:

Description: Test the control layer/insert3 interface after adjusting it as follows

@PostMapping("/insert3")
    public Result validatedDemo3(@Validated() @RequestBody User2Dto user2Dto){
        return (user2Dto);
    }

for interface classes contained in Validated dependencies, not custom interface classes

8. Using the default grouping, the parameter check does not pass:

Note: Same operation as point 7

Difference between @Valid and @Validated

Analyzing through the source code:

@Target({, , , , ElementType.TYPE_USE})
@Retention()
@Documented
public @interface Valid {
}
@Target({, , })
@Retention()
@Documented
public @interface Validated {
    Class<?>[] value() default {};
}

@Valid: there is no grouping feature.

@Valid: can be used on methods, constructors, method parameters and member properties (fields)

@Validated: provides a grouping function that allows different validation mechanisms to be used according to different groups during inbound validation

@Validated: can be used on types, methods and method parameters. But cannot be used on member properties (fields)

Whether or not both can be used on member attributes (fields) has a direct impact on whether or not nested validation can be provided.

 

Code Cloud Address:/jie_harris/

 

It's not easy to hand-code, so please cite the source for reprinting

Thank you!