一、什么是域对象?
域对象主要用在web应用中,负责存储数据,通俗的讲就是这个对象本身可以存储一定范围内的所有数据,通过它就能获取和存储数据,可以理解为万能的一个属性,类似于静态变量,但有些差别。只要调用它就可以获得这个范围(域)内的想要的数据,也可以修改删除数据,当然也可以给这个域添加数据。
二、域对象分类
根据作用域,可分为:
-
PageContext域
作用范围:最小,一个jsp页面
-
HttpServletRequest域
作用范围:一次请求,请求开始到请求结束。
-
Session域
作用范围:一次会话,浏览器开启,到浏览器关闭。
-
ServletContext(Application)域
作用范围:整个应用的范围,也就整个web项目从服务器开启到服务器关闭的过程。
三、在SpringMVC中的域对象
在SpringMVC中一般不用.jsp页面,所以就不太需要PageContext域对象,故本文就只讲三种域对象。
四、域对象的选择
应选择一个能实现功能的范围最小的域对象
五、向HttpServletRequest域对象中共享数据
1、使用servletAPI
先在Controller中调用request.setAttribute()方法向静态页面中传一次参
//通过ServletAPI向Request域对象共享数据
@RequestMapping("/testRequestByServletAPI")
public String testRequestByServletAPI(HttpServletRequest request){
request.setAttribute("testRequestScope","hello,servletAPI");
return "success";
}
然后success中用thymeleaf语法获取
<p th:text="${testRequestScope}"></p>
注意,这样写之后thymeleaf会报错,但是不用管他,直接运行,它可以取到传过来的参。
2、使用ModelAndView(很重要)
无论用的是哪一种方法往request域对象中共享数据,最终Model和View的数据都会被封装到ModelAndView对象中
Model功能:指的是往域对象中共享数据的过程
View功能:指的是所设置的视图名称通过视图解析器解析跳转到指定页面的过程
下面是测试,先在控制器中创建一个一个方法
//通过ModelAndView向Request域对象共享数据
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
ModelAndView mav = new ModelAndView();
//处理模型数据,即向请求域request共享数据
mav.addObject("testRequestScope","hello,ModelAndView");
//设置视图名称
mav.setViewName("success");
return mav;
}
然后在主页加上超链接
<a th:href="@{/testModelAndView}">测试通过testModelAndView向Request域对象共享数据</a><br>
重新部署并点击刚才设置的超链接
可以看到效果与通过servletAPI实现的是一样的
注意:
- 该方法如果是使用ModelAndView对象向request域中共享对象,则返回值应是ModelAndView对象,
- mav.addObject()方法参数和功能与request.setAttribute()一致
- mav.setViewName()方法中的参数是视图的名称,也就是html页面名称。
3、使用Model
该方法最终是将对象封装成了ModelAndView对象。
//通过Model向Request域对象共享数据
@RequestMapping("/testModel")
public String testModel(Model model){
model.addAttribute("testRequestScope","hello,Model");
return "success";
}
该方法与使用servletAPI的方法类似,只不过,参数换成了Model
4、使用map
该方法与使用Model类似
//通过Model向Request域对象共享数据
@RequestMapping("/testMap")
public String testModel(Map<String,Object> map){
map.put("testRequestScope","hello,Map");
return "success";
}
运行后也是一样的效果。
5、使用ModelMap
该方法与前面两种方法都类似
//通过ModelMap向Request域对象共享数据
@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap){
// modelMap.put("testRequestScope","hello,ModelMap");
modelMap.addAttribute("testRequestScope","hello,ModelMap");
return "success";
}
不同的是设置传参的方法有两种,put和addAttribute,无论使用这两种方法中的哪种运行之后结果都是ok的。
从4、5、6三种方法的相似来看,这三种方法有什么联系呢,下面就探讨一下。
6、Model、ModelMap、Map的关系
首先我们先分别在三个方法中加上一个输出语句来输出一下Model、ModelMap、Map三个参数。
然后分别点一下这三个超链接,看看控制台会输出什么
可以很明显的看到。输出的格式都是一样的,也就是说,这三个类的toString方法是一样的,那么这三个类是不是同一个类呢?下面再将这三个类的类名输出。
可以看到,这三个类的参数其实本质上都是BindingAwareModelMap类型的,所以这三个类必定是有关系的。
那么通过观察源码就可以很清楚的看出他们的关系
public interface Model{}
public class ModelMap extends LinkedHashMap<String, Object>{}
public class ExtendedModelMap extends ModelMAp implements Model{}
public class BindingAwareModelMap extends ExtendedModelMap{}
**注意:**这么多方法可以选择,理论上是随便选,但SpringMVC建议我们使用ModelAndView,因为无论是哪一种方法向request域对象中共享数据,最终都会被封装成一个ModelAndView对象返回,所以不如直接使用该对象。
六、向Session域对象中共享数据
1、使用servletAPI
// 使用ServletAPI向session域对象中共享数据
@RequestMapping("/testSession")
public String testSession(HttpSession session){
session.setAttribute("testSessionScope","hello,Session");
return "success";
}
<p th:text="${session.testSessionScope}"></p><br>
那么除了使用servletAPI向Session域对象中共享数据SpringMVC还有什么其他的方法吗?答案是有的,但是对于向Session域对象中共享数据,SpringMVC推荐我们使用servletAPI。
**注意:**取session对象数据在thymeleaf中的语法是session.数据的键,与前面的用法不一样。
七、向ServletContext(application)域对象中共享数据
1、使用servletAPI
//使用ServletAPI向Application域对象中共享数据
@RequestMapping("/testApplication")
public String testServletContext(HttpSession session){
ServletContext context = session.getServletContext();
context.setAttribute("testApplicationScope","hello,Application");
return "success";
}
<p th:text="${application.testApplicationScope}"></p><br>
**注意:**取session对象数据在thymeleaf中的语法是application.数据的键,与session类似。