SpringBoot uses ConstraintValidator to implement custom annotation validation

I. Introduction

        ConstraintValidator is an interface in the Java Bean Validation (JSR-303) specification, which is used to implement the validation logic of custom validation annotations. ConstraintValidator defines two generic parameters, which are the annotation type and the value type to be verified. When implementing the ConstraintValidator interface, methods such as initialize and isValid need to be rewritten, and specific validation logic must be implemented.

2. Whether the custom annotation checks whether the parameter is Null

        For example, the verification parameter name cannot be null or an empty string, first write @interface class ValidNull:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {NullValidator.class})
public @interface ValidNull {
    // 默认错误消息
    String message() default "name不能为空";

    // 分组
    Class<?>[] groups() default {};

    // 负载
    Class<? extends Payload>[] payload() default {};
}

        Then write the validation class NullValidator:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class NullValidator implements ConstraintValidator<ValidNull, String> {
    @Override
    public void initialize(ValidNull constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (null == value || "".equals(value)){
            return false;
        }
        return true;
    }
}

        Write the entity class NullTest and add annotations here:

import lombok.Data;

@Data
public class NullTest {

    @ValidNull
    private String name;
}

         Finally, call verification is performed at the controller layer. Note that the @Validated annotation needs to be added in front of the entity class, otherwise the verification will not take effect:

    @PostMapping(value = "/test")
    public RetResult test(@RequestBody @Validated NullTest nullTest) {
        System.err.println(nullTest.getName());
        return RetResult.success();
    }

        Test Results:

        When name has a value, pass normally:

         When the name is null, a verification error message will be prompted:

        When the name is an empty string, a verification error message will be prompted:

 

3. Custom annotation check parameter value size

        For example, if a parameter is a number, its size needs to be checked, as follows:

        Write the @interface class first:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {NumValidator.class})
public @interface ValidNum {
    int value();

    // 默认错误消息
    String message() default "num不能大于20";

    // 分组
    Class<?>[] groups() default {};

    // 负载
    Class<? extends Payload>[] payload() default {};
}

        There is added value here, which can be used when using this annotation to pass parameters, and the following default error message can also be used together when using annotations, but it is used by default when no parameters are passed.

        Write the NumValidator validation class:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class NumValidator implements ConstraintValidator<ValidNum,Integer> {
    private Integer value;

    @Override
    public void initialize(ValidNum constraintAnnotation) {
        this.value = constraintAnnotation.value();
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        if(value > this.value){
            return false;
        }
        return true;
    }
}

        You can see that the value is also defined here, initialized in initialize, that is, to obtain the value passed in where the annotation is used.

        Write entity class NullTest:

import lombok.Data;

@Data
public class NumTest {

    @ValidNum(value = 30, message = "数值不能大于30")
    private Integer num;
}

        Test at the controller layer:

    @PostMapping(value = "/test")
    public RetResult test(@RequestBody @Validated NumTest numTest) {
        System.err.println(numTest.getNum());
        return RetResult.success();
    }

        Test Results:

        When the incoming parameter is less than 30:

        When the incoming parameter is greater than 30:

 

Guess you like

Origin blog.csdn.net/qq_41061437/article/details/132446337