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<? extends Payload>[] payload() default {};

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

    /**
     * 允许的枚举
     * @return
     */
    Class<? extends Enum<?>> enumClass();

}

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

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

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

    private Class<? extends Enum> 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<T> {

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

}

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

/**
 * @description 测试类型枚举类
 */
public enum TestTypeEnum implements EnumValidate<Integer> {
    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 <T> void validParam(T param) {
    validParamNonNull(param);
    Set<ConstraintViolation<T>> constraintViolations = validator.validate(param, Default.class);
    StringBuilder sb = new StringBuilder();
    if (constraintViolations != null && !constraintViolations.isEmpty()) {
        for (ConstraintViolation<T> 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<? extends Payload>[] payload() default {};

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

    /**
     * 允许的枚举
     * @return
     */
    Class<? extends Enum<?>> enumClass();

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

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

    private Class<? extends Enum> 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<String> {
    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

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
回答: 在Spring Validation中,你可以使用自定义注解来定义校验规则。在引用中的代码中,我们可以看到`@BankNo`注解的定义。这个注解标识了一个银行账号的校验规则。通过`validatedBy`属性指定了具体的校验逻辑的实现类`BankNoValidator`。同时,`groups`和`payload`属性可以用于对校验进行分类和负载。在引用中的代码中,我们可以看到在接口或方法中使用`@Validated`注解来启用校验功能。在例子中,`OrderDTO`对象上使用了`@Validated`注解,表示要对这个对象进行校验。而在引用中的代码中,我们可以看到`EqualsXzhValidator`类实现了`ConstraintValidator<EqualsXzh, String>`接口,其中`EqualsXzh`注解是自定义的注解,用于校验字符串必须是"xzh"。自定义校验规则的实现逻辑写在`isValid`方法中,根据具体的业务需求来编写校验规则。这样,在使用`@Validated`注解进行校验时,就会自动触发对应的校验规则。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring自定义注解(validation)](https://blog.csdn.net/ileopard/article/details/123485111)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [基于Spring Validation自定义校验注解](https://blog.csdn.net/Anenan/article/details/128004111)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值