Spring MVC和JSR 303 - 手动验证

时间:2010-11-15 23:15:52

标签: java spring-mvc bean-validation

我正在使用Spring MVC 3和JSR 303.我有一个表单支持对象,其中包含不同类型的bean。根据请求参数值,我必须选择一个bean来验证和保存。我不能使用@Valid进行验证,因为在运行时之前不知道要验证的bean。

我能够向控制器注入一个javax.validation.Validator,但我不确定如何使用它来验证bean,并以“Spring方式”将任何错误存储在BindingResult/Error中。< / p>

由于请求映射,我需要在处理程序方法而不是initBinder方法中执行此操作。

[编辑]

我遇到validate(Object, Errors)的问题是它无法识别嵌套bean。要验证的bean是通过foo.getBar()。getBean()访问的,其中foo是表单后备对象。当我validate(foo.getBar().getBean(), errors)时,收到以下错误消息。

JSR-303 validated property 'property-name' does not have a corresponding accessor for Spring data binding

以前有人做过这样的事吗?感谢。

3 个答案:

答案 0 :(得分:5)

是的,你正在寻找的魔法类是org.springframework.validation.beanvalidation.SpringValidatorAdapter

此类获取一个注入其中的javax.validation.Validator,并包含代码,顾名思义,将输出“调整”回熟悉的Errors对象。当你将@Valid放在方法参数上时,它就是在内部用于处理的内容。

您可以通过在调度程序servlet中添加显式LocalValidatorFactoryBean来直接获取它们。只需注入一个实例作为标准Spring Validator接口的实例,就像使用'pre jsr-303'弹簧验证提供程序一样使用它。

答案 1 :(得分:4)

只是一个猜测,但你试过吗

 errors.pushNestedPath("bar.bean"); // Path to the nested bean
 validate(foo.getBar().getBean(), errors)
 errors.popNestedPath();

这就是BindingResult通常用于验证嵌套bean的方式。

答案 2 :(得分:0)

我看到这样做的方式是使用标准的JSR-303验证器(无论你注入的是什么)来获取违规行为(即Set<ConstraintViolaion<T>>

然后使用类似于LocalValidatorFactoryBean内部的代码来转换这些违规和Spring错误:

public static <T> void convert(Errors errors, Collection<ConstraintViolation<T>> violations) {
        for (ConstraintViolation<?> violation : violations) {
            String field = violation.getPropertyPath().toString();
            FieldError fieldError = errors.getFieldError(field);
            if (fieldError == null || !fieldError.isBindingFailure()) {
                errors.rejectValue(field, violation.getConstraintDescriptor().getAnnotation().annotationType()
                        .getSimpleName(), getArgumentsForConstraint(errors.getObjectName(), field, violation
                        .getConstraintDescriptor()), violation.getMessage());
            }
        }
    }

    private static Object[] getArgumentsForConstraint(String objectName, String field,
            ConstraintDescriptor<?> descriptor) {
        List<Object> arguments = new LinkedList<Object>();
        String[] codes = new String[] { objectName + Errors.NESTED_PATH_SEPARATOR + field, field };
        arguments.add(new DefaultMessageSourceResolvable(codes, field));
        arguments.addAll(descriptor.getAttributes().values());
        return arguments.toArray(new Object[arguments.size()]);
    }
相关问题