validation自定义注解校验枚举类型

        java validation内没有对枚举的校验工具,但是离散的枚举值校验确实是有必要的。javax.validation包提供了方便的自定义校验的入口,就是javax.validation.ConstraintValidator,故可以通过自定义校验枚举类型方式实现。

一、定义一个校验注解,类似于@NotNull @Size等等那样

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {EnumIntegerValidator.class})
@Documented
public @interface EnumIntegerValid {

    String message() default "";

    Class[] groups() default {};

    Class[] payload() default {};

    Class[] target() default {};

    /**
     * 允许的枚举
     * @return
     */
    Class> enumClass();

}

二、自定义枚举校验的处理类,该类必须实现ConstraintValidator接口

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

/**
 * @description value值是Integer类型的枚举校验器
 */
public class EnumIntegerValidator implements ConstraintValidator {

    private Class enumClass;

    @Override
    public void initialize(EnumIntegerValid enumIntegerValid) {
        enumClass = enumIntegerValid.enumClass();
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }

        EnumValidate[] enums = (EnumValidate[]) enumClass.getEnumConstants();
        if(enums ==null || enums.length == 0){
            return false;
        }

        return enums[0].existValidate(value);
    }
}

三、代码中使用

1、定义一个枚举值校验接口

/**
 * @description 枚举值校验
 */
public interface EnumValidate {

    /**
     * 校验枚举值是否存在
     */
    boolean existValidate(T value);

}

2、定义一个Integer类型枚举类

/**
 * @description 测试类型枚举类
 */
public enum TestTypeEnum implements EnumValidate {
    A(1, "测试A"),
    B(2, "测试B");

    private final Integer code;
    private final String desc;

    TestTypeEnum(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public Integer getCode() {
        return this.code;
    }

    public String getDesc() {
        return this.desc;
    }

    @Override
    public boolean existValidate(Integer value) {
        if (value == null) {
            return false;
        }
        for (TestTypeEnum testTypeEnum : TestTypeEnum.values()) {
            if (testTypeEnum.getCode().intValue() == value.intValue()) {
                return true;
            }
        }
        return false;
    }
}

3、参数校验该枚举,注意接收参数类型必须为Integer,否则使用String的枚举校验器。

public class TestRequest implements Serializable {
 
    private static final long serialVersionUID = -8739613309305982051L;
 
    @NotNull
    @EnumIntegerValid(message = "测试类型输入错误", enumClass = TestTypeEnum.class)
    private Integer type;
	
}

4、Controller中直接加上@Validated 或 @Valid即可

@RequestMapping("/test")
public ApiResponse doSomething(@Validated @RequestBody TestRequest request) {
    log.info("doSomething");
    log.info(request.toString());
    return ApiResponse.retOK();
}

或:

private static Validator validator = Validation.byProvider(HibernateValidator.class)
        .configure()
        .failFast(true)
        .buildValidatorFactory()
        .getValidator();

public static  void validParam(T param) {
    validParamNonNull(param);
    Set> constraintViolations = validator.validate(param, Default.class);
    StringBuilder sb = new StringBuilder();
    if (constraintViolations != null && !constraintViolations.isEmpty()) {
        for (ConstraintViolation constraintViolation : constraintViolations) {
            sb.append(constraintViolation.getPropertyPath())
                .append(":")
                .append(constraintViolation.getMessage())
                .append(".");
        }
        throw new IllegalArgumentException(sb.toString());
    }
}

四、对于String类型的枚举类

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {EnumStringValidator.class})
@Documented
public @interface EnumStringValid {

    String message() default "";

    Class[] groups() default {};

    Class[] payload() default {};

    Class[] target() default {};

    /**
     * 允许的枚举
     * @return
     */
    Class> enumClass();

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

/**
 * @description value值是String类型的枚举校验器
 */
public class EnumStringValidator implements ConstraintValidator {

    private Class enumClass;

    @Override
    public void initialize(EnumStringValid enumStringValid) {
        enumClass = enumStringValid.enumClass();
    }

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

        EnumValidate[] enums = (EnumValidate[]) enumClass.getEnumConstants();
        if(enums ==null || enums.length == 0){
            return false;
        }

        return enums[0].existValidate(value);
    }
}
/**
 * 测试枚举类
 */
public enum TestEnum implements EnumValidate {
    NONE("NONE", "无"),
    C("C", "测试C");

    private final String code;
    private final String desc;

    TestEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
        return this.code;
    }

    public String getDesc() {
        return this.desc;
    }

    @Override
    public boolean existValidate(String value) {
        if (value == null || "".equals(value)) {
            return false;
        }

        for (TestEnum testEnum : TestEnum.values()) {
            if (testEnum.getCode().equalsIgnoreCase(value)) {
                return true;
            }
        }
        return false;
    }

}
public class TestRequest implements Serializable {
 
    private static final long serialVersionUID = -8739613309305982051L;
 
    @NotNull
    @EnumStringValid(message = "测试类型输入错误", enumClass = TestEnum.class)
    private String test;
	
}

 

参考:https://blog.csdn.net/lqadam/article/details/103446179?utm_source=distribute.pc_relevant.none-task

https://blog.csdn.net/ye17186/article/details/88242913

你可能感兴趣的:(Java,validation,枚举类型,校验,自定义)