知識庫 / Spring RSS 訂閱

Spring Session 與 MongoDB

NoSQL,Spring
HongKong
8
01:22 PM · Dec 06 ,2025

1. 概述

在本快速教程中,我們將探討如何使用 Spring Session 與 MongoDB 集成,無論使用 Spring Boot 還是不使用。

Spring Session 也可以與 Redis 和 JDBC 等其他存儲後端集成。

2. Spring Boot 配置

首先,讓我們看一下 Spring Boot 所需的依賴項和配置。首先,讓我們將最新版本的 spring-session-data-mongodbspring-boot-starter-data-mongodb 添加到我們的項目中:

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-mongodb</artifactId>
    <version>3.1.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <version>3.1.5</version>
</dependency>

如果使用了多個 Spring Session 模塊,則需要通過設置 Spring Session 的 store-type 屬性來定義我們想要使用的模塊。例如,在這種情況下,我們會在 application.properties 中將 store-type 設置為 mongodb

spring.session.store-type=mongodb

從 Spring Boot 3.0.0 開始,不再支持存儲類型的屬性,而是通過註解配置來管理會話。

3. 在 Spring Boot 環境之外的 Spring 配置

現在,讓我們來查看在 MongoDB 中存儲 Spring 會話所需的依賴項和配置,而無需使用 Spring Boot。

類似於 Spring Boot 配置,我們需要 spring-session-data-mongodb 依賴項。但是,在這裏,我們將使用 spring-data-mongodb 依賴項來訪問我們的 MongoDB 數據庫:

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-mongodb</artifactId>
    <version>3.1.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>3.1.5</version>
</dependency>

最後,讓我們看看如何配置應用程序:

@EnableMongoHttpSession
public class HttpSessionConfig {

    @Bean
    public JdkMongoSessionConverter jdkMongoSessionConverter() {
        return new JdkMongoSessionConverter(Duration.ofMinutes(30));
    }
}

使用 @EnableMongoHttpSession 註解可以配置將會話數據存儲在 MongoDB 中

此外,請注意,JdkMongoSessionConverter 負責序列化和反序列化會話數據。

4. 示例應用程序

讓我們創建一個應用程序來測試配置。我們將使用 Spring Boot,因為它速度更快,並且需要更少的配置。

我們將首先創建一個控制器來處理請求:

@RestController
public class SpringSessionMongoDBController {

    @GetMapping("/")
    public ResponseEntity<Integer> count(HttpSession session) {

        Integer counter = (Integer) session.getAttribute("count");

        if (counter == null) {
            counter = 1;
        } else {
            counter++;
        }

        session.setAttribute("count", counter);

        return ResponseEntity.ok(counter);
    }
}

如本示例所示,我們每次對端點進行調用時都會遞增 counter,並將其值存儲在名為 count 的會話屬性中。

5. 測試應用程序

讓我們測試應用程序,以確認我們是否能夠將會話數據存儲在 MongoDB 中。

為此,我們將訪問端點並檢查我們收到的 cookie。該 cookie 將包含會話 ID。

之後,我們將查詢 MongoDB 集合,使用會話 ID 檢索會話數據:

@Test
public void 
  givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() {
    
    HttpEntity<String> response = restTemplate
      .exchange("http://localhost:" + 8080, HttpMethod.GET, null, String.class);
    HttpHeaders headers = response.getHeaders();
    String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE);

    Assert.assertEquals(response.getBody(),
      repository.findById(getSessionId(set_cookie)).getAttribute("count").toString());
}

private String getSessionId(String cookie) {
    return new String(Base64.getDecoder().decode(cookie.split(";")[0].split("=")[1]));
}

6. 工作原理

讓我們來了解一下 Spring 會話背後的運作機制。

SessionRepositoryFilter 負責大部分工作:

  • HttpSession 轉換為MongoSession
  • 檢查是否存在Cookie,如果存在,則從存儲中加載會話數據
  • 保存更新後的會話數據到存儲
  • 檢查會話的有效性

此外,SessionRepositoryFilter 會創建一個名為 SESSION 的 Cookie,該 Cookie 是 HttpOnly 和 secure 屬性。此 Cookie 包含會話 ID,該 ID 是 Base64 編碼的值。

要自定義 Cookie 的名稱或屬性,則必須創建一個類型為 DefaultCookieSerializer 的 Spring Bean。

例如,我們在這裏禁用了 Cookie 的 httponly 屬性:

@Bean
public DefaultCookieSerializer customCookieSerializer(){
    DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        
    cookieSerializer.setUseHttpOnlyCookie(false);
        
    return cookieSerializer;
}

7. 會話詳情存儲在 MongoDB 中

以下我們使用以下命令在 MongoDB 控制枱中查詢我們的會話集合:

db.sessions.findOne()

因此,我們會得到一個類似於以下的 BSON 文檔:

{
    "_id" : "5d985be4-217c-472c-ae02-d6fca454662b",
    "created" : ISODate("2019-05-14T16:45:41.021Z"),
    "accessed" : ISODate("2019-05-14T17:18:59.118Z"),
    "interval" : "PT30M",
    "principal" : null,
    "expireAt" : ISODate("2019-05-14T17:48:59.118Z"),
    "attr" : BinData(0,"rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAFY291bnRzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAC3g=")
}

id 是一個 UUID,將由 DefaultCookieSerializer 進行 Base64 編碼,並作為 SESSION 餅乾的值設置。 此外,請注意,attr 屬性包含我們計數器的實際值。

8. 結論

在本教程中,我們探討了使用 MongoDB 作為後端的 Spring Session——這是一種在分佈式系統中管理 HTTP 會話的強大工具。 考慮到這一點,它對於解決應用程序中多個實例之間會話複製的問題非常有幫助。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.