Spring Boot 自定义验证注解不起作用

问题描述 投票:0回答:1

我目前正在开发一个 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'

有人可以帮助我理解为什么我当前的实施没有按预期工作吗?预先感谢。

java spring spring-boot constraints
1个回答
0
投票

您面临的问题是因为您试图直接访问列表的“名称”属性

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;
© www.soinside.com 2019 - 2024. All rights reserved.