web-session.md 4.7 KB
Newer Older
茶陵後's avatar
茶陵後 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
# WebSession Integration

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?

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 [clustered sessions](#websession-redis) without being tied to an application container specific solution.

## WebSession with Redis

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`.<br/>This is what is in charge of replacing the `WebSession` implementation to be backed by Spring Session.<br/>In this instance, Spring Session is backed by Redis.              |
|-----|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.<br/>We configure the connection to connect to localhost on the default port (6379)<br/>For more information on configuring Spring Data Redis, see the [reference documentation](https://docs.spring.io/spring-data/data-redis/docs/2.6.2/reference/html/).|

## How WebSession Integration Works

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`.

|   |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.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

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
}
```

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;
	}

	// ...
}
```

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 [Spring Framework Reference Documentation](https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/web-reactive.html).