@RequestMapping(value = "/submit", method = RequestMethod.POST)
public String submitForm(CustomForm form) {
Set<ConstraintViolation<CustomForm>> errors = validator.validate(form);
BindingResult bindingResult = toBindingResult(errors, form, "form");
...
}
private BindingResult toBindingResult(ConstraintViolationException e, Object object, String objectName) {
BindingResult bindingResult = new BeanPropertyBindingResult(object, objectName);
new AddConstraintViolationsToErrors().addConstraintViolations(e.getConstraintViolations(), bindingResult);
return bindingResult;
}
private static class AddConstraintViolationsToErrors extends SpringValidatorAdapter {
public AddConstraintViolationsToErrors() {
super(Validation.buildDefaultValidatorFactory().getValidator()); // Validator is not actually used
}
@SuppressWarnings({"rawtypes", "unchecked"})
public void addConstraintViolations(Set<? super ConstraintViolation<?>> violations, Errors errors) {
// Using raw type since processConstraintViolations specifically expects ConstraintViolation<Object>
super.processConstraintViolations((Set) violations, errors);
}
}
与此问题的其他答案不同,此解决方案处理已经存在 aSet<ConstraintViolation<?>>
需要转换为 a 的情况BindingResult
。
解释
Spring 提供了SpringValidatorAdapter
执行 bean 验证的类,将结果存储在Errors
实例中(注意BindingResult
extends Errors
)。此类的正常手动使用是使用它通过以下validate
方法执行验证:
Validator beanValidator = Validation.buildDefaultValidatorFactory().getValidator();
SpringValidatorAdapter validatorAdapter = new SpringValidatorAdapter(beanValidator);
BindException bindException = new BindException(form, "form");
validatorAdapter.validate(form, bindException);
但是,这在已经存在 aSet<ConstraintViolation<?>>
需要转换为 a的情况下无济于事BindingResult
。
仍然有可能实现这个目标,尽管它确实需要跳过几个额外的箍。 SpringValidatorAdapter
包含processConstraintViolations
将ConstraintViolation
对象转换为适当的 SpringObjectError
子类型并将它们存储在Errors
对象上的方法。但是,此方法是受保护的,限制了它对子类的可访问性。
这个限制可以通过创建一个自定义子类来解决,该子类SpringValidatorAdapter
委托或公开受保护的方法。这不是典型的用法,但它有效。
public class AddConstraintViolationsToErrors extends SpringValidatorAdapter {
public AddConstraintViolationsToErrors() {
super(Validation.buildDefaultValidatorFactory().getValidator()); // Validator is not actually used
}
@SuppressWarnings({"rawtypes", "unchecked"})
public void addConstraintViolations(Set<? super ConstraintViolation<?>> violations, Errors errors) {
// Using raw type since processConstraintViolations specifically expects ConstraintViolation<Object>
super.processConstraintViolations((Set) violations, errors);
}
}
这个自定义类可以用来填充一个新创建BindingResult
的,实现BindingResult
从一个创建一个的目标Set<ConstraintViolation<?>>
。
private BindingResult toBindException(ConstraintViolationException e, Object object, String objectName) {
BindingResult bindingResult = new BeanPropertyBindingResult(object, objectName);
new AddConstraintViolationsToErrors().addConstraintViolations(e.getConstraintViolations(), bindingResult);
return bindingResult;
}