1、SpringMVC中的域对象
此处只有request、session、servletContext被使用,而page是jsp页面的域,不使用jsp。
- request:一次请求的范围内
- session:一次会话的范围内
- servletContext:整个web的应用范围内
2、向request域对象共享数据的几种方式
(1)使用ServletAPI
控制器方法存入数据
@RequestMapping("/testRequestByServletAPI")
public String testRequestByServletAPI(HttpServletRequest request){
request.setAttribute("username", "zhangsan");
request.setAttribute("password", "123456");
return "success";
}
前端页面读取数据
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Success</title>
</head>
<body>
<h3>success</h3><br>
<p th:text="${username}"></p>
<p th:text="${password}"></p>
</body>
</html>
(2)使用ModelAndView
什么是ModelAndView
ModelAndView是一个类,可以利用它的对象设置当前请求的
视图跳转
与数据共享
。不管使用什么方式,Spring最终都会将模型数据和视图封装到ModelAndView中。
ModelAndView对象的作用
有两个功能。
Model:向request域中共享数据
View:设置视图跳转。可以设置视图名称(setViewName),也可以设置视图(setView)
示例
通过ModelAndView,向request域中存放数据
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
ModelAndView mav = new ModelAndView();
//处理模型数据,即向request域共享数据
mav.addObject("username", "lisi");
mav.addObject("password", "456789");
//处理视图数据,即设置视图名称
mav.setViewName("success");
return mav;
}
读取数据和之前的前端页面一致
<p th:text="${username}"></p>
<p th:text="${password}"></p>
注意
如果在控制器方法中使用了ModelAndView对象,那么
该mav对象必须作为方法的返回值返回
。否则SpringMVC无法知晓你使用了ModelAndView
(3)使用Model
什么是Model
指的是ModelAndView中的Model
Model的作用
共享数据
示例
@RequestMapping("/testModel")
public String testModel(Model model){
model.addAttribute("username", "wangwu");
model.addAttribute("password", "555555");
return "success";
}
注意
单独使用Model
- 形参是Model类型
- 返回值是String类型,返回视图名称
(4)使用Map集合
什么叫使用map向request域共享数据
之前将Model类型作为控制器方法的形参,通过设置model的参数,就达到了共享数据的效果。
如果使用Map集合,也是一样的效果。
将Map类型作为形参,方法体中给map添加键值对,也可以直接将键值对保存到域对象。
示例
@RequestMapping("/testMap")
public String testMap(Map<String, Object> map){
map.put("username", "gaoliu");
map.put("password", "666666");
return "success";
}
(6)原理分析及总结
a. 为什么Model、ModelMap、Map,都能以同样的方式共享数据?
Model、ModelMap、Map类型的参数,其实本质上都是 BindingAwareModelMap 类型。这是Spring做的,并不是原生类型。
具体来说,它们实例化时,都用的是 BindingAwareModelMap 这个类。
那么Model、ModelMap、Map一定存在着联系。
先看Model的源码
public interface Model {...}说明它是Spring中,模型部分的顶层接口。
ModelMap的源码
public class ModelMap extends LinkedHashMap<String, Object> {...}它继承了LinkedHashMap,而LinkedHashMap实现了Map接口。所以
ModelMap也属于一个Map接口的实现类
。ModelMap的继承结构
BindAwareModelMap是ModelMap的子类,所以BindAwareModelMap可以实例化ModelMap。既然ModelMap实现了Map,那么BindAwareModelMap也可以实例化Map
。
BindAwareModelMap的继承结构
BindAwareModelMap的父类是ExtendedModelMap
public class ExtendedModelMap extends ModelMap implements Model {...}
而ExtendedModelMap继承了ModelMap类,并且实现了Model接口,所以BindAwareModelMap可以实例化Model类型
。
总结
Model、ModelMap、Map的关系:
public interface Model{}
public class ModelMap extends LinkedHashMap<String, Object> {}
public class ExtendedModelMap extends ModelMap implements Model {}
public class BindingAwareModelMap extends ExtendedModelMap {}
b.为什么这几种方式都没有指定request域,却都被称作向request域对象中共享数据?
首先,Model、ModelMap或是Map的方式,最终都会由SpringMVC封装成ModelAndView对象。
而使用ModelAndView的方式,是我们自己组装了ModelAndView对象并返回给了SpringMVC。
所以,这个问题的本质是,ModelAndView对象如何向request域对象中存放数据?
ModelandView是将 视图信息和数据封装到一起的,spring来解析ModelandView中的信息,包括视图和数据 ,然后将数据set到request里面,并且根据model里面的视图信息以及spring mvc的配置让request进行跳转。
3、向session域对象共享数据
使用ServletAPI比较简单
@RequestMapping("/testSession")
public String testSession(HttpSession session){
session.setAttribute("username", "xiaowb");
session.setAttribute("password", "000000");
return "success";
}
前端获取session域对象中的值
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Success</title>
</head>
<body>
<h3>success</h3><br>
<p th:text="${session.username}"></p>
<p th:text="${session.password}"></p>
</body>
</html>
thymeleaf获取session域对象中的数据时,需要加
session.键名
4、向servletContext域对象共享数据
注意
在jsp、Thymeleaf等
模板引擎中,servletContext通常被叫做application
,本质是一样的。所以在获取servletContext对象时,最好也叫做application。
使用ServletAPI比较简单
@RequestMapping("/testSessionContext")
public String testServletContext(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("username", "xiaocs");
application.setAttribute("password", "999999");
return "success";
}
前端获取application域对象中的值
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Success</title>
</head>
<body>
<h3>success</h3><br>
<p th:text="${application.username}"></p>
<p th:text="${application.password}"></p>
</body>
</html>
thymeleaf获取application域对象中的数据时,需要加application.键名