元注解
首先,用来修饰注解的注解被称为元注解,如以下代码中的@Documented、@Target、@Retention、@Constraint就是元注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Constraint(validatedBy = EnumValidatorClass.class)
public @interface EnumValidator {
//Class<?> value() 表示需要这个字段对应的枚举的类型。
Class<?> value();
String message() default "枚举值不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@Documented
@Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,那么在生成javadoc的时候就会把@Documented注解给显示出来。
@Retention
@Retention 用于设置注解(Annotation)的有效范围,描述了注解的生命周期。
Retention注解有一个属性value,是RetentionPolicy类型,RetentionPolicy有3个值
@Target
@Target 用于设置注解的作用范围,取值有:
@Constraint
@Constraint(validatedBy = EnumValidator.class) 中的validatedBy指定的是 @Enum 这个注解交由那个类去校验。
public class EnumValidatorClass implements ConstraintValidator<EnumValidator, Object>, Annotation {
private Logger log = LoggerFactory.getLogger(this.getClass());
private List<Object> values = new ArrayList<>();
@Override
public void initialize(EnumValidator enumValidator) {
Class<?> clz = enumValidator.value();
Object[] ojects = clz.getEnumConstants();
try {
Method method = clz.getMethod("getValue");
if (Objects.isNull(method)) {
throw new Exception(String.format("枚举对象{}缺少字段名为value的字段",
clz.getName()));
}
Object value = null;
for (Object obj : ojects) {
value = method.invoke(obj);
values.add(value);
}
} catch (Exception e) {
log.error("[处理枚举校验异常]", e);
}
}
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
return Objects.isNull(value) || StringUtils.isEmpty(value.toString()) || values.contains(value) ? true : false;
}
}
1、ConstraintValidator<Enum, Object>
第一个参数:是我们自定义的校验注解,此处是 Enum,是因为我们上方自定义的注解就是 @interface Enum 。
第二个参数:指的是页面上传递过来的具体的数据的类型。
2、isValid 方法需要保证线程安全,因为它可能是多线程调用。