1. 程式人生 > 其它 >【SpringMVC從入門到精通】03-域物件共享資料

【SpringMVC從入門到精通】03-域物件共享資料

筆記來源:【尚矽谷】SpringMVC教程丨一套快速上手spring mvc

目錄

域物件共享資料

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的繼承關係

閱讀原始碼,梳理出ModelMapModelMap三者的核心繼承關係

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介面

ModelMapModelMap三者的關係到此就一目瞭然了,其 UML 類圖如下:

結論ModelMapModelMap型別的形參本質上都是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:需要返回自身
  • ModelMapModelMap:本質都是BindingAwareModelMap

session域共享資料:HttpSession

application域共享資料:ServletContext

附上導圖,僅供參考