WebSession 統合

Spring Session は、Spring WebFlux の WebSession との透過的な統合を提供します。これは、Spring Session による実装で WebSession 実装を切り替えることができることを意味します。

なぜ Spring Session と WebSession なのでしょうか?

Spring Session が Spring WebFlux の WebSession との透過的な統合を提供することはすでに述べましたが、これからどのようなメリットが得られますか? HttpSession と同様に、Spring Session を使用すると、アプリケーションコンテナー固有のソリューションに縛られることなく、クラスター化されたセッションを簡単にサポートできます。

Redis を使用した WebSession

WebSession で Spring Session を使用するには、Spring Session の ReactiveSessionRepository に基づく WebSessionManager 実装を登録します。Spring 構成は、WebSession 実装を Spring Session による実装に置き換える WebSessionManager の作成を担当します。これを行うには、次の Spring 構成を追加します。

@EnableRedisWebSession (1)
public class SessionConfiguration {

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

}
1@EnableRedisWebSession アノテーションは、webSessionManager という名前の Spring Bean を作成します。その Bean は WebSessionManager を実装します。これは、Spring Session によってサポートされる WebSession 実装の置き換えを担当するものです。この場合、Spring Session は Redis によってサポートされています。
2Spring Session を Redis サーバーに接続する RedisConnectionFactory を作成します。デフォルトのポート (6379) でローカルホストに接続するように接続を構成します。Spring Data の構成の詳細については、リファレンスドキュメントを参照してください

WebSession 統合の仕組み

サーブレット API とその HttpSession と比較して、Spring Session が Spring WebFlux とその WebSession と統合するのはかなり簡単です。Spring WebFlux は、WebSession を永続化するための戦略を提示する WebSessionStore API を提供します。

このセクションでは、Spring Session が WebSession との透過的な統合を提供する方法について説明します。このコンテンツは、内部で何が起こっているのかを理解できるように提供しています。この機能はすでに統合されており、このロジックを自分で実装する必要はありません。

まず、Spring Session の Session に委譲するカスタム SpringSessionWebSession を作成します。次のようになります。

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
}

次に、次のように、ReactiveSessionRepository に委譲し、Session をカスタム WebSession 実装にラップするカスタム WebSessionStore を作成します。

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 の詳細については、Spring Framework リファレンスドキュメントを参照してください。