Java 将JSR-303验证错误转换为Spring';绑定结果

Java 将JSR-303验证错误转换为Spring';绑定结果,java,spring,validation,spring-mvc,bean-validation,Java,Spring,Validation,Spring Mvc,Bean Validation,我在Spring控制器中有以下代码: @Autowired 私有javax.validation.Validator验证程序; @RequestMapping(value=“/submit”,method=RequestMethod.POST) 公共字符串提交表单(自定义表单){ 设置错误=validator.validate(表单); ... } 是否可以将错误映射到Spring的BindingResult对象,而无需手动检查所有错误并将其添加到BindingResult?大概是这样的: /

我在Spring控制器中有以下代码:

@Autowired
私有javax.validation.Validator验证程序;
@RequestMapping(value=“/submit”,method=RequestMethod.POST)
公共字符串提交表单(自定义表单){
设置错误=validator.validate(表单);
...
}
是否可以将
错误
映射到Spring的
BindingResult
对象,而无需手动检查所有错误并将其添加到
BindingResult
?大概是这样的:

// NOTE: this is imaginary code
BindingResult bindingResult = BindingResult.fromConstraintViolations(errors);
我知道可以用
@Valid
注释
CustomForm
参数,并让Spring将
BindingResult
作为另一个方法的参数,但在我的例子中,这不是一个选项

// I know this is possible, but doesn't work for me
public String submitForm(@Valid CustomForm form, BindingResult bindingResult) {
    ...
}

一种更简单的方法是使用Spring的抽象
org.springframework.validation.Validator
,相反,您可以通过在上下文中使用这个bean来获得验证器:

<bean id="jsr303Validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

@Autowired @Qualifier("jsr303Validator") Validator validator;

Spring使用SpringValidatorAdapter将javax.validation.ConstraintViolation对象转换为ObjectError或FieldError对象,如绑定结果中所示。 BindStatus然后使用消息源(如web应用程序上下文本身)来转换错误。 简而言之,您可以:

SpringValidatorAdapter springValidator = new SpringValidatorAdapter(validator);
BindingResult bindingResult= new BeanPropertyBindingResult(myBeanToValidate, "myBeanName");
springValidator.validate(myBeanToValidate, bindingResult);

这在编写单元测试时更容易,因为您甚至不需要创建Spring上下文。

扩展Kristiaan的答案,出于测试目的,不需要创建Spring上下文来使用Spring的bindingResult进行验证。以下是一个例子:

public class ValidatorTest {

    javax.validation.Validator javaxValidator = Validation.buildDefaultValidatorFactory().getValidator();
    org.springframework.validation.Validator springValidator = new SpringValidatorAdapter(javaxValidator);

    @Test
    public void anExampleTest() {

    JSR303AnnotatedClassToTest   ctt  = new JSR303AnnotatedClassToTest( ..init vars..)

    ... test setup...

    WebDataBinder dataBinder = new WebDataBinder(ctt);
    dataBinder.setValidator(springValidator);
    dataBinder.validate();
    BindingResult bindingResult = dataBinder.getBindingResult(); 

    ... test analysis ...

    }
}
这种方法不需要提前创建绑定结果,dataBinder会为您构建正确的绑定结果

@RequestMapping(value=“/submit”,method=RequestMethod.POST)
公共字符串提交表单(自定义表单){
设置错误=validator.validate(表单);
BindingResult BindingResult=toBindingResult(错误,形式,“形式”);
...
}
私有BindingResult到BindingResult(ConstraintViolationException e、对象对象、字符串对象名){
BindingResult BindingResult=新BeanPropertyBindingResult(对象,对象名);
新的AddConstraintViolationsToErrors().addConstraintViolations(例如getConstraintViolations(),bindingResult);
返回绑定结果;
}
私有静态类AddConstraintViolationsToErrors扩展了SpringValidatorAdapter{
public AddConstraintViolationsToErrors(){
super(Validation.buildDefaultValidatorFactory().getValidator());//实际未使用验证程序
}
@SuppressWarnings({“rawtypes”,“unchecked”})
公共void addConstraintViolations(集合>冲突、错误){
//使用原始类型,因为processConstraintViolations特别需要ConstraintViolation
super.processConstraintViolations((设置)冲突、错误);
}
}

与此问题的其他答案不同,此解决方案处理已存在
setThank的情况!这肯定更简洁。我没有看到接受BindingResulti的方法validate如果没有看到接受绑定结果的validate方法,这意味着您的验证器验证器是javax.validation.Validator。将其更改为org.springframework.validation.Validator,您就会没事了。无需更改bean定义。
public class ValidatorTest {

    javax.validation.Validator javaxValidator = Validation.buildDefaultValidatorFactory().getValidator();
    org.springframework.validation.Validator springValidator = new SpringValidatorAdapter(javaxValidator);

    @Test
    public void anExampleTest() {

    JSR303AnnotatedClassToTest   ctt  = new JSR303AnnotatedClassToTest( ..init vars..)

    ... test setup...

    WebDataBinder dataBinder = new WebDataBinder(ctt);
    dataBinder.setValidator(springValidator);
    dataBinder.validate();
    BindingResult bindingResult = dataBinder.getBindingResult(); 

    ... test analysis ...

    }
}