为啥 BindingResult 必须遵循 @Valid?
Posted
技术标签:
【中文标题】为啥 BindingResult 必须遵循 @Valid?【英文标题】:Why does BindingResult have to follow @Valid?为什么 BindingResult 必须遵循 @Valid? 【发布时间】:2015-05-07 09:48:06 【问题描述】:当我遇到错误时,我正在努力让我的 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";
然后它将工作并重定向到表单页面,但如果我将其更改为 -
@RequestMapping(value="/", method=RequestMethod.POST)
public String checkPersonInfo(@Valid Person person, Model model, BindingResult bindingResult)
if (bindingResult.hasErrors())
return "form";
return "redirect:/results";
然后它重定向到 /errors
这是什么原因?
【问题讨论】:
【参考方案1】:BindingResult
必须跟随绑定的对象。原因是如果绑定的对象比较多,就必须知道哪个BindingResult
属于哪个对象。
【讨论】:
在这种情况下,如果我有多个要验证的对象,那么我是否必须添加多个 @Valid? 是的,Valid
注解属于指定的参数。【参考方案2】:
您的请求处理程序中可能有多个模型属性,每个属性都有自己的绑定结果。为了适应这一点,Spring 决定将绑定结果参数绑定到前一个参数。
【讨论】:
【参考方案3】:是啊,今天查了好久,为什么不能返回提交的页面,而是进入一个默认的whitelable错误页面。
调试后得到源代码
// org.springframework.web.method.annotation.ModelAttributeMethodProcessor#resolveArgument
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter))
throw new BindException(binder.getBindingResult());
如果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;
【讨论】:
我的调试问题完全相同。错误消息根本没有信息!以上是关于为啥 BindingResult 必须遵循 @Valid?的主要内容,如果未能解决你的问题,请参考以下文章
使用@Valid+BindingResult进行controller参数校验