Java Spring MVC和JSR-303 hibernate条件验证
我有一张表格要确认。它包含2个地址变量。address1必须始终进行验证,address2必须根据某些条件进行验证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
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添加组将允许许多框架消除重复代码。规格应该有利于实用性而不是理想主义。