2010-11-15 36 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()]); 
    }