2010-11-15 83 views
2

我正在使用Spring MVC 3和JSR 303.我有一个表单支持对象,它有不同类型的bean。根据请求参数值,我将不得不选择一个bean来验证和保存。我不能使用@Valid进行验证,因为直到运行时才能确认要验证的bean。Spring MVC和JSR 303 - 手动验证

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

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

[编辑]

我与validate(Object, Errors)遇到的问题是,它并不能识别嵌套豆。要验证的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 

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

回答

4

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

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

BindingResult通常用于验证嵌套的bean。

5

是啊,你要寻找的魔术类是org.springframework.validation.beanvalidation.SpringValidatorAdapter

该类获得一个javax.validation.Validator注入,并包含了代码,顾名思义,“适应”输出回熟悉的Errors对象。当您将@Valid放在方法参数上时,它就是内部用来执行处理的内容。

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

+0

谢谢,但仍然没有运气。你能看到编辑? – 2010-11-15 23:49:07

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()]); 
    }