Spring MVC中@Pattern校验重复报错问题咨询
我来帮你搞定这个问题!你遇到的情况是因为Spring MVC默认会复用@ModelAttribute绑定的对象,加上验证失败后直接转发回表单页面,导致旧的错误状态被保留在会话或Model中,即使提交有效输入也会显示历史错误。下面是具体的排查和解决步骤:
核心原因分析
当你提交无效输入触发验证错误时,Spring会把带有错误信息的BindingResult和student1对象存入Model并转发回表单页面。如果后续刷新页面再提交有效输入,浏览器可能会重复发送之前的请求,或者Spring复用了之前存在会话里的student1对象,导致旧的错误信息被重复渲染。
解决方案
1. 验证成功时使用重定向(最关键)
直接转发到成功页面会导致浏览器URL不变,刷新时会重复提交POST请求,而且旧的Model数据会被保留。改用重定向可以彻底解决这个问题:
修改你的Controller方法:
@RequestMapping(value = "/submitAdmissionForm.html", method = RequestMethod.POST) public String submitAdmissionForm(@Valid @ModelAttribute("student1") Student student, BindingResult result) { if (result.hasErrors()) { // 验证失败,返回表单页面,显示当前请求的错误 return "AdmissionForm"; } // 验证成功,重定向到成功页面(使用redirect:前缀) return "redirect:admissionSuccess.html"; } // 新增处理成功页面的GET请求方法 @RequestMapping("/admissionSuccess.html") public String showAdmissionSuccess() { return "AdmissionSuccess"; }
重定向后浏览器URL会更新为admissionSuccess.html,刷新页面只会发送GET请求,不会重复提交表单,同时旧的Model数据也会被清空。
2. 每次请求生成新的Student实例
添加一个@ModelAttribute方法,确保每次请求都创建全新的Student对象,避免复用带有错误状态的旧对象:
@Controller public class AdmissionController { // 每次请求都初始化新的Student对象 @ModelAttribute("student1") public Student initStudent() { return new Student(); } // 你的POST提交方法... }
3. 确保页面正确渲染当前错误
检查你的表单页面(比如JSP)是否正确绑定到当前的BindingResult,示例代码如下:
<form:form modelAttribute="student1" action="submitAdmissionForm.html" method="post"> <label>Student Name:</label> <form:input path="studentName" /> <!-- 只显示当前请求的错误信息 --> <form:errors path="studentName" cssClass="error" /> <input type="submit" value="Submit" /> </form:form>
如果使用其他模板引擎(如Thymeleaf),也要确保错误信息是从当前请求的BindingResult中获取,而不是缓存数据。
额外注意:如果使用了@SessionAttributes
如果你在Controller上添加了@SessionAttributes("student1")来跨请求存储对象,验证成功后需要手动清除会话属性:
@RequestMapping(...) public String submitForm(@Valid @ModelAttribute("student1") Student student, BindingResult result, SessionStatus status) { if (result.hasErrors()) { return "AdmissionForm"; } // 清除会话中存储的student1对象 status.setComplete(); return "redirect:admissionSuccess.html"; }
按照上面的步骤修改后,应该就能彻底清除历史绑定错误,提交有效输入时不会再显示旧的错误信息了。
内容的提问来源于stack exchange,提问作者Sanjay Katta

