Spring MVC中@ModelAttribute方法参数的工作机制及问题咨询
解答
@ModelAttribute核心执行流程
- 前置方法执行:请求进入Controller后,所有标注
@ModelAttribute的方法(比如代码中的addAccount)会优先执行,将对象存入Model容器。 - 目标方法参数处理:
- 当目标方法参数带有
@ModelAttribute("name")时,Spring先从Model中查找key为name的对象。 - 若找到该对象,自动将请求中的参数(如表单、URL参数)通过setter方法绑定到该对象的对应属性上。
- 若未找到,则实例化一个新对象,绑定请求参数后存入Model。
- 当目标方法参数带有
场景差异原因分析
1. test方法(/hello请求)
- 请求为GET类型,没有携带任何表单或URL参数。
- 流程:先执行
addAccount将username=zeus,password=123的Account存入Model;处理test方法参数时,从Model取出zeus对象,因无参数可绑定,对象保持初始值,所以输出预期结果。
2. checkLog方法(POST /login请求)
- 请求为POST类型,携带了表单提交的
username和password参数。 - 流程:同样先执行
addAccount存入初始zeus对象;处理checkLog方法参数时,Spring取出Model中的zeus对象后,立即把表单参数赋值给对象的对应属性,覆盖了原来的zeus和123,最终输出用户提交的参数值。
可选解决方案(如需保留Model初始值)
如果希望不覆盖Model中的zeus对象,同时获取表单参数,可改用@RequestParam单独接收:
@RequestMapping(method = RequestMethod.POST, value = "/login") public String checkLog(@RequestParam String username, @RequestParam String password, @ModelAttribute("zeus") Account u) { System.out.println(u); // 输出Model中初始的zeus对象 System.out.println("提交的用户名:" + username + ",密码:" + password); return "hello"; }
或者,将表单的modelAttribute改为其他名称(比如userForm),让Spring新建一个Account对象绑定表单参数,避免影响Model中的zeus对象。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

