Spring Session 2.1.2.RELEASE 官方文档翻译

Spring Session提供了用于管理用户会话信息的API和实现。

Spring Session由以下模块组成:

  • Spring Session Core - 提供核心Spring会话功能和api
  • Spring Session Data Redis -  提供由Redis和配置支持支持的SessionRepository和ReactiveSessionRepository实现
  • Spring Session JDBC - 提供由关系数据库和配置支持支持的SessionRepository实现
  • Spring Session Hazelcast - 提供由Hazelcast和配置支持支持的SessionRepository实现

1. Introduction

Spring Session使得支持集群会话而不需要绑定到特定于应用程序容器的解决方案变得非常简单。它还提供透明的集成与:

  • HttpSession   - 允许在应用程序容器(即Tomcat)中以中立的方式替换HttpSession,支持在header中提供会话id来使用RESTful api
  • WebSocket    -   提供在接收WebSocket消息时保持HttpSession活动的能力
  • WebSession    -   允许以应用程序容器中立的方式替换Spring WebFlux的web会话

2. What’s New in 2.0

  • 升级到Java 8和Spring Framework 5作为基线
  • 增加了对使用Redis ReactiveSessionRepository管理Spring WebFlux的web会话的支持
  • 提取SessionRepository实现以分离模块
  • 改进的会话和SessionRepository api
  • 改进和协调了对所有受支持会话存储的配置支持
  • 增加了使用SessionCookieConfig配置默认CookieSerializer的支持
  • 大量的性能改进和bug修复

3. Samples and Guides (Start Here) 示例和指南(从这里开始)

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

Table 1. Sample Applications using Spring Boot 

Source Description Guide

HttpSession with Redis

演示如何使用Spring会话将HttpSession替换为Redis。

HttpSession with Redis Guide

HttpSession with JDBC

演示如何使用Spring会话将HttpSession替换为关系数据库存储。

HttpSession with JDBC Guide

Find by Username

演示如何使用Spring Session按用户名查找会话。

Find by Username Guide

WebSockets

演示如何在WebSockets中使用Spring会话。

WebSockets Guide

WebFlux

演示如何使用Spring会话将Spring WebFlux的web会话替换为Redis。

TBD

HttpSession with Redis JSON serialization

演示如何使用JSON序列化使用Spring Session将HttpSession替换为Redis。

TBD

4. Spring Session Modules

在Spring Session 1.x Spring会话的所有SessionRepository实现都在 spring-session工件中可用。虽然方便,但这种方法不能长期持续,因为项目中添加了更多的特性和SessionRepository实现。

从Spring Session 2.0开始,项目被分割成Spring Session核心模块和其他几个模块,这些模块承载与特定数据存储相关的SessionRepository实现和功能。Spring Data的用户会发现这种安排很熟悉,Spring会话核心模块扮演的角色相当于Spring Data Commons,并为包含特定数据存储实现的其他模块提供核心功能和api。作为分割的一部分,Spring Session Data MongoDB和Spring Session Data GemFire模块被移动到不同的存储库中,因此项目的存储库/模块的情况如下:

  • spring-session repository 托管Spring Session Core、Spring Session Data Redis、Spring Session JDBC和Spring Session Hazelcast模块
  • spring-session-data-mongodb repository  托管Spring Session Data MongoDB模块
  • spring-session-data-geode repository  Hosts Spring Session Data Geode and Spring Session Data Geode modules

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

  • spring-session-bom repository  托管 Spring Session BOM模块

5. HttpSession Integration  httpsession 集成

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

5.1. Why Spring Session & HttpSession?

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

  • Clustered Sessions -  Spring Session使得支持集群会话而不需要绑定到特定于应用程序容器的解决方案变得非常简单。
  • RESTful APIs - Spring Session允许在header中提供会话id来使用RESTful api

5.2. HttpSession with Redis

通过在使用HttpSession的任何东西之前添加Servlet过滤器,可以将Spring会话与HttpSession一起使用。你可以选择启用这两个:

  • Java Based Configuration

  • XML Based Configuration

5.2.1. Redis Java Based Configuration

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

HttpSession示例提供了一个关于如何使用Java配置集成Spring会话和HttpSession的工作示例。您可以阅读下面的集成基本步骤,但是在与您自己的应用程序集成时,建议您遵循详细的HttpSession指南。

Spring Java Configuration

在添加所需的依赖项之后,我们可以创建Spring配置。Spring配置负责创建Servlet筛选器,用Spring会话支持的实现替换HttpSession实现。添加以下Spring配置:

@EnableRedisHttpSession 
public class Config {

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

 

@EnableRedisHttpSession注释创建了一个名为springSessionRepositoryFilter的Spring Bean,该Bean实现了Filter。过滤器负责替换由Spring会话支持的HttpSession实现。在这个实例中,Spring会话是由Redis支持的。

我们创建一个RedisConnectionFactory,它将Spring会话连接到Redis服务器。我们将连接配置为在默认端口(6379)上连接到localhost,以获得有关配置Spring Data Redis的更多信息,请参阅参考文档。

Java Servlet Container Initialization

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

为了让过滤器发挥它的魔力,Spring需要加载配置类。最后,我们需要确保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加载我们的配置。

5.3. HttpSession with JDBC

略。。。。。。

5.4. HttpSession with Hazelcast

略。。。。。。

5.5. How HttpSession Integration Works  集成的工作原理

幸运的是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过滤器替换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,我们确保过滤器之后调用的任何东西都使用自定义HttpSession实现。这强调了为什么Spring Session的SessionRepositoryFilter必须放在与HttpSession交互的任何东西之前。

5.6. HttpSession & RESTful APIs

Spring Session可以通过允许在header中提供会话来使用RESTful api。

REST示例提供了一个关于如何在REST应用程序中使用Spring会话来支持使用头进行身份验证的工作示例。您可以按照下面的基本步骤进行集成,但是在与您自己的应用程序集成时,建议您遵循详细的REST指南。

5.6.1. Spring Configuration

在添加所需的依赖项之后,我们可以创建Spring配置。Spring配置负责创建Servlet筛选器,用Spring会话支持的实现替换HttpSession实现。添加以下Spring配置:

@Configuration
@EnableRedisHttpSession 
public class HttpSessionConfig {

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

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

LettuceConnectionFactory : 我们创建一个RedisConnectionFactory,它将Spring会话连接到Redis服务器。我们将连接配置为在默认端口(6379)上连接到localhost,以获得有关配置Spring Data Redis的更多信息,请参阅参考文档。

@EnableRedisHttpSession :注释创建了一个名为springSessionRepositoryFilter的Spring Bean,该Bean实现了Filter。过滤器负责替换由Spring会话支持的HttpSession实现。在这个实例中,Spring会话是由Redis支持的。

HttpSessionIdResolver: 我们自定义Spring Session的HttpSession集成,以使用HTTP报头来传递当前会话信息,而不是cookie。

5.6.2. Servlet Container Initialization

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

为了让过滤器发挥它的魔力,Spring需要加载配置类。我们在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。

5.7. HttpSessionListener

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

  • 确保您的SessionRepository实现支持并配置为触发SessionDestroyedEvent和SessionCreatedEvent。
  • 将SessionEventHttpSessionListenerAdapter配置为Spring bean。
  • 将每个HttpSessionListener注入到SessionEventHttpSessionListenerAdapter中

如果您正在使用与Redis一起记录在HttpSession中的配置支持,那么您所需要做的就是将每个HttpSessionListener注册为bean。例如,假设您希望支持Spring Security的并发控制,并且需要使用HttpSessionEventPublisher,那么只需将HttpSessionEventPublisher作为bean添加即可。在Java配置中,如下所示:

@Configuration
@EnableRedisHttpSession
public class RedisHttpSessionConfig {

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

	// ...
}

 In XML configuration, this might look like:

 6. WebSocket Integration

略。。。。

7. WebSession Integration

略。。。。

8. Spring Security Integration

略。。。。

9. API Documentation

您可以在线浏览完整的Javadoc。主要api如下:

9.1. Session

会话是名称值对的简化映射。

典型的用法如下:

public class RepositoryDemo {
	private SessionRepository repository; //----A

	public void demo() {
		S toSave = this.repository.createSession(); //----B

		//----C
		User rwinch = new User("rwinch");
		toSave.setAttribute(ATTR_USER, rwinch);

		this.repository.save(toSave); //----D

		S session = this.repository.findById(toSave.getId()); //----E

		//----F
		User user = session.getAttribute(ATTR_USER);
		assertThat(user).isEqualTo(rwinch);
	}

	// ... setter methods ...
}

 

 会话API还提供与会话实例过期相关的属性。

典型的用法如下:

 

  •  A :我们使用扩展会话的泛型类型S创建SessionRepository实例。泛型类型是在我们的类中定义的。
  • B :我们使用SessionRepository创建一个新会话,并将其分配给类型为S的变量。
  • C :我们与会话交互。在我们的示例中,我们演示了如何将用户保存到会话中。
  • D :现在保存会话。这就是我们需要泛型类型s的原因。SessionRepository只允许保存使用相同SessionRepository创建或检索的会话实例。这允许SessionRepository进行特定于实现的优化(即只编写更改的属性)。
  • E :我们从SessionRepository检索会话。
  • F :我们从会话中获取持久用户,而不需要显式地强制转换属性。
public class ExpiringRepositoryDemo {
	private SessionRepository repository; //-----A

	public void demo() {
		S toSave = this.repository.createSession(); //------B
		// ...
		toSave.setMaxInactiveInterval(Duration.ofSeconds(30)); //------C

		this.repository.save(toSave); //-----D

		S session = this.repository.findById(toSave.getId()); //-----E
		// ...
	}

	// ... setter methods ...
}
  • A :我们使用扩展会话的泛型类型S创建SessionRepository实例。泛型类型是在我们的类中定义的。
  • B :我们使用SessionRepository创建一个新会话,并将其分配给类型为S的变量。
  • C :我们与会话交互。在我们的示例中,我们演示了如何更新会话在到期之前可以不活动的时间量。
  • D :现在保存会话。这就是我们需要泛型类型s的原因。SessionRepository只允许保存使用相同SessionRepository创建或检索的会话实例。这允许SessionRepository进行特定于实现的优化(即只编写更改的属性)。保存会话时,最后一次访问时间将自动更新。
  • E :我们从SessionRepository检索会话。如果会话过期,结果将为空。

 9.2. SessionRepository

SessionRepository负责创建、检索和持久化会话实例。

如果可能,开发人员不应该直接与SessionRepository或会话进行交互。相反,开发人员应该更喜欢通过HttpSession和WebSocket集成间接地与SessionRepository和Session交互。

9.3. FindByIndexNameSessionRepository

Spring Session使用会话的最基本API是SessionRepository。这个API故意非常简单,因此很容易提供具有基本功能的附加实现。

一些SessionRepository实现也可以选择实现FindByIndexNameSessionRepository。例如,Spring的Redis、JDBC和Hazelcast都支持FindByIndexNameSessionRepository的实现。

FindByIndexNameSessionRepository提供了一种方法来查找具有给定索引名和索引值的所有会话。作为所有提供的FindByIndexNameSessionRepository实现都支持的通用用例,有一种方便的方法可以查找特定用户的所有会话。这是通过确保会话属性名为FindByIndexNameSessionRepository来实现的。PRINCIPAL_NAME_INDEX_NAME是用用户名填充的。开发人员有责任确保填充属性,因为Spring Session不知道正在使用的身份验证机制。下面是一个如何使用它的例子:

String username = "username";
this.session.setAttribute(
		FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);

 FindByIndexNameSessionRepository的一些实现将提供钩子来自动索引其他会话属性。例如,许多实现将自动确保使用索引名FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME索引当前Spring安全用户名。

一旦会话被索引,可以使用以下方法找到它:

String username = "username";
Map sessionIdToSession = this.sessionRepository
		.findByPrincipalName(username);

9.4. ReactiveSessionRepository

ReactiveSessionRepository负责以非阻塞和响应方式创建、检索和持久化会话实例。

如果可能,开发人员不应该直接与ReactiveSessionRepository或会话交互。相反,开发人员应该更喜欢通过WebSession集成间接地与ReactiveSessionRepository和Session交互。

9.5. EnableSpringHttpSession

@EnableSpringHttpSession注释可以添加到@Configuration类中,以将SessionRepositoryFilter公开为名为“springSessionRepositoryFilter”的bean。为了利用注释,必须提供一个SessionRepository bean。例如:

@EnableSpringHttpSession
@Configuration
public class SpringHttpSessionConfig {
	@Bean
	public MapSessionRepository sessionRepository() {
		return new MapSessionRepository(new ConcurrentHashMap<>());
	}
}

 需要注意的是,没有为会话到期配置现成的基础设施。这是因为像会话过期这样的东西高度依赖于实现。这意味着如果您需要清理过期的会话,那么您需要负责清理过期的会话。

9.6. EnableSpringWebSession

略。。。。

9.7. RedisOperationsSessionRepository

RedisOperationsSessionRepository是一个使用Spring Data的RedisOperations实现的SessionRepository。在web环境中,这通常与SessionRepositoryFilter结合使用。该实现通过SessionMessageListener支持SessionDestroyedEvent和SessionCreatedEvent。

9.7.1. Instantiating a RedisOperationsSessionRepository

下面是如何创建新实例的一个典型例子:

RedisTemplate redisTemplate = new RedisTemplate<>();

// ... configure redisTemplate ...

SessionRepository repository =
		new RedisOperationsSessionRepository(redisTemplate);

有关如何创建RedisConnectionFactory的其他信息,请参阅Spring Data Redis参考资料。

9.7.2. EnableRedisHttpSession

在web环境中,创建新的RedisOperationsSessionRepository最简单的方法是使用@EnableRedisHttpSession。在示例和指南中可以找到完整的示例用法(从这里开始),您可以使用以下属性来定制配置:

  • maxInactiveIntervalInSeconds :会话结束前的时间以秒为单位
  • redisNamespace :允许为会话配置特定于应用程序的命名空间。Redis键和通道id将以:的前缀开头。
  • redisFlushMode :允许指定何时将数据写入Redis。只有在SessionRepository上调用save时,才使用默认值。RedisFlushMode.IMMEDIATE会尽快给Redis写信。

Custom RedisSerializer

您可以通过创建一个名为springSessionDefaultRedisSerializer的Bean来定制序列化,该Bean实现了RedisSerializer

9.7.3. Redis TaskExecutor

使用RedisMessageListenerContainer订阅RedisOperationsSessionRepository从redis接收事件。您可以通过创建名为springSessionRedisTaskExecutor和/或springSessionRedisSubscriptionExecutor的Bean来定制这些事件的分发方式。有关配置redis任务执行器的详细信息,请在这里找到。

9.7.4. Storage Details

下面的部分概述了如何为每个操作更新Redis。下面是创建新会话的示例。接下来的部分将描述详细信息。

HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe creationTime 1404360000000 \
	maxInactiveInterval 1800 \
	lastAccessedTime 1404360000000 \
	sessionAttr:attrName someAttrValue \
	sessionAttr2:attrName someAttrValue2
EXPIRE spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe 2100
APPEND spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe ""
EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
SADD spring:session:expirations:1439245080000 expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe
EXPIRE spring:session:expirations1439245080000 2100

Saving a Session

每个会话都以Hash的形式存储在Redis中。使用HMSET命令设置和更新每个会话。下面是如何存储每个会话的示例。

HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe creationTime 1404360000000 \
	maxInactiveInterval 1800 \
	lastAccessedTime 1404360000000 \
	sessionAttr:attrName someAttrValue \
	sessionAttr2:attrName someAttrValue2

在这个例子中,下列关于会话的语句是正确的:

  • The session ID is 33fdd1b6-b496-4b33-9f7d-df96679d32fe
  • 从格林威治时间1970年1月1日午夜开始,会话以1404360000000毫秒的速度创建。
  • 会话将在1800秒(30分钟)后结束。
  • 最后一次访问会话是在格林尼治时间1970年1月1日午夜之后的1404360000000毫秒。
  • 会话有两个属性。第一个是值为“someAttrValue”的“attrName”。第二个会话属性名为“attrName2”,值为“someAttrValue2”。

 Optimized Writes  优化写入

RedisOperationsSessionRepository管理的会话实例跟踪已更改的属性,并只更新这些属性。这意味着如果一个属性只写一次,并且读了很多次,那么我们只需要写那个属性一次。例如,假设更新了前面的会话属性“sessionAttr2”。保存后将执行以下命令:

HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe sessionAttr:attrName2 newValue

Session Expiration

使用基于Session.getMaxInactiveInterval()的EXPIRE命令将过期关联到每个会话。例如:

EXPIRE spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe 2100

您将注意到设置的到期时间是在会话实际到期后5分钟。这是必要的,以便在会话到期时可以访问会话的值。会话本身在实际过期5分钟后设置过期,以确保对其进行清理,但必须在执行任何必要的处理之后。

SessionRepository.findById(String)方法确保不会返回过期的会话。这意味着在使用会话之前不需要检查过期时间。

Spring会话分别依赖于Redis的delete和过期密钥空间通知来触发SessionDeletedEvent和SessionExpiredEvent。SessionDeletedEvent或SessionExpiredEvent确保清理与会话相关的资源。例如,在使用Spring Session的WebSocket支持时,Redis过期或删除事件会触发与会话相关的任何WebSocket连接被关闭。

过期不会直接在会话密钥本身上跟踪,因为这意味着会话数据将不再可用。取而代之的是使用一个特殊的会话过期密钥。在我们的例子中,expires键是:

APPEND spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe ""
EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800

当会话过期键被删除或过期时,keyspace通知触发对实际会话的查找,并触发SessionDestroyedEvent。

仅依赖于Redis到期的一个问题是,如果未访问密钥,Redis不能保证过期事件何时触发。具体来说,Redis用来清理过期密钥的后台任务是一个低优先级任务,可能不会触发密钥过期。有关更多详细信息,请参见Redis文档中的过期事件时间一节。

为了避免过期事件不一定会发生这一事实,我们可以确保在预期到期时访问每个密钥。这意味着如果TTL在密钥上过期,当我们试图访问密钥时,Redis将删除密钥并触发过期事件。

因此,每个会话过期也被跟踪到最近的一分钟。这允许后台任务访问可能过期的会话,以确保以更确定的方式触发Redis过期事件。例如:

SADD spring:session:expirations:1439245080000 expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe
EXPIRE spring:session:expirations1439245080000 2100

然后后台任务将使用这些映射显式地请求每个键。通过访问密钥而不是删除它,我们确保只有在TTL过期时,Redis才会为我们删除密钥。

我们不显式地删除键,因为在某些情况下,可能存在竞态条件,该条件错误地将未过期的键标识为过期。如果不使用分布式锁(这会损害我们的性能),就无法确保过期映射的一致性。通过简单地访问密钥,我们确保只有在该密钥上的TTL过期时才删除该密钥。

9.7.5. SessionDeletedEvent and SessionExpiredEvent

SessionDeletedEvent和SessionExpiredEvent都是SessionDestroyedEvent的类型。

RedisOperationsSessionRepository支持在会话被删除时触发SessionDeletedEvent,或者在会话过期时触发SessionExpiredEvent。这对于确保正确清理与会话相关的资源是必要的。

例如,当与WebSocket集成时,SessionDestroyedEvent负责关闭任何活动的WebSocket连接。

触发SessionDeletedEvent或SessionExpiredEvent可以通过监听Redis Keyspace事件的SessionMessageListener获得。为了使其工作,需要为通用命令和过期事件启用Redis Keyspace事件。例如:

redis-cli config set notify-keyspace-events Egx

如果您使用@EnableRedisHttpSession,那么SessionMessageListener和启用必要的Redis Keyspace事件将自动完成。然而,在安全的Redis环境中,配置命令是禁用的。这意味着Spring会话不能为您配置Redis Keyspace事件。要禁用自动配置,请添加ConfigureRedisAction。NO_OP作为bean。

例如,Java配置可以使用以下方法:

@Bean
public static ConfigureRedisAction configureRedisAction() {
	return ConfigureRedisAction.NO_OP;
}

XML Configuration can use the following:

9.7.6. SessionCreatedEvent

创建会话时,使用spring:session:channel:created:33fdd1b6-b496-4b33-9f7d-df96679d32fe通道将事件发送到Redis,使33fdd1b6-b496-4b33-9f7d-df96679d32fe为会话ID。

如果注册为MessageListener(默认),那么RedisOperationsSessionRepository将把Redis消息转换为SessionCreatedEvent。

9.7.7. Viewing the Session in Redis

安装Redis -cli之后,可以使用Redis -cli检查Redis中的值。例如,在终端中输入以下内容:

$ redis-cli
redis 127.0.0.1:6379> keys *
1) "spring:session:sessions:4fc39ce3-63b3-4e17-b1c4-5e1ed96fb021"   ------A
2) "spring:session:expirations:1418772300000" --------B

A:此键的后缀是Spring会话的会话标识符。

B:此键包含在1418772300000时应删除的所有会话id。

您还可以查看每个会话的属性。

redis 127.0.0.1:6379> hkeys spring:session:sessions:4fc39ce3-63b3-4e17-b1c4-5e1ed96fb021
1) "lastAccessedTime"
2) "creationTime"
3) "maxInactiveInterval"
4) "sessionAttr:username"
redis 127.0.0.1:6379> hget spring:session:sessions:4fc39ce3-63b3-4e17-b1c4-5e1ed96fb021 sessionAttr:username
"\xac\xed\x00\x05t\x00\x03rob"

9.8. ReactiveRedisOperationsSessionRepository

略。。。。

9.9. MapSessionRepository

略。。。。

9.10. ReactiveMapSessionRepository

略。。。。

9.11. JdbcOperationsSessionRepository

略。。。

9.12. HazelcastSessionRepository

略。。。。

10. Custom SessionRepository

略。。。

11. Upgrading to 2.x

在新的主要版本中,Spring Session团队利用这个机会进行了一些非被动的更改。这些更改的重点是改进和协调Spring Session的api,以及删除不赞成使用的组件。

11.1. Baseline update

Spring Session 2.0需要Java 8和Spring Framework 5.0作为基线,因为它的整个代码库现在都基于Java 8源代码。请参阅升级到Spring Framework 5的指南。x用于升级Spring框架。

11.2. Replaced and Removed Modules

作为项目划分模块的一部分,现有的spring-session已被spring-session-core模块所替代。spring- sessioncore模块只包含公共api和组件集,而其他模块则包含相应SessionRepository的实现以及与该数据存储相关的功能。这适用于几个现有的,以前是一个简单的依赖聚合器帮助模块,但与新的模块安排,实际上携带的实现:

  • Spring Session Data Redis

  • Spring Session JDBC

  • Spring Session Hazelcast

此外,从主要项目储存库中删除了以下模块:

  • Spring Session Data MongoDB

  • Spring Session Data GemFire

请注意,这两个库已经转移到不同的存储库,并且将继续可用,尽管是在一个变更的工件名称下:

  • spring-session-data-mongodb

  • spring-session-data-geode

11.3. Replaced and Removed Packages, Classes and Methods

  • ExpiringSession API has been merged into Session API

  • Session API has been enhanced to make full use of Java 8

  • Session API has been extended with changeSessionId support

  • SessionRepository API has been updated to better align with Spring Data method naming conventions

  • AbstractSessionEvent and its subclasses are no longer constructable without an underlying Session object

  • Redis namespace used by RedisOperationsSessionRepository is now fully configurable, instead of being partial configurable

  • Redis configuration support has been updated to avoid registering a Spring Session specific RedisTemplate bean

  • JDBC configuration support has been updated to avoid registering a Spring Session specific JdbcTemplate bean

  • Previously deprecated classes and methods have been removed across the codebase

11.4. Dropped Support

作为对HttpSessionStrategy的更改的一部分,以及它与来自响应世界的对应项的对齐,在单个浏览器实例中管理多个用户会话的支持已经被删除。未来的版本将考虑引入新的API来替代此功能。

 

你可能感兴趣的:(Spring,Session)