The article directories

      • background
      • Common scenarios
        • 1. The bean validation
        • 2. Verify plane parameters
        • 3. Manually verify the authentication
        • 4. The List
      • extension
        • Similarities and differences between 1.@Validated and @valid
        • 2. Quick failure mode
        • 3. Verify relevant notes and instructions
        • 4. Customize validation annotations

Prepare a “Build scaffolding from Scratch series” to share the problems encountered and the process of building.

background

When it comes to user input, you need to verify the input content, for example: the name cannot be blank, the age range is 0-150, and so on. We use Spring Boot’s built-in validation to do this.

Starting with Spring Boot 2.3, we need to explicitly add spring-boot-starter-validation dependencies:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-validation</artifactId> 
</dependency>
Copy the code

Common scenarios

Sort out and share some common ways in project development.

1. The bean validation

Entities to be verified:

@Data
@Builder
public class LakerUser {
    /** * name */
    @notblank (message = "name cannot be blank ")
    private String name;

    /** * age */
    @min (value = 0, message = "age should be greater than or equal to 0")
    @min (value = 150, message = "age should be less than or equal to 150")
    private int age;

    /** * Mobile phone number */
    @notblank (message = "Phone number cannot be blank ")
    ^ @ the Pattern (regexp = "[1] [3,4,5,6,7,8,9] [0-9] {9} $", message =" phone number format is wrong ")
    private String mobile;

}
Copy the code

Controller:

Method entry: add @ “Validated”

    @RequestMapping("/lakeruser")
    public Response validatorBean(@RequestBody @Validated LakerUser lakerUser) {
        return Response.ok();
    }
Copy the code

Global exception handling:

@RestControllerAdvice("com.laker.notes")
@Slf4j
public class GlobalExceptionHandler {  
    /** * Verify the bean type */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage(), e);
        List<Map> result = new ArrayList<>();
        e.getBindingResult().getFieldErrors().forEach((fieldError) -> {
            result.add(Dict.create().set("field", fieldError.getField()).set("msg", fieldError.getDefaultMessage()));
        });
        returnResponse.error(result); }...Copy the code

Validation:

2. Verify plane parameters

Controller:

Control class: annotated @Validated

@RestController
@Slf4j
@Validated
public class ValidatorController {    
	@RequestMapping("/validator")
    public Response validatorParam(@notblank (message = "name cannot be blank ") String name, @min (value = 0, message = "age should be greater than or equal to 0")
    @max (value = 150, message = "age should be less than or equal to 150") String age) {
        return Response.ok();
    }
Copy the code

Validation:

3. Manually verify the authentication

Tools:

public class ValidatorUtils {
    private static Validator validator;
    static {
        // Normal mode
        validator = Validation.byProvider(HibernateValidator.class)
                .configure()
                // Fast failure mode. When fast fails to be enabled, validation stops when the first constraint violation is detected
                .failFast(false)
                .buildValidatorFactory()
                .getValidator();
    }
    /** * Check object */
    public static <T> void validate(T object, Class
       ... groups) {
        Set<ConstraintViolation<T>> constraintViolationSet = validator.validate(object, groups);

        if(! constraintViolationSet.isEmpty()) {throw newConstraintViolationException(constraintViolationSet); }}}Copy the code

Controller:

    @RequestMapping("/util")
    public Response validatorUtil(@RequestBody LakerUser lakerUser) {
        ValidatorUtils.validate(lakerUser);// Call before and after any business logic
        return Response.ok();
    }
Copy the code

Validation:

4. The List

Controller:

Method entry: add @VALID, and add @validated annotation to the control layer

@RestController
@Slf4j
@Validated
public class ValidatorController { 
	@RequestMapping("/lakerusers")
    public Response validatorListBean(@RequestBody @Valid List<LakerUser> lakerUser) {
        return Response.ok();
    }
Copy the code

Validation:

extension

Similarities and differences between 1.@Validated and @valid

  • @ValidatedIs a variant of the Spring implementation JSR-303@Valid that supports the validation group specification.
  • @ValidIs a validation annotation for the JSR-303 standard implementation.
annotations The scope of nested Check group
@Validated You can mark classes, methods, and method parameters, not member attributes (fields) Does not support support
@Valid You can tag methods, constructors, method parameters, and member attributes (fields) support Does not support

Both can be used with method inputs, but neither provides nested validation alone. Both can be used with the @valid nested validation annotation for nested validation.

Nested validation examples:

public class ClassRoom{
    @NotNull
    String name;
    @Valid  // Nested checksum validates the attributes inside the parameter
    @NotNull
    Student student;
}
    @GetMapping("/room")   // You can use @valid or @validated to perform nested verification
    public String validator(@Validated ClassRoom classRoom, BindingResult result) {
        if (result.hasErrors()) {
            return result.getFieldError().getDefaultMessage();
        }
        return "ok";
    }
Copy the code

2. Quick failure mode

Fast failure mode: When fast failure is enabled, validation stops when the first constraint violation is detected and defaults to non-fast failure mode.

   // Normal mode
        validator = Validation.byProvider(HibernateValidator.class)
                .configure()
                // Fast failure mode. When fast fails to be enabled, validation stops when the first constraint violation is detected
                .failFast(true)
                .buildValidatorFactory()
                .getValidator();
Copy the code

3. Verify relevant notes and instructions

Validation annotations The type of data to validate instructions
@AssertFalse Boolean,boolean Verify that the element value of the annotation is false
@AssertTrue Boolean,boolean Verify that the element value of the annotation is true
@NotNull Any type Verify that the element value of the annotation is not NULL
@Null Any type Verify that the element value of the annotation is NULL
@ Min (value = value) BigDecimal, BigInteger, byte,short, int, Long, and any Number or CharSequence (which stores numbers) subtypes Verify that the element value of the annotation is greater than or equal to the value specified by @min
@max (value= value) Same as @min Verify that the element value of the annotation is less than or equal to the value specified by @max
@ DecimalMin (value = value) Same as @min Verify that the element value of the annotation is greater than or equal to the value specified by @decimalmin
@ DecimalMax (value = value) Same as @min Verify that the element value of the annotation is less than or equal to the value specified by @decimalmax
@Digits(integer= integer number, fraction= decimal number) Same as @min Validates the upper limit of integer and decimal digits for the element value of the annotation
@size (min= lower limit, Max = upper limit) String, Collection, Map, array, etc Validates the element value of an annotation within the specified min and Max (inclusive) interval, such as character length and collection size
@Past java.util.Date,java.util.Calendar; The date type of the Joda Time class library Verify that the element value (date type) of the annotation is earlier than the current time
@Future Same as @past Verify that the element value (date type) of the annotation is later than the current time
@NotBlank CharSequence subtype Verify that the element value of the annotation is not null (not null, length 0 after removing the first whitespace), unlike @notempty, where @notBlank applies only to strings and removes the first whitespace of strings when comparing
@length (min= lower limit, Max = upper limit) CharSequence subtype Verify that the element value length of the annotation is within min and Max
@NotEmpty CharSequence subtype, Collection, Map, array Verify that the element value of the annotation is not null and is not empty (string length is not 0, collection size is not 0)
@range (min= min, Max = Max) BigDecimal, BigInteger, CharSequence, byte, short, int, long, such as atomic types and package types Verify that the element value of the annotation is between the minimum and maximum value
@email (regexp= regular expression,flag= pattern of flags) CharSequence subtype (e.g. String) Verify that the element value of the annotation is Email, or you can specify a custom Email format using regEXP and flag
@pattern (regexp= regular expression,flag= Pattern of flags) String, the subtype of any CharSequence Verifies that the element value of the annotation matches the specified regular expression

4. Customize validation annotations

1. Create custom annotations

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Constraint(validatedBy = FlagValidatorClass.class) // Bind the corresponding validator
public @interface FlagValidator {
    String[] value() default {};
 
    String message(a) default "flag is not found"; Class<? >[] groups()default {};
 
    Class<? extends Payload>[] payload() default {};
}
Copy the code

2. Write a validator

/** ** flag bit validator */
public class FlagValidatorClass implements ConstraintValidator<FlagValidator.Integer> {
    private String[] values;
 
    /** * initializes **@paramThe value set in the flagValidator annotation */
    @Override
    public void initialize(FlagValidator flagValidator) {
        this.values = flagValidator.value();
    }
 
    /** * check **@paramValue Specifies the verified value, that is, *@param* constraintValidatorContext check context@returnReturns true to verify that the verification passed, false to verify that the verification failed */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
        boolean isValid = false;
        // If value is null, verification fails
        if (value == null) {
            return false;
        }
        // traversal verification
        for (int i = 0; i < values.length; i++) {
            if (values[i].equals(String.valueOf(value))) {
                isValid = true;
                break; }}returnisValid; }}Copy the code

3. Attribute annotations

    @notnull (message = "Flag bit cannot be empty ")
    @flagvalidator (value = {"0", "1"}, message = "error ")
    private Integer flag;
Copy the code

Reference:


🍎QQ group [837324215] 🍎 pay attention to my public number [Java Factory interview officer], learn together 🍎🍎🍎