域对象共享数据
三种域对象
Request
:一次请求Session
:一次会话。从浏览器开启到浏览器关闭(只跟浏览器是否关闭有关,与服务器是否关闭无关)- 钝化:浏览器未关闭而服务器关闭,
Session
数据序列化到磁盘上 - 活化:浏览器仍然关闭而服务器开启,将钝化内容读取到
Session
中
- 钝化:浏览器未关闭而服务器关闭,
Application
/Servlet Context
:上下文对象,整个应用范围。服务器开启时创建,服务器关闭时销毁,从头到尾只创建一次(只跟服务器是否关闭有关,与浏览器是否关闭无关)
选择域对象时,应该选择能实现功能、范围最小的域对象
向 request 域对象共享数据
通过 Servlet API
后台测试代码
1 |
|
前台测试代码
index.html
1 | <a th:href="@{/scopeController/testRequestByServletAPI}">通过Servlet API</a> |
successrequest.html
1 | <p th:text="${testRequestScope}"></p> |
测试结果
可以发现,转发的页面中成功获取到了在后台通过Request
对象向request
域中设置的属性值并正确展示
通过 ModelAndView
食用方式:在 SpringMVC 中,不管用的何种方式,本质上最后都会封装到
ModelAndView
。同时要注意使用ModelAndView
向 request 域对象共享数据时,需要返回ModelAndView
自身
后台测试代码
1 |
|
前台测试代码
1 | <a th:href="@{/scopeController/testRequestByModelAndView}">通过 ModelAndView</a |
测试结果
通过 Model
食用方式:形式与
HttpServletRequest
类似
后台测试代码
1 |
|
前台测试代码
1 | <a th:href="@{/scopeController/testRequestByModel}">通过 Model</a><br /> |
测试结果
通过 Map
食用方式:形式与
Model
方式类似
后台测试代码
1 |
|
前台测试代码
1 | <a th:href="@{/scopeController/testRequestByMap}">通过 Map</a><br /> |
测试结果
通过 ModelMap
食用方式:形式与
Model
方式类似
后台测试代码
1 |
|
前台测试代码
1 | <a th:href="@{/scopeController/testRequestByModelMap}">通过 ModelMap</a><br /> |
测试结果
ModelMap 和 Map
分别在上述对应的控制器方法中,添加打印 Model、ModelMap 和 Map 三个对象及其对应类名的逻辑
1 | System.out.println(model + "======" + model.getClass().getName()); |
通过分别点击前台超链接,并查看后台日志信息
1 | {testRequestScope=hello, Model!}======org.springframework.validation.support.BindingAwareModelMap |
可以发现
- Model、ModelMap 和 Map 三个对象输入格式是一致的,都为键值对形式
- 通过反射方法获取到的类都是同一个,即
BindingAwareModelMap
查看BindingAwareModelMap
的继承关系
阅读源码,梳理出Model
、Map
、ModelMap
三者的核心继承关系
1 | public class BindingAwareModelMap extends ExtendedModelMap {} |
可以发现
BindingAwareModelMap
继承ModelMap
并实现Model
接口ModelMap
继承LinkedHashMap
,而毫无疑问LinkedHashMap
实现了Map
接口
Model
、Map
和ModelMap
三者的关系到此就一目了然了,其 UML 类图如下:
结论:
Model
、Map
、ModelMap
类型的形参本质上都是BindingAwareModelMap
向 session 域共享数据
食用方式:形式与
HttpServletRequest
方式类似,形参为HttpSession
。需要注意的是 SpringMVC 虽然提供了一个@SessionAttribute
注解,但并不好用,因此反而建议直接使用原生 Servlet 中的HttpSession
对象
后台测试代码
1 |
|
前台测试代码
index.html
1 | <a th:href="@{/scopeController/testSession}" |
successsession.html
1 | <p th:text="${session.testSessionScope}"></p> |
测试结果
向 application 域共享数据
食用方式:形式与
HttpSession
方式类似,只不过需要先从session
对象中获取ServletContext
上下文对象,即application
域对象,再做操作
后台测试代码
1 |
|
前台测试代码
index.html
1 | <a th:href="@{/scopeController/testApplication}" |
successapplication.html
1 | <p th:text="${application.testApplicationScope}"></p> |
测试结果
总结
域对象有三种:request
(请求域)、session
(会话域)和application
(上下文)
向request
域对象共享数据方式:本质都是ModelAndView
Servlet API
(不推荐):HttpServletRequest
ModelAndView
:需要返回自身Model
、Map
、ModelMap
:本质都是BindingAwareModelMap
向session
域共享数据:HttpSession
向application
域共享数据:ServletContext
附上导图,仅供参考