簡體   English   中英

Spring MVC和JSR 303 - 手動驗證

[英]Spring MVC and JSR 303 - Manual Validation

我正在使用Spring MVC 3和JSR 303.我有一個表單支持對象,其中包含不同類型的bean。 根據請求參數值,我必須選擇一個bean來驗證和保存。 我無法使用@Valid進行驗證,因為要運行時才知道要驗證的bean。

我能夠向控制器注入一個javax.validation.Validator ,但我不知道如何用它來驗證bean並在“Spring方式” BindingResult/Error任何錯誤存儲在BindingResult/Error中。

由於請求映射,我需要在處理程序方法而不是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

以前有人做過這樣的事嗎? 謝謝。

是的,你正在尋找的魔法類是org.springframework.validation.beanvalidation.SpringValidatorAdapter

該類獲取一個注入其中的javax.validation.Validator,並包含代碼,顧名思義,將輸出“調整”回熟悉的Errors對象。 當你將@Valid放在方法參數上時,它就是在內部用來進行處理的。

您可以通過在調度程序servlet中添加顯式LocalValidatorFactoryBean來直接獲取它們。 只需注入一個實例作為標准Spring Validator接口的實例,並像使用任何'pre jsr-303'彈簧驗證提供程序一樣使用它。

只是一個猜測,但你有沒有嘗試過

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

這就是BindingResult通常用於驗證嵌套bean的方式。

我看到這樣做的方式是使用標准的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()]);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM