HttpSession 整合

Spring Session 提供了與 HttpSession 的透明整合。這意味著開發人員可以將 HttpSession 實現替換為由 Spring Session 支援的實現。

為什麼選擇 Spring Session 和 HttpSession

我們已經提到 Spring Session 提供了與 HttpSession 的透明整合,但這會帶來什麼好處呢?

  • 叢集會話:Spring Session 使支援叢集會話變得輕而易舉,而無需與應用程式容器特定的解決方案繫結。

  • RESTful API:Spring Session 允許在標頭中提供會話 ID,以便與RESTful API配合使用

使用 Redis 的 HttpSession

透過在任何使用 HttpSession 的元件之前新增一個 Servlet Filter,可以啟用 Spring Session 與 HttpSession 的結合使用。您可以透過以下兩種方式之一啟用此功能:

Redis 基於 Java 的配置

本節介紹如何使用基於 Java 的配置,透過 Redis 支援 HttpSession

HttpSession 示例 提供了一個工作示例,展示瞭如何使用 Java 配置整合 Spring Session 和 HttpSession。您可以在接下來的幾節中閱讀整合的基本步驟,但我們鼓勵您在整合自己的應用程式時,參考詳細的 HttpSession 指南。

Spring Java 配置

新增所需的依賴項後,我們可以建立 Spring 配置。Spring 配置負責建立一個 Servlet 過濾器,該過濾器用 Spring Session 支援的實現替換 HttpSession 實現。為此,請新增以下 Spring 配置

@Configuration(proxyBeanMethods = false)
@EnableRedisHttpSession (1)
public class Config {

	@Bean
	public LettuceConnectionFactory connectionFactory() {
		return new LettuceConnectionFactory(); (2)
	}

}
1 @EnableRedisHttpSession 註解會建立一個名為 springSessionRepositoryFilter 的 Spring Bean,它實現了 Filter 介面。該過濾器負責替換 HttpSession 的實現,使其由 Spring Session 提供支援。在此例項中,Spring Session 由 Redis 提供支援。
2 我們建立一個 RedisConnectionFactory,它將 Spring Session 連線到 Redis 伺服器。我們將連線配置為連線到預設埠 (6379) 上的 localhost。有關配置 Spring Data Redis 的更多資訊,請參閱 參考文件

Java Servlet 容器初始化

我們的Spring 配置建立了一個名為 springSessionRepositoryFilter 的 Spring Bean,它實現了 Filter 介面。springSessionRepositoryFilter bean 負責將 HttpSession 替換為由 Spring Session 支援的自定義實現。

為了讓我們的 Filter 發揮作用,Spring 需要載入我們的 Config 類。最後,我們需要確保我們的 Servlet 容器(即 Tomcat)為每個請求使用我們的 springSessionRepositoryFilter。幸運的是,Spring Session 提供了一個名為 AbstractHttpSessionApplicationInitializer 的實用類來簡化這兩個步驟。以下是一個示例:

src/main/java/sample/Initializer.java
public class Initializer extends AbstractHttpSessionApplicationInitializer { (1)

	public Initializer() {
		super(Config.class); (2)
	}

}
我們類的名稱 (Initializer) 無關緊要。重要的是我們擴充套件了 AbstractHttpSessionApplicationInitializer
1 第一步是擴充套件 AbstractHttpSessionApplicationInitializer。這樣做可以確保名為 springSessionRepositoryFilter 的 Spring Bean 被註冊到我們的 Servlet 容器中,以處理每個請求。
2 AbstractHttpSessionApplicationInitializer 還提供了一種機制來確保 Spring 載入我們的 Config

Redis 基於 XML 的配置

本節介紹如何使用基於 XML 的配置,透過 Redis 支援 HttpSession

HttpSession XML 示例 提供了一個工作示例,展示瞭如何使用 XML 配置整合 Spring Session 和 HttpSession。您可以在接下來的幾節中閱讀整合的基本步驟,但我們鼓勵您在整合自己的應用程式時,參考詳細的 HttpSession XML 指南。

Spring XML 配置

新增所需的依賴項後,我們可以建立 Spring 配置。Spring 配置負責建立一個 Servlet 過濾器,該過濾器用 Spring Session 支援的實現替換 HttpSession 實現。為此,請新增以下 Spring 配置

src/main/webapp/WEB-INF/spring/session.xml
(1)
<context:annotation-config/>
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>

(2)
<bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>
1 我們使用 <context:annotation-config/>RedisHttpSessionConfiguration 的組合,因為 Spring Session 尚不提供 XML 名稱空間支援(參見 gh-104)。這會建立一個名為 springSessionRepositoryFilter 的 Spring Bean,它實現了 Filter 介面。該過濾器負責替換 HttpSession 的實現,使其由 Spring Session 提供支援。在此例項中,Spring Session 由 Redis 提供支援。
2 我們建立了一個 RedisConnectionFactory,用於將 Spring Session 連線到 Redis 伺服器。我們將連線配置為連線到預設埠(6379)上的 localhost。有關配置 Spring Data Redis 的更多資訊,請參閱參考文件

XML Servlet 容器初始化

我們的Spring 配置建立了一個名為 springSessionRepositoryFilter 的 Spring Bean,它實現了 Filter 介面。springSessionRepositoryFilter bean 負責將 HttpSession 替換為由 Spring Session 支援的自定義實現。

為了讓我們的 Filter 發揮作用,我們需要指示 Spring 載入我們的 session.xml 配置。我們可以使用以下配置來完成:

src/main/webapp/WEB-INF/web.xml
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		/WEB-INF/spring/session.xml
	</param-value>
</context-param>
<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>
</listener>

ContextLoaderListener 讀取 contextConfigLocation 並載入我們的 session.xml 配置。

最後,我們需要確保我們的 Servlet 容器(即 Tomcat)為每個請求使用我們的 springSessionRepositoryFilter。以下程式碼片段為我們執行了最後一步:

src/main/webapp/WEB-INF/web.xml
<filter>
	<filter-name>springSessionRepositoryFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
	<filter-name>springSessionRepositoryFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>ERROR</dispatcher>
</filter-mapping>

DelegatingFilterProxy 透過名稱 springSessionRepositoryFilter 查詢一個 Bean 並將其轉換為 Filter。對於每個呼叫 DelegatingFilterProxy 的請求,都會呼叫 springSessionRepositoryFilter

使用 Mongo 的 HttpSession

使用 Spring Session 和 HttpSession 是透過在任何使用 HttpSession 的元件之前新增一個 Servlet Filter 來實現的。

本節介紹如何使用基於 Java 的配置,透過 Mongo 支援 HttpSession

HttpSession Mongo 示例 提供了一個工作示例,展示瞭如何使用 Java 配置整合 Spring Session 和 HttpSession。您可以在下方閱讀整合的基本步驟,但我們鼓勵您在整合自己的應用程式時,參考詳細的 HttpSession 指南。

您只需新增以下 Spring 配置:

@Configuration(proxyBeanMethods = false)
@EnableMongoHttpSession (1)
public class HttpSessionConfig {

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

}
1 @EnableMongoHttpSession 註解會建立一個名為 springSessionRepositoryFilter 的 Spring Bean,它實現了 Filter 介面。該過濾器負責將預設的 HttpSession 替換為由 MongoDB 支援的 Bean。
2 將會話超時配置為 30 分鐘。

會話序列化機制

為了能夠在 MongoDB 中持久化會話物件,我們需要提供序列化/反序列化機制。

預設情況下,Spring Session MongoDB 將使用 JdkMongoSessionConverter

但是,您只需向您的 Boot 應用程式新增以下程式碼即可切換到 JacksonMongoSessionConverter

@Bean
JacksonMongoSessionConverter mongoSessionConverter() {
    return new JacksonMongoSessionConverter();
}
JacksonMongoSessionConverter

此機制使用 Jackson 將會話物件序列化為 JSON 並從 JSON 反序列化。

透過建立以下 bean:

@Bean
JacksonMongoSessionConverter mongoSessionConverter() {
    return new JacksonMongoSessionConverter();
}

…​您可以從預設的(基於 JDK 的序列化)切換到使用 Jackson。

如果您要與 Spring Security 整合(透過將會話儲存在 MongoDB 中),此配置將註冊適當的白名單元件,以便 Spring Security 正常工作。

如果您希望提供自定義 Jackson 模組,可以透過顯式註冊模組來實現,如下所示:

Unresolved include directive in modules/ROOT/pages/http-session.adoc - include::example$spring-session-data-mongodb-dir/src/integration-test/java/org/springframework/session/data/mongo/integration/MongoRepositoryJacksonITest.java[]
JdkMongoSessionConverter

JdkMongoSessionConverter 使用標準 Java 序列化將會話屬性對映以二進位制形式持久化到 MongoDB。但是,標準會話元素(如 ID、訪問時間等)仍以普通 Mongo 物件形式寫入,無需額外工作即可讀取和查詢。如果未定義顯式 AbstractMongoSessionConverter Bean,則使用 JdkMongoSessionConverter

還有一個建構函式接受 SerializerDeserializer 物件,允許您傳遞自定義實現,這在使用非預設類載入器時尤為重要。

使用 JDBC 的 HttpSession

您可以透過在任何使用 HttpSession 的元件之前新增一個 servlet 過濾器來使用 Spring Session 和 HttpSession。您可以選擇以下任一方式:

JDBC 基於 Java 的配置

本節介紹如何在使用基於 Java 的配置時,使用關係資料庫來支援 HttpSession

HttpSession JDBC 示例 提供了一個工作示例,展示瞭如何使用 Java 配置整合 Spring Session 和 HttpSession。您可以在接下來的幾節中閱讀整合的基本步驟,但我們鼓勵您在整合自己的應用程式時,參考詳細的 HttpSession JDBC 指南。

Spring Java 配置

新增所需的依賴項後,我們可以建立 Spring 配置。Spring 配置負責建立一個 Servlet 過濾器,該過濾器將 HttpSession 實現替換為由 Spring Session 支援的實現。為此,請新增以下 Spring 配置:

@Configuration(proxyBeanMethods = false)
@EnableJdbcHttpSession (1)
public class Config {

	@Bean
	public EmbeddedDatabase dataSource() {
		return new EmbeddedDatabaseBuilder() (2)
			.setType(EmbeddedDatabaseType.H2)
			.addScript("org/springframework/session/jdbc/schema-h2.sql")
			.build();
	}

	@Bean
	public PlatformTransactionManager transactionManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource); (3)
	}

}
1 @EnableJdbcHttpSession 註解會建立一個名為 springSessionRepositoryFilter 的 Spring Bean。該 Bean 實現了 Filter 介面。該過濾器負責替換 HttpSession 的實現,使其由 Spring Session 提供支援。在此例項中,Spring Session 由關係資料庫提供支援。
2 我們建立了一個 dataSource,它將 Spring Session 連線到 H2 資料庫的嵌入式例項。我們配置 H2 資料庫,使其使用 Spring Session 中包含的 SQL 指令碼來建立資料庫表。
3 我們建立一個 transactionManager,它管理之前配置的 dataSource 的事務。

有關如何配置資料訪問相關問題的更多資訊,請參閱 Spring Framework 參考文件

Java Servlet 容器初始化

我們的Spring 配置建立了一個名為 springSessionRepositoryFilter 的 Spring Bean,它實現了 Filter 介面。springSessionRepositoryFilter bean 負責將 HttpSession 替換為由 Spring Session 支援的自定義實現。

為了讓我們的 Filter 發揮作用,Spring 需要載入我們的 Config 類。最後,我們需要確保我們的 Servlet 容器(即 Tomcat)為每個請求使用我們的 springSessionRepositoryFilter。幸運的是,Spring Session 提供了一個名為 AbstractHttpSessionApplicationInitializer 的實用類來簡化這兩個步驟。以下示例展示瞭如何實現:

src/main/java/sample/Initializer.java
public class Initializer extends AbstractHttpSessionApplicationInitializer { (1)

	public Initializer() {
		super(Config.class); (2)
	}

}
我們類的名稱(Initializer)無關緊要。重要的是我們擴充套件了 AbstractHttpSessionApplicationInitializer
1 第一步是擴充套件 AbstractHttpSessionApplicationInitializer。這樣做可以確保名為 springSessionRepositoryFilter 的 Spring bean 被註冊到我們的 Servlet 容器中,以處理每個請求。
2 AbstractHttpSessionApplicationInitializer 還提供了一種機制來確保 Spring 載入我們的 Config

多個數據源

Spring Session 提供了 @SpringSessionDataSource 限定符,允許您明確宣告應該將哪個 DataSource bean 注入到 JdbcIndexedSessionRepository 中。這在應用程式上下文中存在多個 DataSource bean 的場景中特別有用。

以下示例展示瞭如何實現:

Config.java
@EnableJdbcHttpSession
public class Config {

	@Bean
	@SpringSessionDataSource (1)
	public EmbeddedDatabase firstDataSource() {
		return new EmbeddedDatabaseBuilder()
				.setType(EmbeddedDatabaseType.H2).addScript("org/springframework/session/jdbc/schema-h2.sql").build();
	}

	@Bean
	public HikariDataSource secondDataSource() {
		// ...
	}
}
1 此限定符宣告 firstDataSource 將由 Spring Session 使用。

JDBC 基於 XML 的配置

本節介紹在使用基於 XML 的配置時,如何使用關係資料庫支援 HttpSession

HttpSession JDBC XML 示例 提供了一個工作示例,展示瞭如何使用 XML 配置整合 Spring Session 和 HttpSession。您可以在接下來的幾節中閱讀整合的基本步驟,但我們鼓勵您在整合自己的應用程式時,參考詳細的 HttpSession JDBC XML 指南。

Spring XML 配置

新增所需的依賴項後,我們可以建立 Spring 配置。Spring 配置負責建立一個 servlet 過濾器,該過濾器將 HttpSession 實現替換為由 Spring Session 支援的實現。以下清單展示瞭如何新增以下 Spring 配置:

src/main/webapp/WEB-INF/spring/session.xml
(1)
<context:annotation-config/>
<bean class="org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessionConfiguration"/>

(2)
<jdbc:embedded-database id="dataSource" database-name="testdb" type="H2">
	<jdbc:script location="classpath:org/springframework/session/jdbc/schema-h2.sql"/>
</jdbc:embedded-database>

(3)
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<constructor-arg ref="dataSource"/>
</bean>
1 我們使用 <context:annotation-config/>JdbcHttpSessionConfiguration 的組合,因為 Spring Session 尚不提供 XML 名稱空間支援(參見 gh-104)。這會建立一個名為 springSessionRepositoryFilter 的 Spring bean。該 bean 實現了 Filter 介面。該過濾器負責替換 HttpSession 的實現,使其由 Spring Session 提供支援。在此例項中,Spring Session 由關係資料庫提供支援。
2 我們建立了一個 dataSource,它將 Spring Session 連線到 H2 資料庫的嵌入式例項。我們配置 H2 資料庫,使其使用 Spring Session 中包含的 SQL 指令碼來建立資料庫表。
3 我們建立一個 transactionManager,它管理之前配置的 dataSource 的事務。

有關如何配置資料訪問相關問題的更多資訊,請參閱 Spring Framework 參考文件

XML Servlet 容器初始化

我們的Spring 配置建立了一個名為 springSessionRepositoryFilter 的 Spring bean,它實現了 Filter 介面。springSessionRepositoryFilter bean 負責將 HttpSession 替換為由 Spring Session 支援的自定義實現。

為了讓我們的 Filter 發揮作用,我們需要指示 Spring 載入我們的 session.xml 配置。我們使用以下配置來完成:

src/main/webapp/WEB-INF/web.xml
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>
		/WEB-INF/spring/session.xml
	</param-value>
</context-param>
<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>
</listener>

ContextLoaderListener 讀取 contextConfigLocation 並載入我們的 session.xml 配置。

最後,我們需要確保我們的 Servlet 容器(即 Tomcat)為每個請求使用我們的 springSessionRepositoryFilter。以下程式碼片段為我們執行了最後一步:

src/main/webapp/WEB-INF/web.xml
<filter>
	<filter-name>springSessionRepositoryFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
	<filter-name>springSessionRepositoryFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>ERROR</dispatcher>
</filter-mapping>

DelegatingFilterProxy 查詢名為 springSessionRepositoryFilter 的 bean 並將其轉換為 Filter。對於每個呼叫 DelegatingFilterProxy 的請求,都會呼叫 springSessionRepositoryFilter

JDBC Spring Boot-based Configuration

本節介紹如何在使用 Spring Boot 時,使用關係資料庫來支援 HttpSession

HttpSession JDBC Spring Boot 示例 提供了一個工作示例,展示瞭如何使用 Spring Boot 整合 Spring Session 和 HttpSession。您可以在接下來的幾節中閱讀整合的基本步驟,但我們鼓勵您在整合自己的應用程式時,參考詳細的 HttpSession JDBC Spring Boot 指南。

Spring Boot 配置

新增所需的依賴項後,我們可以建立 Spring Boot 配置。得益於一流的自動配置支援,只需新增依賴項,Spring Boot 就會為我們設定由關係資料庫支援的 Spring Session。

如果類路徑中只有一個 Spring Session 模組,Spring Boot 會自動使用該儲存實現。如果您有多個實現,則必須選擇您希望用於儲存會話的 StoreType,如上所示。

在底層,Spring Boot 應用的配置等同於手動新增 @EnableJdbcHttpSession 註解。這會建立一個名為 springSessionRepositoryFilter 的 Spring bean。該 bean 實現了 Filter 介面。該過濾器負責替換 HttpSession 的實現,使其由 Spring Session 提供支援。

您可以使用 application.properties 進行進一步自定義。以下列表展示瞭如何實現:

src/main/resources/application.properties
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds are used.
spring.session.jdbc.initialize-schema=embedded # Database schema initialization mode.
spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema.
spring.session.jdbc.table-name=SPRING_SESSION # Name of the database table used to store sessions.

有關更多資訊,請參閱 Spring Boot 文件的 Spring Session 部分。

配置 DataSource

Spring Boot 會自動建立一個 DataSource,將 Spring Session 連線到 H2 資料庫的嵌入式例項。在生產環境中,您需要更新配置以指向您的關係資料庫。例如,您可以在 application.properties 中包含以下內容:

src/main/resources/application.properties
spring.datasource.url= # JDBC URL of the database.
spring.datasource.username= # Login username of the database.
spring.datasource.password= # Login password of the database.

有關更多資訊,請參閱 Spring Boot 文件的 配置 DataSource 部分。

Servlet 容器初始化

我們的Spring Boot 配置建立了一個名為 springSessionRepositoryFilter 的 Spring bean,它實現了 Filter 介面。springSessionRepositoryFilter bean 負責將 HttpSession 替換為由 Spring Session 支援的自定義實現。

為了讓我們的 Filter 發揮作用,Spring 需要載入我們的 Config 類。最後,我們需要確保我們的 Servlet 容器(即 Tomcat)為每個請求使用我們的 springSessionRepositoryFilter。幸運的是,Spring Boot 為我們處理了這兩個步驟。

使用 Hazelcast 的 HttpSession

使用 Spring Session 和 HttpSession 是透過在任何使用 HttpSession 的元件之前新增一個 Servlet Filter 來實現的。

本節介紹如何使用基於 Java 的配置,透過 Hazelcast 支援 HttpSession

Hazelcast Spring 示例 提供了一個工作示例,展示瞭如何使用 Java 配置整合 Spring Session 和 HttpSession。您可以在接下來的幾節中閱讀整合的基本步驟,但我們鼓勵您在整合自己的應用程式時,參考詳細的 Hazelcast Spring 指南。

Spring 配置

新增所需的依賴項後,我們可以建立 Spring 配置。Spring 配置負責建立一個 Servlet 過濾器,該過濾器用 Spring Session 支援的實現替換 HttpSession 實現。為此,請新增以下 Spring 配置

@EnableHazelcastHttpSession (1)
@Configuration
public class HazelcastHttpSessionConfig {

	@Bean
	public HazelcastInstance hazelcastInstance() {
		Config config = new Config();
		AttributeConfig attributeConfig = new AttributeConfig()
			.setName(HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
			.setExtractorClassName(PrincipalNameExtractor.class.getName());
		config.getMapConfig(HazelcastIndexedSessionRepository.DEFAULT_SESSION_MAP_NAME) (2)
			.addAttributeConfig(attributeConfig)
			.addIndexConfig(
					new IndexConfig(IndexType.HASH, HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE));
		SerializerConfig serializerConfig = new SerializerConfig();
		serializerConfig.setImplementation(new HazelcastSessionSerializer()).setTypeClass(MapSession.class);
		config.getSerializationConfig().addSerializerConfig(serializerConfig); (3)
		return Hazelcast.newHazelcastInstance(config); (4)
	}

}
1 @EnableHazelcastHttpSession 註解會建立一個名為 springSessionRepositoryFilter 的 Spring bean,它實現了 Filter 介面。該過濾器負責替換 HttpSession 的實現,使其由 Spring Session 提供支援。在此例項中,Spring Session 由 Hazelcast 提供支援。
2 為了支援按主體名稱索引檢索會話,需要註冊一個適當的 ValueExtractor。Spring Session 為此目的提供了 PrincipalNameExtractor
3 為了高效地序列化 MapSession 物件,需要註冊 HazelcastSessionSerializer。如果未設定此項,Hazelcast 將使用原生 Java 序列化將會話序列化。
4 我們建立了一個 HazelcastInstance,它將 Spring Session 連線到 Hazelcast。預設情況下,應用程式啟動並連線到 Hazelcast 的嵌入式例項。有關配置 Hazelcast 的更多資訊,請參閱參考文件
如果首選 HazelcastSessionSerializer,則需要在所有 Hazelcast 叢集成員啟動之前對其進行配置。在 Hazelcast 叢集中,所有成員應為會話使用相同的序列化方法。此外,如果使用 Hazelcast 客戶端/伺服器拓撲,則成員和客戶端都必須使用相同的序列化方法。序列化器可以透過 ClientConfig 與成員的相同 SerializerConfiguration 一起註冊。

Servlet 容器初始化

我們的Spring 配置建立了一個名為 springSessionRepositoryFilter 的 Spring bean,它實現了 Filter 介面。springSessionRepositoryFilter bean 負責將 HttpSession 替換為由 Spring Session 支援的自定義實現。

為了讓我們的 Filter 發揮作用,Spring 需要載入我們的 SessionConfig 類。由於我們的應用程式已經使用 SecurityInitializer 類載入 Spring 配置,我們可以將 SessionConfig 類新增到其中。以下列表展示瞭如何實現:

src/main/java/sample/SecurityInitializer.java
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {

	public SecurityInitializer() {
		super(SecurityConfig.class, SessionConfig.class);
	}

}

最後,我們需要確保我們的 Servlet 容器(即 Tomcat)為每個請求使用我們的 springSessionRepositoryFilter。Spring Session 的 springSessionRepositoryFilter 在 Spring Security 的 springSecurityFilterChain 之前被呼叫是極其重要的。這樣做可以確保 Spring Security 使用的 HttpSession 由 Spring Session 提供支援。幸運的是,Spring Session 提供了一個名為 AbstractHttpSessionApplicationInitializer 的實用類,使這變得容易。以下示例展示瞭如何實現:

src/main/java/sample/Initializer.java
public class Initializer extends AbstractHttpSessionApplicationInitializer {

}
我們類的名稱 (Initializer) 無關緊要。重要的是我們擴充套件了 AbstractHttpSessionApplicationInitializer

透過擴充套件 AbstractHttpSessionApplicationInitializer,我們確保名為 springSessionRepositoryFilter 的 Spring Bean 在 Spring Security 的 springSecurityFilterChain 之前註冊到我們的 servlet 容器中,以處理每個請求。

HttpSession 整合的工作原理

幸運的是,HttpSessionHttpServletRequest(用於獲取 HttpSession 的 API)都是介面。這意味著我們可以為這些 API 提供自己的實現。

本節描述了 Spring Session 如何提供與 HttpSession 的透明整合。我們提供此內容是為了讓您瞭解底層發生的事情。此功能已經整合,您無需自行實現此邏輯。

首先,我們建立一個自定義的 HttpServletRequest,它返回 HttpSession 的自定義實現。它看起來像以下內容:

public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {

	public SessionRepositoryRequestWrapper(HttpServletRequest original) {
		super(original);
	}

	public HttpSession getSession() {
		return getSession(true);
	}

	public HttpSession getSession(boolean createNew) {
		// create an HttpSession implementation from Spring Session
	}

	// ... other methods delegate to the original HttpServletRequest ...
}

任何返回 HttpSession 的方法都會被覆蓋。所有其他方法都由 HttpServletRequestWrapper 實現,並委託給原始的 HttpServletRequest 實現。

我們使用一個名為 SessionRepositoryFilter 的 servlet Filter 來替換 HttpServletRequest 的實現。以下虛擬碼展示了它的工作原理:

public class SessionRepositoryFilter implements Filter {

	public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		SessionRepositoryRequestWrapper customRequest =
			new SessionRepositoryRequestWrapper(httpRequest);

		chain.doFilter(customRequest, response, chain);
	}

	// ...
}

透過將自定義的 HttpServletRequest 實現傳遞到 FilterChain 中,我們確保在我們的 Filter 之後呼叫的任何內容都使用自定義的 HttpSession 實現。這突出了為什麼 Spring Session 的 SessionRepositoryFilter 必須放置在任何與 HttpSession 互動的元件之前。

HttpSession 與 RESTful API

Spring Session 可以透過允許在請求頭中提供會話來與 RESTful API 協同工作。

REST 示例 提供了一個工作示例,展示瞭如何在 REST 應用程式中使用 Spring Session 來支援透過請求頭進行身份驗證。您可以按照接下來的幾節中描述的整合基本步驟進行操作,但我們鼓勵您在整合自己的應用程式時,參考詳細的 REST 指南。

Spring 配置

新增所需的依賴項後,我們可以建立 Spring 配置。Spring 配置負責建立一個 Servlet 過濾器,該過濾器用 Spring Session 支援的實現替換 HttpSession 實現。為此,請新增以下 Spring 配置

@Configuration
@EnableRedisHttpSession (1)
public class HttpSessionConfig {

	@Bean
	public LettuceConnectionFactory connectionFactory() {
		return new LettuceConnectionFactory(); (2)
	}

	@Bean
	public HttpSessionIdResolver httpSessionIdResolver() {
		return HeaderHttpSessionIdResolver.xAuthToken(); (3)
	}

}
1 @EnableRedisHttpSession 註解會建立一個名為 springSessionRepositoryFilter 的 Spring bean,它實現了 Filter 介面。該過濾器負責替換 HttpSession 的實現,使其由 Spring Session 提供支援。在此例項中,Spring Session 由 Redis 提供支援。
2 我們建立一個 RedisConnectionFactory,它將 Spring Session 連線到 Redis 伺服器。我們將連線配置為連線到預設埠 (6379) 上的 localhost。有關配置 Spring Data Redis 的更多資訊,請參閱 參考文件
3 我們定製 Spring Session 的 HttpSession 整合,以使用 HTTP 頭來傳遞當前會話資訊,而不是使用 cookie。

Servlet 容器初始化

我們的Spring 配置建立了一個名為 springSessionRepositoryFilter 的 Spring Bean,它實現了 Filter 介面。springSessionRepositoryFilter bean 負責將 HttpSession 替換為由 Spring Session 支援的自定義實現。

為了讓我們的 Filter 發揮作用,Spring 需要載入我們的 Config 類。我們在 Spring MvcInitializer 中提供了配置,如下例所示:

src/main/java/sample/mvc/MvcInitializer.java
@Override
protected Class<?>[] getRootConfigClasses() {
	return new Class[] { SecurityConfig.class, HttpSessionConfig.class };
}

最後,我們需要確保我們的 Servlet 容器(即 Tomcat)為每個請求使用我們的 springSessionRepositoryFilter。幸運的是,Spring Session 提供了一個名為 AbstractHttpSessionApplicationInitializer 的實用類,使這變得容易。為此,請使用預設建構函式擴充套件該類,如下例所示:

src/main/java/sample/Initializer.java
public class Initializer extends AbstractHttpSessionApplicationInitializer {

}
我們類的名稱 (Initializer) 無關緊要。重要的是我們擴充套件了 AbstractHttpSessionApplicationInitializer

使用 HttpSessionListener

Spring Session 透過將 SessionDestroyedEventSessionCreatedEvent 轉換為 HttpSessionEvent,並宣告 SessionEventHttpSessionListenerAdapter 來支援 HttpSessionListener。要使用此支援,您需要:

  • 確保您的 SessionRepository 實現支援並配置為觸發 SessionDestroyedEventSessionCreatedEvent

  • SessionEventHttpSessionListenerAdapter 配置為 Spring bean。

  • 將每個 HttpSessionListener 注入到 SessionEventHttpSessionListenerAdapter 中。

如果您使用 Redis 支援,並且 enableIndexingAndEvents 設定為 true,即 @EnableRedisHttpSession(enableIndexingAndEvents = true),您只需將每個 HttpSessionListener 註冊為 bean 即可。例如,假設您希望支援 Spring Security 的併發控制並需要使用 HttpSessionEventPublisher。在這種情況下,您可以將 HttpSessionEventPublisher 新增為 bean。在 Java 配置中,這可能如下所示:

@Configuration
@EnableRedisHttpSession
public class RedisHttpSessionConfig {

	@Bean
	public HttpSessionEventPublisher httpSessionEventPublisher() {
		return new HttpSessionEventPublisher();
	}

	// ...

}

在 XML 配置中,這可能如下所示:

<bean class="org.springframework.security.web.session.HttpSessionEventPublisher"/>
© . This site is unofficial and not affiliated with VMware.