Spring验证器无法查找类级别约束的值

时间:2016-05-17 15:08:17

标签: spring bean-validation hibernate-validator

我在JSR 303级别验证和spring时遇到错误,我想知道我是否以正确的方式进行设置。

我在spring(4.2.6.RELEASE)中使用hibernate-validator(5.2.4.Final)进行验证,在弹簧控制器内部进行典型设置,如:

@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public SomeDto update(@PathVariable Integer id, @Valid @RequestBody SomeDto someDto) {
    ...
    return someDto; 
}

这适用于大多数设置,但是当验证目标包含一组使用类级别验证注释的对象时,SpringValidatorAdaptor在尝试查找原始值时失败

以下代码说明了问题:

要验证的目标类:

public class Base {
@Valid
Set<MyClass> myClassSet = new HashSet<>();

public Set<MyClass> getMyClassSet() {
    return myClassSet;
}

具有类级别验证注释的类:

@CheckMyClass
public class MyClass {
    String a;
    String b;

    public MyClass(final String a, final String b) {
        this.a = a;
        this.b = b;
    }
}

约束:

@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = CheckMyClassValidator.class)
@Documented
public @interface CheckMyClass {

    String message() default "Invalid class";

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

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

验证

public class CheckMyClassValidator implements ConstraintValidator<CheckMyClass, MyClass> {

    @Override
    public void initialize(final CheckMyClass constraintAnnotation) {

    }

    @Override
    public boolean isValid(final MyClass value, final ConstraintValidatorContext context) {
        return false; // want it to fail for testing purposes
    }
}

测试类:

@SpringBootApplication
public class SpringValidationTest {

    @Bean
    public org.springframework.validation.Validator validator() {
        return new org.springframework.validation.beanvalidation.LocalValidatorFactoryBean();
    }

    private void doStandardValidation() {
        Base base = createBase();
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<Base>> violations = validator.validate(base);
        for (ConstraintViolation<?> violation : violations) {
            System.out.println(violation.getMessage());
        }
    }

    private Base createBase() {
        Base base = new Base();
        base.getMyClassSet().add(new MyClass("a1", "b1"));
//        base.getMyClassSet().add(new MyClass("a2", "b2"));
        return base;
    }

    @PostConstruct
    private void doSpringValidation() {
        Base base = createBase();
        org.springframework.validation.Validator validator = validator();
        DataBinder binder = new DataBinder(base);
        binder.setValidator(validator);
        binder.validate();

        BindingResult results = binder.getBindingResult();
        for (ObjectError error : results.getAllErrors()) {
            System.out.println(error.getDefaultMessage());
        }
    }

    public static void main(String[] args) {
        (new SpringValidationTest()).doStandardValidation();
        System.out.println();
        ApplicationContext applicationContext =     SpringApplication.run(SpringValidationTest.class);
    }
}

标准验证工作正常,但是当它被弹簧验证器包装时(如在典型的控制器设置中),它最终会出现异常(如下所示),试图查找属性的值:

Caused by: java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.8.0_45]
    at java.lang.Integer.parseInt(Integer.java:592) ~[na:1.8.0_45]
    at java.lang.Integer.parseInt(Integer.java:615) ~[na:1.8.0_45]
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:657) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    ... 37 common frames omitted

0 个答案:

没有答案