• 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;
    }
  • 相关阅读:
    Python 字符串操作
    Python 字典操作
    16 飞机大战:思路整理、重要代码
    15 飞机大战:pygame入门、python基础串连
    14 windows下安装pygame模块
    13 制作模块压缩包、安装模块
    12 包及导包
    11 模块、模块的搜索顺序、__file__内置属性、__name__属性
    异常集
    10 异常
  • 原文地址:https://www.cnblogs.com/itsharehome/p/15626554.html
Copyright © 2020-2023  润新知