1.简介

Spring Session

Spring Session 提供了一个管理用户session信息的接口和实现

1.介绍

Spring Session 提供了一个管理用户session信息的接口和实现,同时也使得支持集群会话变得微不足道,而不依赖于特定于应用程序容器的解决方案。 它还提供透明集成:

HttpSession - 允许以应用程序容器(即Tomcat)中立的方式替换HttpSession,支持在头文件中提供会话ID以使用RESTful API。

WebSocket - 提供在接收WebSocket消息时保持HttpSession存活的能力

WebSession - 允许以应用程序容器中立方式替换Spring WebFlux的WebSession。


2.新特性

以下是Spring Session 2.0新增内容的重点。 您可以通过参考2.0.0.M1,2.0.0.M2,2.0.0.M3,2.0.0.M4,2.0.0.M5,2.0.0.RC1的更改日志找到新的完整列表。 ,2.0.0.RC2和2.0.0.RELEASE。

升级到Java 8和Spring Framework 5作为基线

添加了使用Redis ReactiveSessionRepository管理Spring WebFlux的WebSession的支持

提取SessionRepository实现以分离模块

改进了Session和SessionRepository API

为所有支持的会话存储提供改进和协调的配置支持

添加了使用SessionCookieConfig配置默认CookieSerializer的支持

大量的性能改进和错误修复

3.样例和指南

如果您希望开始使用Spring Session,最好的起点是我们的示例应用程序。

表1.使用Spring Boot的示例应用程序

代码 | 描述 | 手册

---------|--------|-------

[HttpSession 使用 Redis](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/boot/redis) |  演示如何将HttpSession替换为Spring Session使用Redis 。 |  [HttpSession 使用 Redis 手册](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/boot-redis.html)

[HttpSession with JDBC](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/boot/jdbc) | 演示如何使用关系数据库存储session替代httpsession. |  [HttpSession with JDBC Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/boot-jdbc.html)

[Find by Username](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/boot/findbyusername) | 演示如何使用spring session 根据用户名查找session. | [Find by Username Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/boot-findbyusername.html)

[WebSockets](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/boot/websocket) | 演示如何与Websockets一起使用Spring Session. | [WebSockets Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/boot-websocket.html)

[WebFlux](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/boot/webflux) | 演示如何使用redis 让Spring Session替换 Spring WebFlux’s `WebSession`. | TBD

[HttpSession with Redis JSON serialization](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/boot/redis-json) | 演示如何使用Spring Session替换 HttpSession 使用redis 的JSON序列化. | TBD

表 2. 基于java配置的样例程序

| 代码 | 描述 | 手册 |

| --- | --- | --- |

| [HttpSession with Redis](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/javaconfig/redis) |  演示如何将HttpSession替换为Spring Session使用Redis 。 |  [HttpSession with Redis Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/java-redis.html) |

| [HttpSession with JDBC](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/javaconfig/jdbc) | 演示如何使用关系数据库存储session替代httpsession. | [HttpSession with JDBC Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/java-jdbc.html) |

| [HttpSession with Hazelcast](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/javaconfig/hazelcast) | 演示使用Spring Session和Hazelcast 替换 HttpSession . | [HttpSession with Hazelcast Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/java-hazelcast.html) |

| [Custom Cookie](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/javaconfig/custom-cookie) | 演示如何使用Spring Session自定义cookie. | [Custom Cookie Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/java-custom-cookie.html) |

| [Spring Security](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/javaconfig/security) | 演示如何在一个已经存在的spring security应用中使用Spring Session. | [Spring Security Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/java-security.html) |

|  [REST](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/javaconfig/rest) | 演示如何使用Spring Session 在一个REST应用中支持头信息认证. |  [REST Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/java-rest.html) |

表 3.使用基于Spring XML配置的样例程序

| 代码 | 描述 | 手册 |

| --- | --- | --- |

| [HttpSession with Redis](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/xml/redis) | 演示如何将HttpSession替换为Spring Session使用Redis存储. | [HttpSession with Redis Guide](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/xml-redis.html) |

| [HttpSession with JDBC](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/xml/jdbc) | 演示如何使用Spring Session和关系数据库存储替代httpsession. . | [HttpSession 和 JDBC 手册](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/xml-jdbc.html) |

表 4. 小例子

| Source | Description | Guide |

| --- | --- | --- |

| [Grails 3](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/misc/grails3)| 演示 Spring Session 和 Grails 3一起使用.| [Grails 3 手册](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/guides/grails3.html) |

| [Hazelcast](https://github.com/spring-projects/spring-session/tree/2.1.0.RELEASE/samples/misc/hazelcast) |演示在javaEE应用中使用Spring Session和Hazelcast.| TBD |


4.Spring Session模块

在Spring Session 1.x中,所有Spring Session的SessionRepository实现都在spring-session组件中可用。 虽然方便,但随着更多功能和SessionRepository实现添加到项目中,这种方法不可能长期持续。

从Spring Session 2.0开始,该项目已经拆分为Spring Session Core模块,以及其他几个带有SessionRepository实现和与特定数据存储相关的功能的模块。Spring Data的用户会发现这种安排很熟悉,Spring Session Core模块扮演的角色相当于Spring Data Commons,并提供核心功能和API以及其他包含数据存储特定实现的模块。作为此拆分的一部分,Spring Session Data MongoDB和Spring Session Data GemFire模块被移动到单独的存储库,因此项目的存储库/模块的情况如下:

[`spring-session` repository](https://github.com/spring-projects/spring-session)

Spring Session Core,Spring Session Data Redis,Spring Session JDBC和Spring Session Hazelcast模块

[`spring-session-data-mongodb` repository](https://github.com/spring-projects/spring-session-data-mongodb)

Spring会话数据MongoDB模块

[`spring-session-data-geode` repository](https://github.com/spring-projects/spring-session-data-geode)

Spring Session Data Geode和Spring Session Data Geode模块

最后,Spring Session现在还提供了Maven BOM(如“物料清单”)模块,以帮助用户解决版本管理问题:

[`spring-session-bom` repository](https://github.com/spring-projects/spring-session-bom)

Spring Session BOM 模块

5.HttpSession整合

Spring Session提供与HttpSession的透明集成。 这意味着开发人员可以使用Spring Session支持的实现来切换HttpSession实现。

5.1. 为什么需要 Spring Session 整合 HttpSession?

我们已经提到Spring Session提供了与HttpSession的透明集成,但是我们从中获得了什么好处呢?

集群会话 - Spring会话使得支持集群会话变得微不足道,而不依赖于特定于应用程序容器的解决方案。

RESTful API - Spring Session允许在标头中提供会话ID以使用RESTful API

5.2. HttpSession 和 Redis

通过在使用HttpSession的任何东西之前添加Servlet过滤器来启用使用Spring Session和HttpSession。 您可以选择启用此功能:

*  [基于java config](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#httpsession-redis-jc)

*  [基于XML配置](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#httpsession-redis-xml)

5.2.1. 基于Java的redis配置

本节介绍如何基于Java的配置使用Redis来支持HttpSession。

[HttpSession示例](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#samples)提供了有关如何使用Java配置集成Spring Session和HttpSession的工作示例。 您可以在下面阅读集成的基本步骤,但建议您在与自己的应用程序集成时遵循详细的HttpSession指南。

Spring Java 配置

添加所需的依赖项后,我们可以创建Spring配置。 Spring配置负责创建一个Servlet过滤器,该过滤器用Spring Session支持的实现替换HttpSession实现。 添加以下Spring配置:

@EnableRedisHttpSession

public class Config {

@Bean

public LettuceConnectionFactory connectionFactory() {

return new LettuceConnectionFactory();

}

}

@EnableRedisHttpSession注释创建一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 过滤器负责替换由Spring Session支持的HttpSession实现。 在这种情况下,Spring Session由Redis提供支持。

我们创建了一个RedseConnectionFactory,它将Spring Session连接到Redis Server。 我们将连接配置为在默认端口上连接到localhost(6379)有关配置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 {

public Initializer() {

super(Config.class);

}

}

我们类的名字(初始化程序)并不重要。 重要的是我们扩展了AbstractHttpSessionApplicationInitializer。

第一步是扩展AbstractHttpSessionApplicationInitializer。 这确保了名为springSessionRepositoryFilter的Spring Bean为每个请求注册了我们的Servlet容器。

AbstractHttpSessionApplicationInitializer还提供了一种机制,可以轻松确保Spring加载我们的Config。

5.2.2. Redis 基于XML 配置

本节介绍如何使用Redis使用基于XML的配置来支持HttpSession。

[HttpSession XML示例](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#samples)提供了有关如何使用XML配置集成Spring Session和HttpSession的工作示例。 您可以在下面阅读集成的基本步骤,但建议您在与自己的应用程序集成时遵循详细的HttpSession XML指南。

Spring XML 配置

添加所需的依赖项后,我们可以创建Spring配置。 Spring配置负责创建一个Servlet过滤器,该过滤器用Spring Session支持的实现替换HttpSession实现。 添加以下Spring配置:

src/main/webapp/WEB-INF/spring/session.xml

<context:annotation-config/>

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>

<bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>

我们使用<context:annotation-config />和RedisHttpSessionConfiguration的组合,因为Spring Session尚未提供XML Namespace支持(请参阅gh-104)。 这将创建一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 过滤器负责替换由Spring Session支持的HttpSession实现。 在这种情况下,Spring Session由Redis提供支持。

我们创建了一个RedseConnectionFactory,它将Spring Session连接到Redis Server。 我们将连接配置为在默认端口上连接到localhost(6379)有关配置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/*.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。

5.3. HttpSession 和 JDBC

通过在使用HttpSession的任何东西之前添加Servlet过滤器来启用使用Spring Session和HttpSession。 您可以选择启用此功能:

*  [Java  配置](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#httpsession-jdbc-jc)

*  [XML 配置](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#httpsession-jdbc-xml)

*  [基于Spring Boot配置](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#httpsession-jdbc-boot)

#### [](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#httpsession-jdbc-jc)

5.3.1. 基于java的JDBC配置

本节介绍如何使用关系数据库来使用基于Java的配置来支持HttpSession。

[HttpSession JDBC示例](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#samples)提供了有关如何使用Java配置集成Spring Session和HttpSession的工作示例。 您可以在下面阅读集成的基本步骤,但是在与您自己的应用程序集成时,建议您遵循详细的HttpSession JDBC指南。

Spring Java 配置

添加所需的依赖项后,我们可以创建Spring配置。 Spring配置负责创建一个Servlet过滤器,该过滤器用Spring Session支持的实现替换HttpSession实现。 添加以下Spring配置:

@EnableJdbcHttpSession

public class Config {

@Bean

public EmbeddedDatabase dataSource() {

return new EmbeddedDatabaseBuilder()

.setType(EmbeddedDatabaseType.H2)

.addScript("org/springframework/session/jdbc/schema-h2.sql").build();

}

@Bean

public PlatformTransactionManager transactionManager(DataSource dataSource) {

return new DataSourceTransactionManager(dataSource);

}

}

@EnableJdbcHttpSession注释创建一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 过滤器负责替换由Spring Session支持的HttpSession实现。 在这种情况下,Spring Session由关系数据库支持。

我们创建了一个dataSource,它将Spring Session连接到H2数据库的嵌入式实例。 我们将H2数据库配置为使用Spring Session中包含的SQL脚本创建数据库表。

我们创建一个transactionManager来管理先前配置的dataSource的事务。

有关如何配置与数据访问相关的问题的其他信息,请参阅[Spring 框架参考手册](https://docs.spring.io/spring/docs/5.1.1.RELEASE/spring-framework-reference/data-access.html)。

Java Servlet 容器初始化

我们的[Spring配置](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#httpsession-spring-configuration)创建了一个名为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 {

public Initializer() {

super(Config.class);

}

}

我们类的名字(Initializer)并不重要。 重要的是我们扩展了AbstractHttpSessionApplicationInitializer。

第一步是扩展AbstractHttpSessionApplicationInitializer。 这确保了名为springSessionRepositoryFilter的Spring Bean为每个我们的Servlet容器请求注册。

AbstractHttpSessionApplicationInitializer还提供了一种机制,可以轻松确保Spring加载我们的Config。

5.3.2. JDBC 基于 XML 配置

本节介绍如何使用关系数据库使用基于XML的配置来支持HttpSession。

[HttpSession JDBC XML示例](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#samples)提供了有关如何使用XML配置集成Spring Session和HttpSession的工作示例。 您可以在下面阅读集成的基本步骤,但是在与您自己的应用程序集成时,建议您遵循详细的HttpSession JDBC XML指南。

Spring XML 配置

添加所需的依赖项后,我们可以创建Spring配置。 Spring配置负责创建一个Servlet过滤器,该过滤器用Spring Session支持的实现替换HttpSession实现。 添加以下Spring配置:

src/main/webapp/WEB-INF/spring/session.xml

<context:annotation-config/>

<bean class="org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessionConfiguration"/>

<jdbc:embedded-database id="dataSource" database-name="testdb" type="H2">

<jdbc:script location="classpath:org/springframework/session/jdbc/schema-h2.sql"/>

</jdbc:embedded-database>

<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<constructor-arg ref="dataSource"/>

</bean>

我们使用<context:annotation-config />和JdbcHttpSessionConfiguration的组合,因为Spring Session尚未提供XML Namespace支持(请参阅gh-104)。 这将创建一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 过滤器负责替换由Spring Session支持的HttpSession实现。 在这种情况下,Spring Session由关系数据库支持。

我们创建了一个dataSource,它将Spring Session连接到H2数据库的嵌入式实例。 我们将H2数据库配置为使用Spring Session中包含的SQL脚本创建数据库表。

我们创建一个transactionManager来管理先前配置的dataSource的事务。

有关如何配置与数据访问相关的问题的其他信息,请参阅[Spring 框架参考手册](https://docs.spring.io/spring/docs/5.1.1.RELEASE/spring-framework-reference/data-access.html)。

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/*.xml

</param-value>

</context-param>

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

[ContextLoaderListener](https://docs.spring.io/spring/docs/5.1.1.RELEASE/spring-framework-reference/core.html#context-create)读取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。

5.3.3. JDBC 基于Spring Boot配置

本节介绍在使用Spring Boot时如何使用关系数据库来支持HttpSession。

[HttpSession JDBC Spring Boot 示例](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#samples)提供了一个关于如何使用Spring Boot集成Spring Session和HttpSession的工作示例。 您可以在下面阅读集成的基本步骤,但是在与您自己的应用程序集成时,建议您遵循详细的HttpSession JDBC Spring Boot 手册。

Spring Boot 配置

添加所需的依赖项后,我们可以创建Spring Boot配置。 由于支持一流的自动配置,设置由关系数据库支持的Spring Session就像向application.properties添加单个配置属性一样简单:

src/main/resources/application.properties

spring.session.store-type=jdbc # Session store type.

在引擎盖下,Spring Boot将应用相当于手动添加@EnableJdbcHttpSession注释的配置。 这将创建一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 过滤器负责替换由Spring Session支持的HttpSession实现。

使用application.properties可以进一步自定义:

src/main/resources/application.properties

server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds will be 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](https://docs.spring.io/spring-boot/docs/2.1.0.M3/reference/htmlsingle/#boot-features-session)部分。

配置数据库

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文档的[配置数据源](https://docs.spring.io/spring-boot/docs/2.1.0.M3/reference/htmlsingle/#boot-features-configure-datasource)部分。

Servlet 容器初始化

我们的[Spring Boot配置](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#httpsession-jdbc-boot-spring-configuration)创建了一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 springSessionRepositoryFilter bean负责将HttpSession替换为Spring Session支持的自定义实现。

为了使我们的Filter能够发挥其魔力,Spring需要加载我们的Config类。 最后,我们需要确保我们的Servlet容器(即Tomcat)对每个请求都使用springSessionRepositoryFilter。 幸运的是,Spring Boot为我们处理了这两个步骤。

5.4. HttpSession 的 Hazelcast

通过在使用HttpSession的任何东西之前添加Servlet过滤器来启用使用Spring Session和HttpSession。

本节介绍如何使用Hazelcast使用基于Java的配置来支持HttpSession。

[Hazelcast Spring示例](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#samples)提供了有关如何使用Java配置集成Spring Session和HttpSession的工作示例。 您可以在下面阅读集成的基本步骤,但我们鼓励您在与自己的应用程序集成时遵循详细的Hazelcast Spring Guide。

5.4.1. Spring 配置

添加所需的依赖项后,我们可以创建Spring配置。 Spring配置负责创建一个Servlet过滤器,该过滤器用Spring Session支持的实现替换HttpSession实现。 添加以下Spring配置:

@EnableHazelcastHttpSession

@Configuration

public class HazelcastHttpSessionConfig {

@Bean

public HazelcastInstance hazelcastInstance() {

MapAttributeConfig attributeConfig = new MapAttributeConfig()

.setName(HazelcastSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)

.setExtractor(PrincipalNameExtractor.class.getName());

Config config = new Config();

config.getMapConfig(HazelcastSessionRepository.DEFAULT_SESSION_MAP_NAME)

.addMapAttributeConfig(attributeConfig)

.addMapIndexConfig(new MapIndexConfig(

HazelcastSessionRepository.PRINCIPAL_NAME_ATTRIBUTE, false));

return Hazelcast.newHazelcastInstance(config);

}

}

@EnableHazelcastHttpSession注释创建一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 过滤器负责替换由Spring Session支持的HttpSession实现。 在这种情况下,Spring Session由Hazelcast支持。

为了支持按主体名称索引检索会话,需要注册适当的ValueExtractor。 Spring Session为此提供了PrincipalNameExtractor。

我们创建了一个将Spring Session连接到Hazelcast的HazelcastInstance。 默认情况下,Hazelcast的嵌入式实例已启动并由应用程序连接。 有关配置Hazelcast的更多信息,请参阅[参考文档](http://docs.hazelcast.org/docs/3.10.6/manual/html-single/index.html#hazelcast-configuration)。

5.4.2. Servlet 容器初始化

我们的[Spring配置](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#security-spring-configuration)创建了一个名为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 Security的springSecurityFilterChain之前调用Spring Session的springSessionRepositoryFilter是非常重要的。 这可确保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容器。

5.5。 HttpSession集成如何工作

幸运的是,HttpSession和HttpServletRequest(用于获取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交互的任何内容之前。

5.6。 HttpSession和RESTful API

Spring Session可以通过允许在标头中提供会话来使用RESTful API。

[REST示例](https://docs.spring.io/spring-session/docs/2.1.0.RELEASE/reference/html5/#samples)提供了有关如何在REST应用程序中使用Spring Session以支持使用标头进行身份验证的工作示例。 您可以按照以下集成的基本步骤进行操作,但建议您在与自己的应用程序集成时遵循详细的REST指南。

5.6.1. Spring 配置

添加所需的依赖项后,我们可以创建Spring配置。 Spring配置负责创建一个Servlet过滤器,该过滤器用Spring Session支持的实现替换HttpSession实现。 添加以下Spring配置:

@Configuration

@EnableRedisHttpSession

public class HttpSessionConfig {

@Bean

public LettuceConnectionFactory connectionFactory() {

return new LettuceConnectionFactory();

}

@Bean

public HttpSessionIdResolver httpSessionIdResolver() {

return HeaderHttpSessionIdResolver.xAuthToken();

}

}

@EnableRedisHttpSession注释创建一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 过滤器负责替换由Spring Session支持的HttpSession实现。 在这种情况下,Spring Session由Redis提供支持。

我们创建了一个RedseConnectionFactory,它将Spring Session连接到Redis Server。 我们将连接配置为在默认端口上连接到localhost(6379)有关配置Spring Data Redis的更多信息,请参阅参考文档。

我们定制Spring Session的HttpSession集成以使用HTTP头来传达当前会话信息而不是cookie。

5.6.2. Servlet 容器初始化

我们的Spring配置创建了一个名为springSessionRepositoryFilter的Spring Bean,它实现了Filter。 springSessionRepositoryFilter bean负责将HttpSession替换为Spring Session支持的自定义实现。

为了使我们的Filter能够发挥其魔力,Spring需要加载我们的Config类。 我们在Spring Mvc Initializer中提供配置,如下所示:

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。

5.7. HttpSessionListener

Spring Session通过声明SessionEventHttpSessionListenerAdapter将SessionDestroyedEvent和SessionCreatedEvent转换为HttpSessionEvent来支持HttpSessionListener。 要使用此支持,您需要:

确保您的SessionRepository实现支持并配置为触发SessionDestroyedEvent和SessionCreatedEvent。

将SessionEventHttpSessionListenerAdapter配置为Spring bean。

将每个HttpSessionListener注入SessionEventHttpSessionListenerAdapter

如果您正在使用HttpSession中使用Redis记录的配置支持,那么您需要做的就是将每个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"/>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352

推荐阅读更多精彩内容