参考资料:spring-framework-reference的Using @ModelAttribute on a method和Using @ModelAttribute on a method argument 先看一个没有使用@ModelAttribute的Controller方法. @RequestMapping("/save") public String save(User user) { user.setUsername("U love me"); userService.save(user); return "result"; } 其中User包含id和username两个私有属性,含有公共setter和getter方法. 执行此方法时会将key为"user"(注意:这里即便参数名称是user1,key同样仍是"user"),value为user的对象加入到model.在jsp页面能够经过${user.id}和${user.name}获得值的,即上面方法和下面方法是至关的. @RequestMapping("/save") public String save(Model model,int id,String username) { User user=new User(); //这里是经过反射从request里面拿值再set到user user.setId(id); user.setUsername(username); model.addAttribute("user",user); user.setUsername("U love me"); userService.save(user); return "result"; } 一.下面再来看看@ModelAttribute的基本用法. 1.在方法上使用@ModelAttribute @ModelAttribute("user1") public User addUser(User user) { return new User(520,"I love U"); } 假设此方法是写在UserController内,那么执行UserController内带有@RequestMapping的方法以前,都会先执行此addUser方法.而且执行addUser过程当中会添加两个对象到model,先将key为"user"的对象(由addUser方法的User user引发的),再添加key为"user1"的对象(由注解@ModelAttribute("user1")引发的). 2.在方法参数上使用@ModelAttribute. @RequestMapping("/save") public String save(@ModelAttribute User user) { user.setUsername("U love me"); userService.save(user); return "result"; } 此方法会先从model去获取key为"user"的对象,若是获取不到会经过反射实例化一个User对象,再从request里面拿值set到这个对象,而后把这个User对象添加到model(其中key为"user"). 使用了@ModelAttribute可修改这个key,不必定是"user",此状况下,用与不用@ModelAttribute没有区别. 3.再来看看在方法和方法参数上结合使用@ModelAttribute,即上面两步的两个方法都添加UserController,以下: @ModelAttribute("user1") public User addUser(User user) { return new User(520,"I love U"); } @RequestMapping("/save") public String save(@ModelAttribute User user) { user.setUsername("U love me"); userService.save(user); return "result"; } 假设要执行保存用户操做,根据一分析可知,先执行完会产生两个User类型的对象(一个key是"user",另外一个key是"user1")添加到model,再执行save方法,此时会先从model去找key为"user"的对象,能找到再从request取值set到这个User对象.最后返回到jsp页面,model里也只有两个User类型对象. 再来个小小假设,将上面@ModelAttribute("user1")的user1改成user,其它不变.虽然执行了addUser方法,那么执行到save方法内,user对象的字段值仍是来源于请求,最后返回到jsp页面,model里也只有一个User类型对象. 4.另类: @ModelAttribute @RequestMapping("/save") public String save(@ModelAttribute User user) { user.setUsername("U love me"); userService.save(user); return "result"; } 此种状况,会添加一个key为"user"的User对象到model,还会添加一个key为"string",value为"result"的对象到model,而视图名称则变为了"save"而不是"result".相信通常开发者都不会这样用. 二.下面再看看结合@SessionAttributes的用法. 1.先看看这段代码 @Controller @RequestMapping("user") @SessionAttributes("test") public class UserController { @RequestMapping(value = "test1") public String test1(Map<String, Object> model, SessionStatus sessionStatus) { model.put("test","something"); //sessionStatus.setComplete(); return "user/list"; } @RequestMapping(value = "test2") public String test2(Map<String,?> model) { Object test = model.get("test"); System.out.println(test); return "user/list"; } } 在类级别上使用@SessionAttributes("test"),它的做用是在controller共享 model 属性,直到调用org.springframework.web.bind.support.SessionStatus#setComplete会清除此session值.不然长期保留(session过时,这个值也再也不保留).所以先调用/user/test1,再调用/user/test2.在test2方法能获得test1方法put进去的值.当移除上面的注解,由于属性为test的session也被清除了,因此test2方法会获得是null. 2.再看结合@ModelAttribute的用法. @Controller @RequestMapping("user") @SessionAttributes("test") public class UserController { @RequestMapping(value = "test1") public String test1(HttpServletRequest request) { User user = new User("xiejx618"); request.getSession().setAttribute("test",user); return "user/list"; } @RequestMapping(value = "test2") public String test2(@ModelAttribute("test") User user,SessionStatus sessionStatus) { System.out.println(user.getUsername()); sessionStatus.setComplete(); return "user/list"; } } 同样先调用/user/test1,再调用/user/test2.在test2方法能获得test1方法set进去的值.使用了@SessionAttributes,若是在controller的方法参数上有@ModelAttribute,那么此方法会确保属性test的session会存在,不然会抛org.springframework.web.HttpSessionRequiredException异常,即上面代码先不调/user/test1,直接调/user/test2就会抛此异常