文章目录
除了传入原生request和session,SpringMVC还提供了很多其他方式将数据带给页面。
一、传入Map,Model,ModelMap
Map,Model,ModelMap的作用域都是request。
1.handler中传入Map
@RequestMapping("handler01")
public String handler01(Map<String, Object> map) {
map.put("msg", "你好");
return "success";
}
2.handler中传入Model
@RequestMapping("handler02")
public String handler02(Model model) {
model.addAttribute("msg", "你好呀!");
return "success";
}
3.handler中传入ModelMap
@RequestMapping("handler03")
public String handler03(ModelMap modelmap) {
modelmap.addAttribute("msg", "你好啊!");
return "success";
}
4.Map,Model,ModelMap的关系
通过getclass,可以看到Map
,Model
,ModelMap
最终都是BindingAwareModelMap
在工作;相当于给BindingAwareModelMap
中保存的东西都会被放在请求域中。
- Map是一个jdk的接口(interface)。
- Model是一个spring的接口(interface)。
- ModelMap是一个类(class)。
二、处理模型数据
SpringMVC提供了以下几种途径输出模型数据(方法返回值类型)。
1.ModelAndView类型
ModelAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据。
- 数据放在请求域中。
- 返回值是ModelAndView可以为页面携带数据。
@RequestMapping("handler04")
public ModelAndView handler04(ModelMap modelmap) {
// 之前的返回值就是试图名
ModelAndView mv = new ModelAndView("success");
mv.addObject("msg", "你好哦");
return mv;
}
2.使用@SessionAttributes注解为session域中暂存数据
使用@SessionAttributes(value = "msg")
注解会在给BindingAwareModelMap
中保存数据的同时,为session中存放一份。value指定保存数据时要给session中存放的key。
value = {"msg"}
:只要保存的是这种key的数据,给session中存放一份。types={String.class}
:只要保存的是这种类型的数据,给session中存放一份。
@SessionAttributes(value = "msg")
@Controller
public class OutputController {
@RequestMapping("handler01")
public String handler01(Map<String, Object> map) {
map.put("msg", "你好");
System.out.println("map的类型是:" + map.getClass());
return "success";
}
}
SpringMVC虽然提供了为session存放数据的@SessionAttributes注解,不过还是推荐使用原始API,因为使用SpringMVC提供的注解可能会引发异常。
3.@ModelAttribute
在Hibernate的时代,@ModelAttribute注解用的很多,但自从有了Mybatis后@ModelAttribute就没有了应用场景。对于@ModelAttribute注解,了解即可。
3.1@ModelAttribute应用场景
有些时候,修改页面信息,并不是全字段修改,而是修改部分字段,以修改用户信息为例:
- 不修改的字段可以在页面展示,但是不要提供修改输入框。
- 为了简单,Controller直接在参数位置来写用户对象。
- SpringMVC可以为我们自动封装这个对象(没有带的值为null)。
- 如果调用一个全字段更新的操作,可能会将其他字段变null。
如何能保证全字段修改时,只更新了页面携带的数据呢?
方式1
:修改dao,但是代价太大。
方式2
:不使用SpringMVC创建的对象,而是从数据库中先取出一个对象。这样请求参数带了哪些值就覆盖之前的值,没带的字段就保持之前的值。
方式2的核心思想就是:Spring要封装的请求参数不是自己new出来的,而是从数据库中拿到的准备好的对象。下面演示@ModelAttribute。
3.2演示@ModelAttribute
当@ModelAttribute注解标注在方法位置,该方法会优先执行。当@ModelAttribute注解注解标注在参数位置,可以用来接收方法数据库中拿过来的对象。
@RequestMapping("updateBook")
public String updateBook(@ModelAttribute("book01") Book book) {
System.out.println("页面要提交过来的图书信息" + book);
return "success";
}
@ModelAttribute
public void haha(Map<String, Object> map) {
Book book = new Book(100, "红楼梦", "曹雪芹", 98, 10, 199.99);
map.put("book01", book);
System.out.println("数据库中查到的图书信息是:" + book);
}
33@ModelAttribute的原理
使用getClass可以查看到上面演示中使用的参数map实际上就是BindingAwareModelMap
,因此是可以跨方法取值的。
请求从头到尾都有一个map在跟随,可以从一开始用到页面。这个map被称为隐含模型。