为什么BindingResult必须关注@Valid?

far*_*lmr 9 java validation spring spring-mvc

当我遇到错误时,我很难让我的Spring MVC验证返回页面提交页面.我终于解决了这个问题,注意到BindingResult需要在我正在验证的表单参数旁边.

例如,如果我将spring.io教程(http://spring.io/guides/gs/validating-form-input/)中的checkPersonInfo方法修改为 -

@RequestMapping(value="/", method=RequestMethod.POST)
public String checkPersonInfo(@Valid Person person, BindingResult bindingResult, Model model) {
    if (bindingResult.hasErrors()) {
        return "form";
    }
    return "redirect:/results";
}
Run Code Online (Sandbox Code Playgroud)

然后它将工作并重定向到表单页面,但如果我将其更改为 -

@RequestMapping(value="/", method=RequestMethod.POST)
public String checkPersonInfo(@Valid Person person, Model model, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        return "form";
    }
    return "redirect:/results";
}
Run Code Online (Sandbox Code Playgroud)

然后它重定向到/ errors

这是什么原因?

Hen*_*nry 12

BindingResult先后跟随绑定的对象.原因是如果你有更多被绑定的对象,你必须知道BindingResult哪个对象属于哪个对象.


zhu*_*wei 6

是的,今天我花了很长时间检查为什么无法返回到提交的页面而是进入默认的可白标错误页面。

调试后得到源码

// org.springframework.web.method.annotation.ModelAttributeMethodProcessor#resolveArgument
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
    throw new BindException(binder.getBindingResult());
}
Run Code Online (Sandbox Code Playgroud)

如果BindingResult不遵循@Valid,会导致isBindExceptionRequired(binder, parameter)返回true,然后直接抛出异常,因此无法执行控制器方法中的代码。

// org.springframework.web.method.annotation.ModelAttributeMethodProcessor#isBindExceptionRequired 
protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter methodParam) {
    int i = methodParam.getParameterIndex();
    Class<?>[] paramTypes = methodParam.getMethod().getParameterTypes();
    boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));
    return !hasBindingResult;
}  
Run Code Online (Sandbox Code Playgroud)