Spring MVC和JSR-303 hibernate条件验证

时间:2010-10-25 09:43:38

标签: java spring validation spring-mvc bean-validation

我有一个我要验证的表单。它包含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);

但是我从bindingResultAddress2获得的错误列表无法添加到一般的'bindingResult',因为字段名称不正确('street'而不是'address2.street')并且绑定将不起作用

一些肮脏的方法是扩展BeanPropertyBindingResult以接受一些字符串附加到字段名称..你有更好的方法吗?

3 个答案:

答案 0 :(得分:5)

验证层次结构的标准方法是使用pushNestedPath() / popNestedPath(),但我不确定它如何与JSR-303一起使用:

bindingResult.pushNestedPath("address2");
validate(form.getAddress2(), bindingResult);
bindingResult.popNestedPath();

答案 1 :(得分:1)

我从未尝试过自己,但我认为正确的方法是使用validator groups

答案 2 :(得分:0)

首先,让我们看看@javax.validation.Valid API

  

将关联标记为级联。关联的对象将通过级联验证。

当Spring框架使用@Valid 作为标记来验证其命令对象时,它会破坏其目的。 Spring应该创建自己的特定注释,指定应该验证的组。

不幸的是,如果需要验证某些组

,则应使用Spring本机Validator API
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()); 
        }
    }

}
相关问题