DefaultWebSessionManager decoupled from DefaultWebSession
DefaultWebSessionManager no longer requires the WebSessionStore to use DefaultWebSession. Removed explicit start() in save(). This seemed unnecessary since at that point isStarted is guaranteed to return true. The status can be updated through the copy constructor. DefaultWebSessionTests added. Issue: SPR-15875
This commit is contained in:
committed by
Rossen Stoyanchev
parent
86912475af
commit
8ad14ae95c
@@ -86,28 +86,9 @@ class DefaultWebSession implements WebSession {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to refresh an existing session for a new request.
|
||||
* @param existingSession the session to recreate
|
||||
* @param lastAccessTime the last access time
|
||||
* @param saveOperation save operation for the current request
|
||||
*/
|
||||
DefaultWebSession(DefaultWebSession existingSession, Instant lastAccessTime,
|
||||
Function<WebSession, Mono<Void>> saveOperation) {
|
||||
|
||||
this.id = existingSession.id;
|
||||
this.idGenerator = existingSession.idGenerator;
|
||||
this.attributes = existingSession.attributes;
|
||||
this.clock = existingSession.clock;
|
||||
this.changeIdOperation = existingSession.changeIdOperation;
|
||||
this.saveOperation = saveOperation;
|
||||
this.creationTime = existingSession.creationTime;
|
||||
this.lastAccessTime = lastAccessTime;
|
||||
this.maxIdleTime = existingSession.maxIdleTime;
|
||||
this.state = existingSession.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing purposes.
|
||||
* Constructor for creating a new session with an updated last access time.
|
||||
* @param existingSession the existing session to copy
|
||||
* @param lastAccessTime the new last access time
|
||||
*/
|
||||
DefaultWebSession(DefaultWebSession existingSession, Instant lastAccessTime) {
|
||||
this.id = existingSession.id;
|
||||
@@ -119,7 +100,7 @@ class DefaultWebSession implements WebSession {
|
||||
this.creationTime = existingSession.creationTime;
|
||||
this.lastAccessTime = lastAccessTime;
|
||||
this.maxIdleTime = existingSession.maxIdleTime;
|
||||
this.state = existingSession.state;
|
||||
this.state = existingSession.isStarted() ? State.STARTED : State.NEW;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.web.server.session;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
@@ -43,9 +40,6 @@ public class DefaultWebSessionManager implements WebSessionManager {
|
||||
|
||||
private WebSessionStore sessionStore = new InMemoryWebSessionStore();
|
||||
|
||||
private Clock clock = Clock.system(ZoneId.of("GMT"));
|
||||
|
||||
|
||||
/**
|
||||
* Configure the id resolution strategy.
|
||||
* <p>By default an instance of {@link CookieWebSessionIdResolver}.
|
||||
@@ -80,38 +74,14 @@ public class DefaultWebSessionManager implements WebSessionManager {
|
||||
return this.sessionStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link Clock} to use to set lastAccessTime on every created
|
||||
* session and to calculate if it is expired.
|
||||
* <p>This may be useful to align to different timezone or to set the clock
|
||||
* back in a test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))}
|
||||
* in order to simulate session expiration.
|
||||
* <p>By default this is {@code Clock.system(ZoneId.of("GMT"))}.
|
||||
* @param clock the clock to use
|
||||
*/
|
||||
public void setClock(Clock clock) {
|
||||
Assert.notNull(clock, "'clock' is required.");
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured clock for session lastAccessTime calculations.
|
||||
*/
|
||||
public Clock getClock() {
|
||||
return this.clock;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Mono<WebSession> getSession(ServerWebExchange exchange) {
|
||||
return Mono.defer(() ->
|
||||
retrieveSession(exchange)
|
||||
.flatMap(session -> removeSessionIfExpired(exchange, session))
|
||||
.flatMap(this.getSessionStore()::updateLastAccessTime)
|
||||
.switchIfEmpty(createSession(exchange))
|
||||
.cast(DefaultWebSession.class)
|
||||
.map(session -> new DefaultWebSession(session, session.getLastAccessTime(), s -> saveSession(exchange, s)))
|
||||
.doOnNext(session -> exchange.getResponse().beforeCommit(session::save)));
|
||||
.switchIfEmpty(this.sessionStore.createWebSession())
|
||||
.doOnNext(session -> exchange.getResponse().beforeCommit(() -> save(exchange, session))));
|
||||
}
|
||||
|
||||
private Mono<WebSession> retrieveSession(ServerWebExchange exchange) {
|
||||
@@ -128,35 +98,28 @@ public class DefaultWebSessionManager implements WebSessionManager {
|
||||
return Mono.just(session);
|
||||
}
|
||||
|
||||
private Mono<Void> saveSession(ServerWebExchange exchange, WebSession session) {
|
||||
private Mono<Void> save(ServerWebExchange exchange, WebSession session) {
|
||||
if (session.isExpired()) {
|
||||
return Mono.error(new IllegalStateException(
|
||||
"Sessions are checked for expiration and have their " +
|
||||
"lastAccessTime updated when first accessed during request processing. " +
|
||||
"However this session is expired meaning that maxIdleTime elapsed " +
|
||||
"before the call to session.save()."));
|
||||
"lastAccessTime updated when first accessed during request processing. " +
|
||||
"However this session is expired meaning that maxIdleTime elapsed " +
|
||||
"before the call to session.save()."));
|
||||
}
|
||||
|
||||
if (!session.isStarted()) {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
// Force explicit start
|
||||
session.start();
|
||||
|
||||
if (hasNewSessionId(exchange, session)) {
|
||||
this.sessionIdResolver.setSessionId(exchange, session.getId());
|
||||
DefaultWebSessionManager.this.sessionIdResolver.setSessionId(exchange, session.getId());
|
||||
}
|
||||
|
||||
return this.sessionStore.storeSession(session);
|
||||
return session.save();
|
||||
}
|
||||
|
||||
private boolean hasNewSessionId(ServerWebExchange exchange, WebSession session) {
|
||||
List<String> ids = getSessionIdResolver().resolveSessionIds(exchange);
|
||||
return ids.isEmpty() || !session.getId().equals(ids.get(0));
|
||||
}
|
||||
|
||||
private Mono<WebSession> createSession(ServerWebExchange exchange) {
|
||||
return this.sessionStore.createWebSession();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user