WebSession Integration

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

Spring Session provides transparent integration with Spring WebFlux’s WebSession. This means that you can switch the WebSession implementation out with an implementation that is backed by Spring Session.

Why Spring Session and WebSession?

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

We have already mentioned that Spring Session provides transparent integration with Spring WebFlux’s WebSession, but what benefits do we get out of this? As with HttpSession, Spring Session makes it trivial to support websession-redis without being tied to an application container specific solution.

WebSession with Redis

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

Using Spring Session with WebSession is enabled by registering a WebSessionManager implementation backed by Spring Session’s ReactiveSessionRepository. The Spring configuration is responsible for creating a WebSessionManager that replaces the WebSession implementation with an implementation backed by Spring Session. To do so, add the following Spring Configuration:

@EnableRedisWebSession (1)
public class SessionConfiguration {

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

}
1 The @EnableRedisWebSession annotation creates a Spring bean with the name of webSessionManager. That bean implements the WebSessionManager. This is what is in charge of replacing the WebSession implementation to be backed by Spring Session. In this instance, Spring Session is backed by Redis.
2 We create a RedisConnectionFactory that connects Spring Session to the Redis Server. We configure the connection to connect to localhost on the default port (6379) For more information on configuring Spring Data Redis, see the {docs-url}/spring-data/data-redis/docs/{spring-data-redis-version}/reference/html/[reference documentation].

How WebSession Integration Works

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

It is considerably easier for Spring Session to integrate with Spring WebFlux and its WebSession, compared to Servlet API and its HttpSession. Spring WebFlux provides the WebSessionStore API, which presents a strategy for persisting WebSession.

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

This section describes how Spring Session provides transparent integration with WebSession. We offer this content so that you can understand what is happening under the covers. This functionality is already integrated and you do NOT need to implement this logic yourself.

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

First, we create a custom SpringSessionWebSession that delegates to Spring Session’s Session. It looks something like the following:

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 实现中,如下面的清单所示:

Next, we create a custom WebSessionStore that delegates to the ReactiveSessionRepository and wraps Session into custom WebSession implementation, as the following listing shows:

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 参考文档]。

To be detected by Spring WebFlux, this custom WebSessionStore needs to be registered with ApplicationContext as a bean named webSessionManager. For additional information on Spring WebFlux, see the {docs-url}/spring-framework/docs/{spring-core-version}/reference/html/web-reactive.html[Spring Framework Reference Documentation].