Spring Boot自定义校验注解校验List失效,抛出异常问题排查
自定义Spring Boot校验注解无法校验List集合的问题
我在开发Spring Boot项目时,尝试实现一个自定义校验注解SampleValid,期望能同时校验对象的单个字段和List集合,但当前实现无法正常工作,校验List时会抛出异常,单个对象校验则正常。
自定义注解代码
@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(); } }
校验器代码
public class SampleValidator implements ConstraintValidator<SampleValid, Object> { private String fieldName; public void initialize(SampleValid constraintAnnotation) { fieldName = constraintAnnotation.name(); } public boolean isValid(Object value, ConstraintValidatorContext context) { if (value == null) return true; try { String fieldValue = BeanUtils.getProperty(value, fieldName); if (/* 这里是你的校验逻辑 */) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()) .addConstraintViolation(); return false; } } catch (Exception ex) { return false; } return true; } }
使用示例与报错
@SampleValid private List<SomeObject> someObjects; // 此用法报错 @SampleValid private SomeObject someObject; // 此用法正常
报错信息:
java.lang.NoSuchMethodException: Unknown property 'name' on class 'class java.util.ArrayList'
问题原因
- 当注解标注在
List字段上时,校验器接收的value是ArrayList实例,而你的校验逻辑直接调用BeanUtils.getProperty(value, fieldName)尝试获取name属性,但ArrayList本身并没有这个属性,因此抛出异常。 - 当前校验器没有区分单个对象和集合类型,默认将所有传入值当作单个对象处理,没有遍历集合内的元素进行逐个校验。
修复方案
修改SampleValidator的isValid方法,先判断传入值是否为集合/数组类型,若是则遍历每个元素执行校验逻辑;若为单个对象则直接校验:
public class SampleValidator implements ConstraintValidator<SampleValid, Object> { private String fieldName; public void initialize(SampleValid constraintAnnotation) { fieldName = constraintAnnotation.name(); } public boolean isValid(Object value, ConstraintValidatorContext context) { if (value == null) return true; // 处理集合/数组类型 if (value instanceof Collection) { Collection<?> collection = (Collection<?>) value; for (Object element : collection) { if (!validateSingleElement(element, context)) { return false; } } } else if (value.getClass().isArray()) { Object[] array = (Object[]) value; for (Object element : array) { if (!validateSingleElement(element, context)) { return false; } } } else { // 处理单个对象 return validateSingleElement(value, context); } return true; } // 抽取单个对象的校验逻辑 private boolean validateSingleElement(Object element, ConstraintValidatorContext context) { if (element == null) return true; try { String fieldValue = BeanUtils.getProperty(element, fieldName); if (/* 这里替换为你的实际校验逻辑 */) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()) .addConstraintViolation(); return false; } } catch (Exception ex) { return false; } return true; } }
内容的提问来源于stack exchange,提问作者H Athukorala
相关产品推荐
相关产品推荐

