Java Spring MVC和JSR-303 hibernate条件验证

Java Spring MVC和JSR-303 hibernate条件验证,java,spring,validation,spring-mvc,bean-validation,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 @Request

我有一张表格要确认。它包含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
问题是如果我使用LocalValidatoryFactoryBean验证器,我就不能重用Spring提供的BinidigResult对象。绑定无法工作,因为“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以接受要附加到字段名的字符串。。您有更好的方法吗?

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

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

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

首先,让我们看看API

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

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

不幸的是,如果需要验证某些组,则应该使用Spring本机验证程序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()); 
        }
    }

}
公共类BeanValidationValidator实现验证器{
javax.validation.Validator Validator=ValidatorUtil.getValidator();
私有类[]组;
公共BeanValidationValidator(类…组){
这个组=组;
}
公共无效验证(对象命令,错误){
Set constraintViolationSet=validator.validate(命令,组);
for(ConstraintViolation ConstraintViolation:constraintViolationSet){
errors.rejectValue(constraintViolation.getPropertyPath().toString(),null,constraintViolation.getMessage());
}
}
}

不幸的是@Valid没有组。不幸的是,请参阅我上面的评论。我认为这对规范来说是一个很好的补充,这种实用性应该优于理想主义。或者为了安抚理想主义者,我们应该停止称它为“Bean验证框架”,开始称它为“Java验证框架”,并在对象图之外添加对方法参数和返回值的支持。感谢axtavt,它起作用了。我想知道这是否是最好的方法,为什么@Valid中没有groups属性,如果JSR-303 groups概念是实现条件验证的唯一方法,
@Valid
中有对组的功能请求:我不同意将组添加到@Valid注释会破坏其用途。我认为这是一种改进@Valid表示“应验证此对象”。添加组实际上意味着“应该以这种方式验证此对象”。同样的语句没有理由不能应用于对象图的级联关联以及方法参数。此外,规范应该随着明显的有价值的补充而发展;向@Valid添加组将允许许多框架消除重复代码。规格应该有利于实用性而不是理想主义。