WebSession Integration

Spring Session 提供了与 Spring WebFlux 的 WebSession 的透明集成。这意味着你可以用 Spring Session 支持的实现来替换 WebSession 实现。

Why Spring Session and WebSession?

我们已经提到 Spring Session 提供了与 Spring WebFlux 的 WebSession 的透明集成,但我们能从中得到什么好处?与 HttpSession 一样,Spring Session 让支持 clustered sessions 变得轻而易举,而无需绑定到特定于应用程序容器的解决方案。

WebSession with Redis

通过注册由 Spring Session ReactiveSessionRepository 支持的 WebSessionManager 实现,即可启用在 WebSession 上使用 Spring Session。Spring 配置负责创建一个 WebSessionManager,它用 Spring Session 支持的实现替换 WebSession 实现。为此,添加以下 Spring 配置:

@EnableRedisWebSession (1)
public class SessionConfiguration {

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

}
1 @EnableRedisWebSession 注释创建的 Spring Bean 名称是 webSessionManager。该 Bean 实现 WebSessionManager。这就是负责用 Spring 会话替换 WebSession 实现,使其由 Spring 会话支持。在此例中,Spring 会话由 Redis 支持。
2 我们创建一个 RedisConnectionFactory,将 Spring 会话连接到 Redis 服务器。我们配置连接以在默认端口 (6379) 上连接到 localhost。有关配置 Spring 数据 Redis 的更多信息,请参阅 {docs-url}/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[参考文档]。

How WebSession Integration Works

Spring Session 与 Spring WebFlux 及其 WebSession 集成比与 Servlet API 及其 HttpSession 集成要容易得多。Spring WebFlux 提供 WebSessionStore API,它提供了一种持久化 WebSession 的策略。

本节描述了 Spring Session 如何与 WebSession 透明集成。我们提供此内容以便您可以理解在幕后发生的情况。此功能已集成,您不需要自己实现此逻辑。

首先,我们创建一个自定义 SpringSessionWebSession,它委托给 Spring Session 的 Session。它看起来如下所示:

public class SpringSessionWebSession implements WebSession {

	enum State {
		NEW, STARTED
	}

	private final S session;

	private AtomicReference<State> state = new AtomicReference<>();

	SpringSessionWebSession(S session, State state) {
		this.session = session;
		this.state.set(state);
	}

	@Override
	public void start() {
		this.state.compareAndSet(State.NEW, State.STARTED);
	}

	@Override
	public boolean isStarted() {
		State value = this.state.get();
		return (State.STARTED.equals(value)
				|| (State.NEW.equals(value) && !this.session.getAttributes().isEmpty()));
	}

	@Override
	public Mono<Void> changeSessionId() {
		return Mono.defer(() -> {
			this.session.changeSessionId();
			return save();
		});
	}

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

接下来,我们创建一个自定义 WebSessionStore,它委托给 ReactiveSessionRepository,并将 Session 包装到自定义 WebSession 实现中,如下面的清单所示:

public class SpringSessionWebSessionStore<S extends Session> implements WebSessionStore {

	private final ReactiveSessionRepository<S> sessions;

	public SpringSessionWebSessionStore(ReactiveSessionRepository<S> reactiveSessionRepository) {
		this.sessions = reactiveSessionRepository;
	}

	// ...
}

为了让 Spring WebFlux 检测到,此自定义 WebSessionStore 需要使用名为 webSessionManager 的 bean 注册在 ApplicationContext 中。有关 Spring WebFlux 的更多信息,请参阅 {docs-url}/spring-framework/docs/{spring-core-version}/reference/html/web-reactive.html[Spring Framework 参考文档]。