2

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

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

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

[编辑]

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

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

有没有人做过这样的事情?谢谢。

4

3 回答 3

5

是的,你要找的魔法课是org.springframework.validation.beanvalidation.SpringValidatorAdapter

这个类得到一个注入它的 javax.validation.Validator 并包含代码,顾名思义,将输出“调整”回熟悉的Errors对象。@Valid当您放置方法参数 时,它就是在内部用来进行处理的东西。

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

于 2010-11-15T23:28:30.960 回答
4

只是一个猜测,但你有没有试过

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

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

于 2010-11-16T12:49:17.697 回答
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()]);
    }
于 2010-11-16T09:15:36.627 回答