zl程序教程

您现在的位置是:首页 >  Java

当前栏目

Java自定义注解校验枚举值类型参数

2023-04-18 15:24:17 时间

  项目开发中会经常使用到各种枚举值,枚举值一般都是固定的,不会随意改变其中的值。

比如性别分为男女,确定之后一般都不会轻易改变,这时候使用枚举值就非常地方便。很多

时候,在页面中传入的参数就是枚举值中的一个,比如性别,或者是星期,月份,以及自定义

的各种类型等等。如果是手动校验就非常麻烦,假如有50个枚举值,不可能每一个枚举值都

进行手动校验,那这时候如何更好的校验呢?答案很简单,使用自定义的校验注解即可。

先上代码,然后在慢慢地讲解。自定义的校验注解如下:

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR,ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Constraint(validatedBy = {EnumValidateValidator.class})

public @interface EnumValidate {

 

    Class<? extends Enum<?>> enumClass();

 

    String enumMethod() default "isValid";

 

    String message() default "必须传入枚举类型的class";

 

    boolean nullAble() default false;

 

    //分组

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

 

    // 负载

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

 

    // 指定多个时使用

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR,ElementType.PARAMETER})

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    @interface List {

        EnumValidate [] value();

    }

}

 

自定义校验注解验证器如下:

public class EnumValidateValidator implements ConstraintValidator<EnumValidate, Object> {

 

    private Class<? extends Enum<?>> enumClass;

    private String enumMethod;

    private boolean nullAble;

 

    @Override

    public void initialize(EnumValidate constraintAnnotation) {

        enumClass = constraintAnnotation.enumClass();

        enumMethod = constraintAnnotation.enumMethod();

        nullAble = constraintAnnotation.nullAble();

    }

 

    @Override

    public boolean isValid(Object value, ConstraintValidatorContext context) {

        if (value == null) {

            return nullAble;

        }

        try {

            Object[] enumConstants = enumClass.getEnumConstants();

            Method method = enumClass.getMethod(enumMethod, value.getClass());

            Object result = method.invoke(enumConstants[0], value);

            System.out.println("invoke--->" + result);

            return (Boolean)result;

        } catch (Exception ex) {

            ex.printStackTrace();

            throw new RuntimeException("枚举类型验证错误");

        }

    }

}

 

自定义的测试枚举如下:

public enum  TestEnum {

 

    TYPE_ONE("ONE", "成功"),

 

    TYPE_TWO("TYPE_TWO", "失败"),

    ;

    /*

     * 编码

     */

    private String code;

 

    /*

     * 信息

     */

    private String msg;

 

    public String getCode() {

        return code;

    }

 

    TestEnum(String code, String msg) {

        this.code = code;

        this.msg = msg;

    }

 

    /* @Description: 枚举里面的自定义校验方法

     * @author: yilang

     * @date: 2022/12/6 20:53

     * @param: value

     * @return: boolean

     */

    public boolean isValid(String value) {

        for(TestEnum testEnum : TestEnum.values()) {

            if (testEnum.getCode().equals(value)) {

                return true;

            }

        }

        return false;

    }

}

测试入参如下:

@Data

public class ParamTest {

 

    /*

     * 名称

     */

    @NotNull(message = "名称不能为null")

    private String name;

 

    /*

     * 简介

     */

    @Length(max = 10, message = "简介长度最大为10")

    private String abs;

 

    @EnumValidate(enumClass = TestEnum.class, nullAble = false, message = "传入的枚举类型参数错误")

    private String enumTest;

}

 

Controller中的测试方法如下:

@Slf4j

@RestController

@RequestMapping("/happy/yilang")

public class TestControlelr {

    @PostMapping("/enum")

    public String enumTest(@Valid @RequestBody ParamTest paramTest){

        return "枚举类型统计";

    }

}

 

自定义注解中主要有几个自定参数,

 // 限定传入的class为枚举类型

    Class<? extends Enum<?>> enumClass();

// 指定传入的需要调用的枚举类的检验方法

    String enumMethod() default "isValid";

 // 错误提示信息

    String message() default "必须传入枚举类型的class";

// 待校验的参数是否允许为null

    boolean nullAble() default false;

    //分组-自定义注解最好加上

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

    // 负载-自定义注解必加参数,否则报错

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

自定义注解校验器EnumValidateValidator 需要实现接口ConstraintValidator然后重写里面的校验方法。

// 返回枚举类的元素 enumClass是通过注解拿到的,然后初始化的时候赋值给成员变量

 Object[] enumConstants = enumClass.getEnumConstants();

// 获取需要执行的方法 enumMethod是通过注解拿到的,然后初始化的时候赋值给成员变量

//  value.getClass() 可以获取到原始传入数据的类型

 Method method = enumClass.getMethod(enumMethod, value.getClass());

// 使用反射的方式执行方法,传入枚举变量和参数 程序底层会调用注解中获取到的需要执行的校验方法,默认为isValid,可以任意修改

 Object result = method.invoke(enumConstants[0],  value);

// 自定义枚举类中isValid 方法返回的值是一个Object类型,可以转换为布尔类型

return (Boolean)result;

自定义枚举类中, isValid是自定义方法,名称可以随便取。 TestEnum.values()是每一个枚举类中都自带的方法,可以获取当前枚举的所有值。

    public boolean isValid(String value) {

        for(TestEnum testEnum : TestEnum.values()) {

            if (testEnum.getCode().equals(value)) {

                return true;

            }

        }

        return false;

}

Controller中的方法和参数中使用注解的方式都很常规,不在赘述。

测试结果如下,通过校验的测试

 

 

 

未通过校验的测试

 

 

 

参考文章:

https://blog.csdn.net/h2604396739/article/details/83825148