Spring MVC 獲取三個域(request請求域,session 會話域,application 應用域)物件的方式

Rainbow-Sea發表於2024-06-30

1. Spring MVC 獲取三個域(request請求域,session 會話域,application 應用域)物件的方式

@

目錄
  • 1. Spring MVC 獲取三個域(request請求域,session 會話域,application 應用域)物件的方式
  • 2. Servlet中的三個域物件
  • 3. 準備工作
    • 3.1 建立模組,新增依賴
    • 3.2 新增 web 支援
    • 3.3 編寫 web.xml 檔案
    • 3.4 建立 IndexController 類
    • 3.5 編寫 springmvc.xml
    • 3.6 編寫 index.html 檔案檢視
    • 3.7 部署測試
  • 4. Spring MVC 獲取 request 請求域物件的五種方式
    • 4.1 第一種方式:使用原生Servlet API方式 獲取到 request 請求域,同時獲取到請求域當中對應的內容
    • 4.2 第二種方式:使用 Model 介面 獲取到 request 請求域,同時獲取到請求域當中對應的內容
    • 4.3 第三種方式:使用Map介面 獲取到 request 請求域,同時獲取到請求域當中對應的內容
    • 4.4 第四種方式:使用 ModelMap 類 獲取到 request 請求域,同時獲取到請求域當中對應的內容
    • 4.5 補充:Model、Map、ModelMap的關係
    • 4.6 第五種方式:使用 ModelAndView 類獲取到 request 請求域,同時獲取到請求域當中對應的內容
    • 4.7 補充:ModelAndView 原始碼分析
  • 5. Spring MVC 獲取 session 會話域物件的二種方式
    • 5.1 第一種方式:使用原生Servlet API 獲取到 session 會話域,同時獲取到 session 會話域當中的資訊
    • 5.2 第二種方式:使用 @SessionAttributes 註解 獲取到 session 會話域,同時獲取到 session 會話域當中的資訊
  • 6. Spring MVC 獲取 application 應用域物件的方式
  • 7. 總結:
  • 8. 最後:


2. Servlet中的三個域物件

Servlet 中的三個域物件分別是:

請求域:request
會話域:session
應用域:application
三個域都有以下三個方法:

// 向域中儲存資料
void setAttribute(String name, Object obj);

// 從域中讀取資料
Object getAttribute(String name);

// 刪除域中的資料
void removeAttribute(String name);

主要是透過:setAttribute + getAttribute 方法來完成在域中資料的傳遞和共享。

request:

介面名:HttpServletRequest
簡稱:request
request物件代表了一次請求。一次請求一個request。

使用請求域的業務場景:

在A資源中透過轉發的方式跳轉到B資源,因為是轉發,因此從A到B是一次請求,如果想讓A資源和B資源共享同一個資料,可以將資料儲存到request域中。

session:

介面名:HttpSession
簡稱:session
session物件代表了一次會話。從開啟瀏覽器開始訪問,到最終瀏覽器關閉,這是一次完整的會話。每個會話session物件都對應一個JSESSIONID,而JSESSIONID生成後以cookie的方式儲存在瀏覽器客戶端。瀏覽器關閉,JSESSIONID失效,會話結束。

使用會話域的業務場景:

  1. 在 A 資源中透過重定向(重定向是一次新的請求)的方式轉到 B 資源,因為是重定向,因此從 A到 B 是兩次請求,如果想讓 A 資源和 B 資源共享同一個資料,可以將資料儲存到 session域中
  2. 登入成功後儲存使用者的登入狀態

application

介面名:ServletContext
簡稱:application
application物件代表了整個 web 應用,伺服器啟動的建立,伺服器關閉時銷燬,對於一個 web 應用來說,application 物件只有一個。

使用應用域的業務場景:記錄網站的線上人數。

3. 準備工作

3.1 建立模組,新增依賴

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>springmvc-004-blog</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <!--springmvc依賴-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>6.1.4</version>
        </dependency>
        <!--logback依賴-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.5.3</version>
        </dependency>
        <!--servlet依賴-->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
            <scope>provided</scope>
        </dependency>
        <!--thymeleaf和spring6整合的依賴-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring6</artifactId>
            <version>3.1.2.RELEASE</version>
        </dependency>
    </dependencies>


</project>

3.2 新增 web 支援

先在 main 目錄下,新增名為 webapp 的目錄(資料夾),只能是這個 webapp 目錄名,不可以是其他的。

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述


3.3 編寫 web.xml 檔案

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">

    <!--前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--透過初始化引數來指定springmvc配置檔案的路徑和名字。-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--在伺服器啟動的時候初始化DispatcherServlet,提高第一次訪問的效率-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
<!--        除了 jsp 其他的路徑都被獲取到-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

3.4 建立 IndexController 類

建立 IndexController 類作為 首頁來使用

在這裡插入圖片描述

package com.rainbowsea.springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller // 交給 Spring IOC 容器管理
public class IndexController {


    @RequestMapping("/")
    public String index() {
        return "index";
    }
}

3.5 編寫 springmvc.xml

在 springmvc.xml 當中配置兩個資訊:

  • 元件掃描
  • 檢視解析器

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--    元件掃描-->
    <context:component-scan base-package="com.rainbowsea.springmvc.controller"></context:component-scan>

    <!--    檢視解析器-->
    <bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
        <!--作用於檢視渲染的過程中,可以設定檢視渲染後輸出時採用的編碼字符集-->
        <property name="characterEncoding" value="UTF-8"/>
        <!--如果配置多個檢視解析器,它來決定優先使用哪個檢視解析器,它的值越小優先順序越高-->
        <property name="order" value="1"/>
        <!--當 ThymeleafViewResolver 渲染模板時,會使用該模板引擎來解析、編譯和渲染模板-->
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring6.SpringTemplateEngine">
                <!--用於指定 Thymeleaf 模板引擎使用的模板解析器。模板解析器負責根據模板位置、模板資源名稱、檔案編碼等資訊,載入模板並對其進行解析-->
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
                        <!--設定模板檔案的位置(字首)-->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!--設定模板檔案字尾(字尾),Thymeleaf副檔名不一定是html,也可以是其他,例如txt,大部分都是html-->
                        <property name="suffix" value=".html"/>
                        <!--設定模板型別,例如:HTML,TEXT,JAVASCRIPT,CSS等-->
                        <property name="templateMode" value="HTML"/>
                        <!--用於模板檔案在讀取和解析過程中採用的編碼字符集-->
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

</beans>

3.6 編寫 index.html 檔案檢視

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>
<h2>測試 request 域物件</h2>
</body>
</html>

3.7 部署測試

在這裡插入圖片描述


4. Spring MVC 獲取 request 請求域物件的五種方式

在SpringMVC中,在request域中共享資料有以下五種方式:

  1. 使用原生Servlet API方式。
  2. 使用Model介面。
  3. 使用Map介面。
  4. 使用ModelMap類。
  5. 使用ModelAndView類。

4.1 第一種方式:使用原生Servlet API方式 獲取到 request 請求域,同時獲取到請求域當中對應的內容

第一種方式: 在Spring MVC 中使用原生的 Servlet API 可以完成 request 域資料共享
,在處理器方法上新增 HttpServletRequest 引數即可。

將 HttpServletRequest 作為引數,定義到方法上,Spring MVC 框架會自動從 Tomcat 伺服器當中獲取到這個 HttpServletRequest 物件的值,然後,傳遞給這個方法的 HttpServletRequest 引數值上,完成賦值。

建立一個 RequestScopeTestController 類,注意要交給 Spring IOC 容器管理起來

在這裡插入圖片描述

package com.rainbowsea.springmvc.controller;


import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交給Spring IOC 容器管理
public class RequestScopeTestController {


    // request 請求域
    @RequestMapping("/testServletAPI")
    public String testServletAPI(HttpServletRequest request) {

        // 將共享的資料儲存到 request域當中
        // 跳轉檢視,在檢視頁面將request域中的資料取出,這樣就完成了,Controller和View在同一個請求當中兩個元件之間的資料共享

        // 將共享的資料儲存到request域當中
        request.setAttribute("testRequestScope", "在SpringMVC當中使用原生Servlet API 完成 request域的資料共享");
        System.out.println(request);
        System.out.println(request.getClass().getName());

        // 跳轉檢視,在檢視頁面將 request 域中的資料取出來,這樣就完成了,Controller 和 View 在同
        // 一個請求當中兩個元件之間資料的共享

        // 注意:這個是跳轉,預設情況下是,轉發的方式,(轉發 forward 是一次請求)
        // 這個返回的是一個邏輯檢視名稱,經過檢視解析器解析,變成物理檢視名稱,/WEB-INF/templates/ok.html
        return "ok";
    }

}

index頁面超連結的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>
<h2>測試 request 域物件</h2>


<a th:href="@{/testServletAPI}">測試在SpringMVC當中使用原生 Servlet API 完成 request 域的資料共享</a>
<br>

</body>
</html>

ok 頁面獲取 request 請求域的展示

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>
<h2>測試 request 域物件</h2>


<a th:href="@{/testServletAPI}">測試在SpringMVC當中使用原生 Servlet API 完成 request 域的資料共享</a>
<br>

</body>
</html>

測試結果:

在這裡插入圖片描述

這種方式當然可以,用 SpringMVC 框架,不建議使用原生 Servlet API

4.2 第二種方式:使用 Model 介面 獲取到 request 請求域,同時獲取到請求域當中對應的內容

在這裡插入圖片描述


import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交給Spring IOC 容器管理
public class RequestScopeTestController {

    @RequestMapping(value = "/testModel")
    public String testModel(Model model) {
        // 向 request 域當中繫結資料
        model.addAttribute("testRequestScope", "在SpringMVC 當中使用 Model 介面完成 request 域資料共享");
        System.out.println(model);
        System.out.println(model.getClass().getName());
        // 轉發
        return "ok";
    }
}

index 頁面超連結的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>
<h2>測試 request 域物件</h2>


<a th:href="@{/testServletAPI}">測試在SpringMVC當中使用原生 Servlet API 完成 request 域的資料共享</a>
<br>
<a th:href="@{/testModel}">測試在 Spring MVC 當中使用 Model 介面完成 request 域資料共享</a>
<br>
</body>
</html>

ok 頁面獲取 request 請求域的展示

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http//www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>OK</title>
</head>
<body>
<div th:text="${testRequestScope}"></div>
</body>
</html>

啟動 Tomcat 伺服器測試結果:

在這裡插入圖片描述

4.3 第三種方式:使用Map介面 獲取到 request 請求域,同時獲取到請求域當中對應的內容

在這裡插入圖片描述

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交給Spring IOC 容器管理
public class RequestScopeTestController {
    @RequestMapping(value = "/testMap")
    public String testMap(Map<String, Object> map) {

        // 向 request 域當中的儲存資料
        map.put("testRequestScope", "在Spring MVC 當中使用 Map介面完成 request 域資料共享");
        System.out.println(map);
        System.out.println(map.getClass().getName());
        // 轉發
        return "ok";
    }
}

index 頁面超連結的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>
<h2>測試 request 域物件</h2>


<a th:href="@{/testServletAPI}">測試在SpringMVC當中使用原生 Servlet API 完成 request 域的資料共享</a>
<br>
<a th:href="@{/testModel}">測試在 Spring MVC 當中使用 Model 介面完成 request 域資料共享</a>
<br>
<a th:href="@{/testMap}">測試在Spring MVC 當中使用 Map 介面完成 request 域資料共享</a>
<br>
</body>
</html>

ok 頁面獲取 request 請求域的展示 保持不變

啟動 Tomcat 伺服器測試結果:

在這裡插入圖片描述

4.4 第四種方式:使用 ModelMap 類 獲取到 request 請求域,同時獲取到請求域當中對應的內容

在這裡插入圖片描述



import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交給Spring IOC 容器管理
public class RequestScopeTestController {

    @RequestMapping(value = "/testModelMap")
    public String testModelMap(ModelMap modelMap) {
        // 向 request 域當中儲存資料
        modelMap.addAttribute("testRequestScope", "在Spring MVC 當中 ModelMap類完成request 域資料共享");
        System.out.println(modelMap);
        System.out.println(modelMap.getClass().getName());
        return "ok";
    }
}

index 頁面超連結的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>
<h2>測試 request 域物件</h2>


<a th:href="@{/testServletAPI}">測試在SpringMVC當中使用原生 Servlet API 完成 request 域的資料共享</a>
<br>
<a th:href="@{/testModel}">測試在 Spring MVC 當中使用 Model 介面完成 request 域資料共享</a>
<br>
<a th:href="@{/testMap}">測試在Spring MVC 當中使用 Map 介面完成 request 域資料共享</a>
<br>
<a th:href="@{/testModelMap}">測試在Spring MVC當中使用 ModelMap 類完成 request 域資料共享</a>
<br>
</body>
</html>

ok 頁面獲取 request 請求域的展示 保持不變

啟動 Tomcat 伺服器測試結果:

在這裡插入圖片描述

4.5 補充:Model、Map、ModelMap的關係

可以在以上Model、Map、ModelMap的測試程式中將其輸出,看看輸出什麼:

在這裡插入圖片描述

看不出來什麼區別,從輸出結果上可以看到都是一樣的。
可以將其執行時類名輸出:

在這裡插入圖片描述

在這裡插入圖片描述

透過輸出結果可以看出,無論是Model、Map還是ModelMap,底層例項化的物件都是:BindingAwareModelMap。

可以檢視 BindingAwareModelMap的繼承結構:

在這裡插入圖片描述

透過繼承結構可以看出:BindingAwareModelMap繼承了ModelMap,而ModelMap又實現了Map介面。
另外,請看以下原始碼:

在這裡插入圖片描述

可以看出ModelMap又實現了Model介面。因此表面上是採用了不同方式,底層本質上是相同的。
SpringMVC之所以提供了這些方式,目的就是方便程式設計師的使用,提供了多樣化的方式,可見它的重要性。

4.6 第五種方式:使用 ModelAndView 類獲取到 request 請求域,同時獲取到請求域當中對應的內容

在 Spring MVC 框架中為了更好的體現 MVC 架構模式,提供了一個類:ModelAndView。

這個類的例項封裝了 Model 和 View 。也就是說 這個類封裝業務處理之後的資料,也體現了跳轉到哪個檢視。使用它也可以完成 request 域資料共享。

使用這種方式的注意事項:

  1. 方法的返回值型別不是 String 了,而是 ModelAndView 物件
  2. ModelAndView 不是出現在方法的引數位置上了,而是在方法體中 new 出來的
  3. 需要呼叫 addObject() 向域中儲存資料
  4. 需要呼叫 setViewName() 設定檢視的名字
  5. 最後需要將 ModelAndView 作為引數,返回。

在這裡插入圖片描述


import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

@Controller // 交給Spring IOC 容器管理
public class RequestScopeTestController {



    @RequestMapping(value = "/testModelAndView")
    public ModelAndView testModelAndView() {
        // 建立模型檢視物件
        ModelAndView modelAndView = new ModelAndView();
        // 給模型檢視物件繫結資料
        modelAndView.addObject("testRequestScope", "在SpringMVC當中使用 ModelAndView 類完成 request 域資料共享");

        // 給模型檢視物件 繫結檢視(繫結邏輯檢視名稱)
        modelAndView.setViewName("ok");

        // 返回模型檢視物件
        return modelAndView;
    }
}

index頁面超連結的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>
<h2>測試 request 域物件</h2>


<a th:href="@{/testServletAPI}">測試在SpringMVC當中使用原生 Servlet API 完成 request 域的資料共享</a>
<br>
<a th:href="@{/testModel}">測試在 Spring MVC 當中使用 Model 介面完成 request 域資料共享</a>
<br>
<a th:href="@{/testMap}">測試在Spring MVC 當中使用 Map 介面完成 request 域資料共享</a>
<br>
<a th:href="@{/testModelMap}">測試在Spring MVC當中使用 ModelMap 類完成 request 域資料共享</a>
<br>
<a th:href="@{/testModelAndView}">測試在Spring MVC當中使用 ModelAndView 類完成 request 域資料共享</a>
<br>

</body>
</html>

ok 頁面獲取 request 請求域的展示的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http//www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>OK</title>
</head>
<body>
<div th:text="${testRequestScope}"></div>
</body>
</html>

啟動 Tomcat 伺服器測試結果:

在這裡插入圖片描述

4.7 補充:ModelAndView 原始碼分析

以上我們透過了五種方式完成了request域資料共享,包括:原生 Servlet API,Model、Map、ModelMap、ModelAndView
其中後四種:Model、Map、ModelMap、ModelAndView。

這四種方式在底層DispatcherServlet呼叫我們的Controller之後,返回的物件都是ModelAndView,

這個可以透過原始碼進行分析。

在以上四種方式中,拿Model舉例,新增斷點進行除錯:

在這裡插入圖片描述

啟動伺服器,傳送請求,走到斷點:

在這裡插入圖片描述

檢視VM Stack資訊:

在這裡插入圖片描述

檢視 DispatcherServlet 的1089行,原始碼如下:
在這裡插入圖片描述

可以看到這裡,無論你使用哪種方式,最終都要返回一個ModelAndView物件。

對於 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 處理器方法來說,不管你使用的引數是 Model介面,還是Map介面,還是ModelMap類,還是ModelAndView類,最終處理器方法執行結束之前
返回的都是 ModelAndView物件,這個返回的ModelAndView物件給DispatcherServlet類了
當請求路徑不是JSP的時候,都會走前端控制器 DispatcherServlet
DispatcherServlet 中有一個核心方法 doDispatch(),這個方法用來透過請求路徑找到對應的處理器方法
然後呼叫處理器方法,處理器方法返回一個邏輯檢視名稱(可能也會直接返回一個ModelAndView物件)
,返回給DispatcherServlet

提醒:大家可以透過以下斷點除錯方式,採用一級一級返回,最終可以看到都會返回ModelAndView物件。

在這裡插入圖片描述

5. Spring MVC 獲取 session 會話域物件的二種方式

在SpringMVC中使用session域共享資料,實現方式有多種,其中比較常見的兩種方式:

  1. 使用原生Servlet API
  2. 使用SessionAttributes註解

5.1 第一種方式:使用原生Servlet API 獲取到 session 會話域,同時獲取到 session 會話域當中的資訊

使用原生Servlet API ,就是將 HttpSession 作為方法的引數形式,Spring MVC 會自動獲取到 Tomcat 伺服器當中的 HttpSession 物件,賦值到這個方法的對應的 HttpSession 引數上。

建立:SessionScopeTestController 類

在這裡插入圖片描述


import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;



@Controller // 交給 Spring IOC 容器管理
public class SessionScopeTestController {


    @RequestMapping("/testSessionServletAPI")
    public String testServletAPI(HttpSession session) {
        // 處理核心業務...
        //將資料儲存到 Session中
        session.setAttribute("testSessionScope","在Spring MVC 當中使用原生 Servlet API 完成 session 域資料共享");
        // 返回邏輯檢視(這是一個轉發的行為)
        return "ok";
    }
}

index 頁面超連結的編寫:
在這裡插入圖片描述

ok 頁面獲取 request 請求域的展示的編寫

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http//www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>OK</title>
</head>
<body>
<div th:text="${session.testSessionScope}"></div>
</body>
</html>

啟動 Tomcat 伺服器測試結果:
在這裡插入圖片描述

5.2 第二種方式:使用 @SessionAttributes 註解 獲取到 session 會話域,同時獲取到 session 會話域當中的資訊

使用 @SessionAttributes 註解標註 Controller:

在這裡插入圖片描述

@SessionAttributes(value = {"x","y","testSessionScope"}) // 標註 x 和 y 都是存放到 session 域中,而不是 request域

**注意:@SessionAttributes 註解使用在Controller類上。標註了當 key是 x 或者 y 時,該(x 或 y)的資料將被儲存到會話 session域當中中。而如果沒有 SessionAttributes註解,預設儲存到 request域中。 **
在這裡插入圖片描述


import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;


@SessionAttributes(value = {"x","y","testSessionScope"}) // 標註 x 和 y 都是存放到 session 域中,而不是 request域
@Controller // 交給 Spring IOC 容器管理
public class SessionScopeTestController {



    @RequestMapping(value = "/testSessionAttributes")
    public String testSessionAttributes(ModelMap modelMap) {
        // 處理業務
        // 將資料儲存到 Session域當中
        modelMap.addAttribute("testSessionScope","在Spring MVC 當中使用@SessionAttributes 註解完成 session 域資料共享");
        modelMap.addAttribute("x","李華");
        modelMap.addAttribute("y","小紅");
        return "ok";
    }
}

index 頁面超連結的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>



<h2>測試Session域物件</h2>
<a th:href="@{/testSessionAttributes}">測試在Spring MVC 當中使用 @SessionAttributes 註解完成 session域資料共享</a>
<br>

</body>
</html>

ok 頁面獲取 request 請求域的展示的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http//www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>OK</title>
</head>
<body>
<div th:text="${session.testSessionScope}"></div>
<div th:text="${session.x}"></div>
<div th:text="${session.y}"></div>
</body>
</html>

啟動 Tomcat 伺服器測試結果:

在這裡插入圖片描述

6. Spring MVC 獲取 application 應用域物件的方式

在SpringMVC實現application域資料共享,最常見的方案就是直接使用Servlet API了:

這個 application 域使用較少,如果使用的話,一般是採用 ServletAPI的方式使用

建立:ApplicationScopeTestController 類

將 HttpServletRequest 作為引數,定義到方法上,Spring MVC 框架會自動從 Tomcat 伺服器當中獲取到這個 HttpServletRequest 物件的值,然後,傳遞給這個方法的 HttpServletRequest 引數值上,完成賦值。
在這裡插入圖片描述

package com.rainbowsea.springmvc.controller;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller // 交給 Spring IOC 容器管理
public class ApplicationScopeTestController {


    @RequestMapping("/testApplicationScope")
    public String testApplicationScope(HttpServletRequest request) {
        // 將資料儲存到application域當中
        // 獲取application物件,其實就是獲取 ServletContext物件
        // 怎麼獲取 ServletContext物件/透過 request,透過 session都可以用
        ServletContext application = request.getServletContext();
        application.setAttribute("testApplicationScope", "在Spring MVC 中使用 Servlet API中實現application域共享");
        return "ok";
    }
}

index 頁面超連結的編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試三個物件</title>
</head>
<body>
<h1>測試三個域物件</h1>
<hr>



<h2>測試Application應用域物件</h2>
<a th:href="@{/testApplicationScope}">測試在Spring MVC 當中使用 Servlet API 實現application域資料共享</a>
<br>

</body>
</html>

ok 頁面獲取 request 請求域的展示的編寫

在這裡插入圖片描述

啟動 Tomcat 伺服器測試結果:
在這裡插入圖片描述

7. 總結:

  1. 三個域:request 請求域,session 會話域,application 應用域

  2. 三者域的使用,從最小範圍的域,來判斷使用,可以用範圍更小的域,就用範圍更小的域來解決問題,傳資料資源。如果域的範圍不夠,就一點的擴大。

  3. 在SpringMVC中,在request域中共享資料有以下五種方式:

    1. 使用原生Servlet API方式。
    2. 使用Model介面。
    3. 使用Map介面。
    4. 使用ModelMap類。
    5. 使用ModelAndView類。
  4. 在SpringMVC中使用session域共享資料,實現方式有多種,其中比較常見的兩種方式:

    1. 使用原生Servlet API
    2. 使用SessionAttributes註解
  5. Spring MVC 獲取 application 應用域物件的方式

8. 最後:

“在這個最後的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回覆是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮鬥。感謝你們,我們總會在某個時刻再次相遇。”

在這裡插入圖片描述

相關文章