9

検証したいフォームがあります。2つのアドレス変数が含まれています。address1は常に検証する必要があり、address2はいくつかの条件に基づいて検証する必要があります

public class MyForm {
    String name;
    @Valid Address address1;
    Address address2;
 }

public class Address {
    @NotEmpty   
    private String street;
}

私のコントローラーは自動的に私のフォームobjを検証してバインドします

@RequestMapping(...)
public ModelAndView edit(
        @ModelAttribute("form")
        @Valid
        MyForm form,
        BindingResult bindingResult,
        ...)

        if(someCondition) {
            VALIDATE form.address2 USING JSR 303

問題は、LocalValidatorFactoryBeanバリデーターを使用すると、Springが提供するBinidingResultオブジェクトを再利用できないことです。'result'のターゲットオブジェクトが'MyForm'であり、'Address'ではないため、バインドは機能しません

validate(form.getAddress2(), bindingResult)   //won't work

条件付き検証を行うための標準/クリーンなアプローチは何でしょうか。

私は、コントローラーで新しいBindingResultをプログラムで作成することを考えていました。

final BindingResult bindingResultAddress2 = new BeanPropertyBindingResult(address2, "form");
validate(form.getAddress2(), bindingResultAddress2);

ただし、フィールド名が正しくないため('address2.street'ではなく'street')、バインディングが機能しないため、bindingResultAddress2から取得したエラーのリストを一般的な'bindingResult'に追加できません。

いくつかの汚いアプローチは、BeanPropertyBindingResultを拡張して、フィールド名に追加する文字列を受け入れることです。より良いアプローチはありますか?

4

3 に答える 3

5

階層構造を検証するための標準的なアプローチはpushNestedPath()/を使用するpopNestedPath()ことですが、JSR-303でどのように機能するかはわかりません。

bindingResult.pushNestedPath("address2");
validate(form.getAddress2(), bindingResult);
bindingResult.popNestedPath();
于 2010-10-25T12:32:37.053 に答える
1

私は自分自身を試したことがありませんが、正しいアプローチはバリデーターグループを使用することだと思います。

于 2010-10-25T14:14:28.827 に答える
0

まず、@javax.validation.ValidAPIを見てみましょう

関連付けをカスケードとしてマークします。関連するオブジェクトはカスケードによって検証されます。

Springフレームワークが@Validをマーカーとして使用してコマンドオブジェクトを検証すると、その目的が損なわれます。代わりに、Springは、検証する必要のあるグループを指定する独自のアノテーションを作成する必要があります。

残念ながら、一部のグループを検証する必要がある場合は、SpringネイティブのValidatorAPIを使用する必要があります

public void doSomething(Command command, Errors errors) {
    new BeanValidationValidator(SomeUserCase.class, OtherUserCase.class)
        .validate(command, errors);

    if(errors.hasErrors()) {

    } else {

    }
}

BeanValidationValidatorは次のように実装できます

public class BeanValidationValidator implements Validator {

    javax.validation.Validator validator = ValidatorUtil.getValidator();

    private Class [] groups;

    public BeanValidationValidator(Class... groups) {
        this.groups = groups;
    }

    public void validate(Object command, Errors errors) {
        Set<ConstraintViolation<Object>> constraintViolationSet = validator.validate(command, groups);

        for(ConstraintViolation<Object> constraintViolation: constraintViolationSet) {
            errors.rejectValue(constraintViolation.getPropertyPath().toString(), null, constraintViolation.getMessage()); 
        }
    }

}
于 2010-10-26T04:18:37.073 に答える