SpringBoot EnumValidator验证器实现

实现背景

在实际开发过程中,往往也需要对某些参数进行枚举合法值校验。如果在代码中大量充斥者if else check代码,实现不够优雅。借鉴Hibernate其他优秀验证器的实现,Enum校验也可以拥有自己的验证器!

 

实现原理

1. 定义枚举检查注解@EnumCheck,方便在请求对象参数上使用;

2. 定义接口EnumValidator,让需要验证的Enum类实现getValue()方法,主要目的是获取枚举的比较值;

3. 实现接口ConstraintValidator的isValid()方法,实现具体的枚举校验逻辑。

 

代码实现

1. @EnumCheck注解类:

复制代码
/**
 * 枚举检查注解
 *
 * @author binglang
 * @date 2021/8/31 11:41
 */
@Documented
@Constraint(validatedBy = EnumConstraintValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(EnumCheck.List.class)
public @interface EnumCheck {
    /**
     * 提示信息
     *
     */
    String message() default "{javax.validation.constraints.EnumCheck.message}";

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

    /**
     * 扩展对象
     *
     */
    Class<? extends Payload>[] payload() default { };

    /**
     * 必须实现EnumValidator接口的枚举类
     *
     */
    Class<? extends EnumValidator> clazz();

    /**
     * 调用的方法名称
     */
    String method() default "getValue";

    /**
     * Defines several {@code @In} constraints on the same element.
     *
     * @see EnumCheck
     */
    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        /**
         * In数组
         */
        EnumCheck[] value();
    }
}
复制代码

 

2. EnumValidator接口定义:

复制代码
/**
 * 枚举验证接口
 *
 * @author binglang
 * @date 2021/8/31 11:43
 */
public interface EnumValidator {
    Object getValue();
}
复制代码

 

3. EnumConstraintValidator验证器具体实现:

复制代码
/**
 * 枚举验证器实现
 *
 * @author binglang
 * @date 2021/8/31 11:44
 */
public class EnumConstraintValidator implements ConstraintValidator<EnumCheck, Object> {
    /**
     * 注解对象
     */
    private EnumCheck annotation;

    /**
     * 初始化方法
     *
     * @param constraintAnnotation 注解对象
     */
    @Override
    public void initialize(EnumCheck constraintAnnotation) {
        this.annotation = constraintAnnotation;
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (Objects.isNull(value)) {
            return false;
        }

        Object[] enumConstants = annotation.clazz().getEnumConstants();
        try {
            // 核心代码实现
            Method method = annotation.clazz().getMethod(annotation.method());
            for (Object enumConstant : enumConstants) {
                if (value.equals(method.invoke(enumConstant))) {
                    return true;
                }
            }
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }

        return false;
    }
}
复制代码

 

如何使用

1. 需要校验的枚举类实现上面的EnumValidator接口:

复制代码
/**
 * 引用节点类型
 *
 * @author binglang
 * @date 2021/7/13 20:12
 */
public enum RefNodeType implements EnumValidator {
    FIELD("field", "field"),
    FUNC("func", "func");

    private final String code;
    private final String label;

    RefNodeType(String code, String label) {
        this.code = code;
        this.label = label;
    }

    public String getCode() {
        return code;
    }

    public String getLabel() {
        return label;
    }

    // 实现getValue()逻辑
    @Override
    public Object getValue() {
        return code;
    }
复制代码

 

2. 请求对象使用@EnumCheck注解:

@Data
public class TestDto {
    @ApiModelProperty(value = "变量类型")
    @NotBlank(message = "变量类型不能为空")
    @EnumCheck(clazz = RefNodeType.class, message = "变量类型不合法")
    private String refNodeType;
}

 

posted @   冰狼爱魔  阅读(1579)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
历史上的今天:
2018-11-30 javascript之url转义escape()、encodeURI()和decodeURI()
2018-11-30 yii2.0安装ElasticSearch及使用
2018-11-30 Linux 查看CPU、Memory等资源占用情况
点击右上角即可分享
微信分享提示