【问题标题】:Spring MVC and JSR 303 - Manual ValidationSpring MVC 和 JSR 303 - 手动验证
【发布时间】:2011-05-10 13:00:49
【问题描述】:

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

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

由于请求映射,我需要在处理程序方法中而不是 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

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

【问题讨论】:

    标签: java spring-mvc bean-validation


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      我看到的方法是使用标准的 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()]);
          }
      

      【讨论】:

        【解决方案3】:

        只是猜测,但你试过吗

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

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

        【讨论】:

          猜你喜欢
          • 2011-04-30
          • 1970-01-01
          • 2018-08-15
          • 1970-01-01
          • 2014-09-28
          • 2013-11-23
          • 2013-12-27
          • 2012-02-08
          • 2011-07-21
          相关资源
          最近更新 更多