我有一个我要验证的表单。它包含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以接受一些字符串附加到字段名称..你有更好的方法吗?
答案 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 APIpublic 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());
}
}
}