【SpringMVC從入門到精通】03-域物件共享資料
目錄
域物件共享資料
1、三種域物件
-
Request
:一次請求 -
Session
:一次會話。從瀏覽器開啟到瀏覽器關閉(只跟瀏覽器是否關閉有關,與伺服器是否關閉無關)-
鈍化
Session
資料序列化到磁碟上 -
活化:瀏覽器仍然關閉而伺服器開啟,將鈍化內容讀取到
Session
中
-
鈍化
-
Application
/Servlet Context
:上下文物件,整個應用範圍。伺服器開啟時建立,伺服器關閉時銷燬,從頭到尾只建立一次(只跟伺服器是否關閉有關,與瀏覽器是否關閉無關)
選擇域物件時,應該選擇能實現功能、範圍最小的域物件
2、向 request 域物件共享資料
2.1、通過 Servlet API
後臺測試程式碼
@RequestMapping("/testRequestByServletAPI") public String testRequestByServletAPI(HttpServletRequest request) { request.setAttribute("testRequestScope", "hello, Servlet API!"); return "successrequest"; }
前臺測試程式碼
index.html
<a th:href="@{/scopeController/testRequestByServletAPI}">通過Servlet API</a>
successrequest.html
<p th:text="${testRequestScope}"></p>
測試結果
可以發現,轉發的頁面中成功獲取到了在後臺通過Request
物件向request
域中設定的屬性值並正確展示
2.2、通過 ModelAndView
食用方式:在 SpringMVC 中,不管用的何種方式,本質上最後都會封裝到
ModelAndView
。同時要注意使用ModelAndView
向 request 域物件共享資料時,需要返回ModelAndView
自身
後臺測試程式碼
@RequestMapping("/testRequestByModelAndView")
public ModelAndView testRequestByModelAndView() {
/**
* ModelAndView有Model和View兩個功能
* Model用於向請求域共享資料
* View用於設定檢視,實現頁面跳轉
*/
ModelAndView mv = new ModelAndView();
//向請求域共享資料
mv.addObject("testRequestScope", "hello, ModelAndView!");
//設定檢視,實現頁面跳轉
mv.setViewName("successrequest");
return mv;
}
前臺測試程式碼
<a th:href="@{/scopeController/testRequestByModelAndView}">通過 ModelAndView</a><br/>
測試結果
2.3、通過 Model
食用方式:形式與
HttpServletRequest
類似
後臺測試程式碼
@RequestMapping("/testRequestByModel")
public String testRequestByModel(Model model) {
//向請求域共享資料
model.addAttribute("testRequestScope", "hello, ModelAndView!");
return "successrequest";
}
前臺測試程式碼
<a th:href="@{/scopeController/testRequestByModel}">通過 Model</a><br/>
測試結果
2.4、通過 Map
食用方式:形式與
Model
方式類似
後臺測試程式碼
@RequestMapping("/testRequestByMap")
public String testRequestByMap(Map<String, Object> map) {
//向請求域共享資料
map.put("testRequestScope", "hello, Map!");
return "successrequest";
}
前臺測試程式碼
<a th:href="@{/scopeController/testRequestByMap}">通過 Map</a><br/>
測試結果
2.5、通過 ModelMap
食用方式:形式與
Model
方式類似
後臺測試程式碼
@RequestMapping("/testRequestByModelMap")
public String testRequestByModelMap(ModelMap modelMap) {
//向請求域共享資料
modelMap.addAttribute("testRequestScope", "hello, ModelMap!");
return "successrequest";
}
前臺測試程式碼
<a th:href="@{/scopeController/testRequestByModelMap}">通過 ModelMap</a><br/>
測試結果
2.6、Model、ModelMap 和 Map
分別在上述對應的控制器方法中,新增列印 Model、ModelMap 和 Map 三個物件及其對應類名的邏輯
System.out.println(model + "======" + model.getClass().getName());
System.out.println(map + "======" + map.getClass().getName());
System.out.println(modelMap + "======" + modelMap.getClass().getName());
通過分別點選前臺超連結,並檢視後臺日誌資訊
{testRequestScope=hello, Model!}======org.springframework.validation.support.BindingAwareModelMap
{testRequestScope=hello, Map!}======org.springframework.validation.support.BindingAwareModelMap
{testRequestScope=hello, ModelMap!}======org.springframework.validation.support.BindingAwareModelMap
可以發現
- Model、ModelMap 和 Map 三個物件輸入格式是一致的,都為鍵值對形式
- 通過反射方法獲取到的類都是同一個,即
BindingAwareModelMap
檢視BindingAwareModelMap
的繼承關係
閱讀原始碼,梳理出Model
、Map
、ModelMap
三者的核心繼承關係
public class BindingAwareModelMap extends ExtendedModelMap {}
public class ExtendedModelMap extends ModelMap implements Model {}
public class ModelMap extends LinkedHashMap<String, Object> {}
public interface Model {}
可以發現
-
BindingAwareModelMap
繼承ModelMap
並實現Model
介面 -
ModelMap
繼承LinkedHashMap
,而毫無疑問LinkedHashMap
實現了Map
介面
Model
、Map
和ModelMap
三者的關係到此就一目瞭然了,其 UML 類圖如下:
結論:
Model
、Map
、ModelMap
型別的形參本質上都是BindingAwareModelMap
3、向 session 域共享資料
食用方式:形式與
HttpServletRequest
方式類似,形參為HttpSession
。需要注意的是 SpringMVC 雖然提供了一個@SessionAttribute
註解,但並不好用,因此反而建議直接使用原生 Servlet 中的HttpSession
物件
後臺測試程式碼
@RequestMapping("/testSession")
public String testSession(HttpSession session) {
//向session域共享資料
session.setAttribute("testSessionScope", "hello, HttpSession!");
return "successsession";
}
前臺測試程式碼
index.html
<a th:href="@{/scopeController/testSession}">通過 Servlet API 向 Session 域物件共享資料</a><br/>
successsession.html
<p th:text="${session.testSessionScope}"></p>
測試結果
4、向 application 域共享資料
食用方式:形式與
HttpSession
方式類似,只不過需要先從session
物件中獲取ServletContext
上下文物件,即application
域物件,再做操作
後臺測試程式碼
@RequestMapping("/testApplication")
public String testApplication(HttpSession session) {
ServletContext application = session.getServletContext();
application.setAttribute("testApplicationScope", "hello, application!");
return "successapplication";
}
前臺測試程式碼
index.html
<a th:href="@{/scopeController/testApplication}">通過 Servlet API 向 Application 域物件共享資料</a><br/>
successapplication.html
<p th:text="${application.testApplicationScope}"></p>
測試結果
總結
域物件有三種:request
(請求域)、session
(會話域)和application
(上下文)
向request
域物件共享資料方式:本質都是ModelAndView
-
Servlet API
(不推薦):HttpServletRequest
-
ModelAndView
:需要返回自身 -
Model
、Map
、ModelMap
:本質都是BindingAwareModelMap
向session
域共享資料:HttpSession
向application
域共享資料:ServletContext
附上導圖,僅供參考