===============
== ffff65535 ==
===============
十六个一[1111111111111111]

自定义校验注解ConstraintValidator

ConstraintValidator

新建一个枚举类,限制请求参数中的属性值只能等于枚举中的值

public enum EnumType {
    /**
     * 数组中是要等于的值每增加一个要校验的类型,
     * 增加一个对应枚举类
     */
    // 性别
    GENDER_TYPE(new String[]{"0", "1"}),
    // 年级
    GRADE_TYPE(new String[]{"1", "2", "3"});

    private String[] values;

    EnumType(String[] values) {
        this.values = values;
    }

    public String[] getValues() {
        return values;
    }
}

新建一个自定义注解

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

/**
 * 自定义注解
 *
 * @author
 */
// 指定这个校验注解的实现类
@Constraint(validatedBy = {EnumValidatorImpl.class})
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumValidator {

    EnumType value();

    /**
     * 是否强制校验
     *
     * @return 是否强制校验的boolean值
     */
    boolean required() default true;

    /**
     * 校验不通过时的报错信息
     *
     * @return 校验不通过时的报错信息
     */
    String message() default "";

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

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

定义校验类,实现ConstraintValidator接口.

接口使用了泛型,需要指定两个参数

  1. 第一个是自定义注解
  2. 第二个是需要校验的数据类型

重写2个方法:

  1. initialize方法主要做一些初始化操作,它的参数是我们使用到的注解,可以获取到运行时的注解信息。
  2. isValid方法就是要实现的校验逻辑,被注解的对象会传入此方法中。
import org.apache.commons.lang3.StringUtils;

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

/**
 * 校验类
 * @author
 */
public class EnumValidatorImpl implements ConstraintValidator<EnumValidator, String> {

    /**
     * 是否强制校验
     */
    private boolean required;
    private String[] values;
    private String message;

    /**
     * 会在校验实例化后被调用,一般用于做些初始化工作。
     *
     * @param constraintAnnotation
     */
    @Override
    public void initialize(EnumValidator constraintAnnotation) {
        this.required = constraintAnnotation.required();
        this.values = constraintAnnotation.value().getValues();
        this.message = constraintAnnotation.message();
    }

    /**
     * 实际执行验证的方法,第一个参数获取的是字段或对象实际对应的值,取决于类的枚举限定类型。
     * 第二个参数是ConstraintValidatorContext,上下文可以做些默认的设置。
     *
     * @param checkValue                 要校验的值
     * @param constraintValidatorContext
     * @return
     */
    @Override
    public boolean isValid(String checkValue, ConstraintValidatorContext constraintValidatorContext) {
        if (required) {
            //value就是需要校验的值
            //验证
            boolean exist = false;
            for (String value : values) {
                if (value.equals(checkValue)) {
                    exist = true;
                    break;
                }
            }
            // 校验未通过,并且message为null
            if (StringUtils.isBlank(message) && !exist) {
                StringBuilder sb = new StringBuilder();
                for (String s : values) {
                    sb.append(s).append(";");
                }
                String msg = sb.toString();
                msg = msg.substring(0, msg.length() - 1);
                // 禁用默认的message的值
                constraintValidatorContext.disableDefaultConstraintViolation();
                ///重新添加错误提示语句
                constraintValidatorContext.buildConstraintViolationWithTemplate("value must in:" + msg).addConstraintViolation();
            }
            return exist;
        }
        return false;
    }

}

创建要校验的实体类

import cn.domin.base.PrinterBaseEntity;
import cn.domin.common.validator.EnumType;
import cn.domin.common.validator.EnumValidator;
import lombok.Data;

import javax.validation.constraints.NotEmpty;
import java.io.Serializable;

@Data
public class Student extends BaseEntity implements Serializable {
    /**
     * 性别
     */
    @EnumValidator(EnumType.GENDER_TYPE)
    private String gender;
    /**
     * 年级
     */
    @EnumValidator(EnumType.GRADE_TYPE)
    private String grade;
}

创建接口

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@Slf4j
@RestController
@RequestMapping("/test/")
public class TestController {
    @PostMapping("/student/create")
    public void createStudent(@RequestBody @Valid Student student) {
    }
}

发起请求

如果请求参数属性值和枚举值不同时就会提示


参考资料:

https://www.jianshu.com/p/a3ed25e96daf

https://www.cnblogs.com/luciochn/p/14529281.html

https://www.cnblogs.com/liuboyuan/p/11093383.html