我目前正在开发一个 Spring Boot 项目,并尝试实现一个自定义验证注释,该注释应该能够验证对象的单个字段和对象的字段列表。但是,我当前的实现似乎没有按预期工作。我正在寻求有关如何使其正常工作的指导。
示例有效类
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = SampleValidator.class)
@Repeatable(SampleValid.List.class)
@Documented
public @interface SampleValid {
String name() default "name";
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List {
SampleValid[] value();
}
}
SampleValidator 类
public class SampleValidator implements ConstraintValidator<SampleValid, Object> {
private String fieldName;
public void initialize(SampleValid constraintAnnotation) {
name = constraintAnnotation.name();
}
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (value == null) return true;
try {
String fieldValue = BeanUtils.getProperty(value, name);
if (some validation goes here) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate())
.addConstraintViolation();
return false;
}
} catch (Exception ex) {
return false;
}
return true;
}
}
因此,当我使用它来验证列表时,它会抛出一个错误,
@SampleValid
private List<SomeObject> someObjects;
java.lang.NoSuchMethodException:类上的未知属性“名称” '类 java.util.ArrayList'
有人可以帮助我理解为什么我当前的实施没有按预期工作吗?预先感谢。
您面临的问题是因为您试图直接访问列表的“名称”属性
List<SomeObject> someObjects
,但列表没有“名称”属性。
您的自定义验证注释和验证器旨在验证单个对象的属性,而不是列表本身的属性。
如果要验证列表中对象的属性,您应该迭代列表并单独验证每个对象。
我正在考虑对你的
SampleValidator
类进行这样的修改:
public class SampleValidator implements ConstraintValidator<SampleValid, Object> {
private String fieldName;
public void initialize(SampleValid constraintAnnotation) {
fieldName = constraintAnnotation.fieldName();
}
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (value == null) return true;
if (value instanceof List) {
List<?> list = (List<?>) value;
for (Object item : list) {
if (item != null) {
try {
String className = item.getClass().getSimpleName();
String fieldValue = BeanUtils.getProperty(item, fieldName);
// Perform your validation here
if (some validation goes here) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(className + context.getDefaultConstraintMessageTemplate())
.addConstraintViolation();
return false;
}
} catch (Exception ex) {
return false;
}
}
}
}
return true;
}
}
在这种情况下,您的验证器将迭代列表并单独验证每个对象的“名称”属性,如下所示:
@SampleValid
private List<SomeObject> someObjects;