用法
其实这个注解最多也就两个用处,第一个就是被该注解注释的方法会在相应的controller中的任何一个方法执行之前执行一遍,直接贴代码吧
@ModelAttribute
public void getUser(Map<String, Object> map){
User user=new User("xhj", "123456", "23");
map.put("user", user);
}
@RequestMapping("testModelAttribute")
public String testModelAttribute(User user){
System.out.println("修改:"+user);
return SUCCESS;
}
当执行testModelAttribute方法时,SpringMVC会先执行getUser方法,通过map将其得到的user放到请求域中,然后找到名字同样叫user的对象作为入参传递给testModelAttribute方法。这里需要注意的是第一个方法中放入map的key值应该和第二个方法中入参的参数名一致,如果必须不一致的话这里就牵扯到第二个用法了(个人觉得也不算第二个用法),代码如下
@ModelAttribute
public void getUser(Map<String, Object> map){
User user=new User("xhj", "123456", "23");
map.put("xx", user);
}
@RequestMapping("testModelAttribute")
public String testModelAttribute(@ModelAttribute("xx")User user){
System.out.println("修改:"+user);
return SUCCESS;
}
在第二个方法的入参前面加入@ModelAttribute注解,SpringMVC会去请求域中找名为xx的User对象。
原理
想要知道这货的原理当然得去阅读源代码,考虑到过程有点复杂这里就直接将楼主的理解和心得贴出来分享给大家吧。
*1. 确定一个 key:
* 1). 若目标方法(第二个方法)的 POJO 类型的参数木有使用 @ModelAttribute 作为修饰, 则 key 为 POJO 类名第一个字母的小写
* 2). 若使用了 @ModelAttribute 来修饰, 则 key 为 @ModelAttribute 注解的 value 属性值.
* 2. 在 implicitModel 中查找 key 对应的对象, 若存在, 则作为入参传入
* 1). 若在 @ModelAttribute 标记的方法中在 Map 中保存过, 且 key 和 1 确定的 key 一致, 则会获取到.
* 3. 若 implicitModel 中不存在 key 对应的对象, 则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰, 若使用了该注解, 且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从 HttpSession 中来获取 key 所对应的 value 值, 若存在则直接传入到目标方法的入参中. 若不存在则将抛出异常.
* 4. 若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 则会通过反射来创建 POJO 类型的参数, 传入为目标方法的参数
* 5. SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中.
注意
最后还要多嘴一句,如果你是将这个注解跟@SessionAttributes注解一起使用的话,一不小心就会抛出这样的异常
发生这样错误的代码我也贴出来吧
@SessionAttributes(value={"user"})
@Controller
public class HelloWorld {
public static final String SUCCESS="success";
@RequestMapping("testModelAttribute")
public String testModelAttribute(@ModelAttribute("user")User user){
System.out.println("修改:"+user);
return SUCCESS;
}
}
原因其实在上面的原理中写的很明白了,这里就不再多说了,大家都是聪明人。