By default an instance of {@link CookieWebSessionIdResolver}.
+ *
+ * By default an instance of {@link CookieWebSessionIdResolver}.
* @param sessionIdResolver the resolver to use
*/
public void setSessionIdResolver(WebSessionIdResolver sessionIdResolver) {
@@ -59,27 +73,31 @@ public class SpringSessionWebSessionManager implements WebSessionManager {
this.sessionIdResolver = sessionIdResolver;
}
- /**
- * Return the configured {@link WebSessionIdResolver}.
- */
- private WebSessionIdResolver getSessionIdResolver() {
- return this.sessionIdResolver;
- }
-
/**
* Return the configured {@link WebSessionStore}.
+ * @return the configured {@link WebSessionStore}
*/
private WebSessionStore getSessionStore() {
return this.sessionStore;
}
/**
- * Configure the {@link Clock} to use to set lastAccessTime on every created
- * session and to calculate if it is expired.
- *
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.
- *
By default this is {@code Clock.system(ZoneId.of("GMT"))}.
+ * Return the configured clock for session {@code lastAccessTime} calculations.
+ * @return the configured clock for session {@code lastAccessTime} calculations
+ */
+ private Clock getClock() {
+ return this.clock;
+ }
+
+ /**
+ * Configure the {@link Clock} to use to set lastAccessTime on every created session
+ * and to calculate if it is expired.
+ *
+ * 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.
+ *
+ * By default this is {@code Clock.system(ZoneOffset.UTC)}.
* @param clock the clock to use
*/
public void setClock(Clock clock) {
@@ -87,15 +105,9 @@ public class SpringSessionWebSessionManager implements WebSessionManager {
this.clock = clock;
}
- /**
- * Return the configured clock for session lastAccessTime calculations.
- */
- private Clock getClock() {
- return this.clock;
- }
-
@Override
public Mono getSession(ServerWebExchange exchange) {
+ // @formatter:off
return Mono.defer(() ->
retrieveSession(exchange)
.flatMap(session -> removeSessionIfExpired(exchange, session))
@@ -105,16 +117,20 @@ public class SpringSessionWebSessionManager implements WebSessionManager {
})
.switchIfEmpty(createSession(exchange))
.doOnNext(session -> exchange.getResponse().beforeCommit(session::save)));
+ // @formatter:on
}
private Mono retrieveSession(ServerWebExchange exchange) {
+ // @formatter:off
return Flux.fromIterable(getSessionIdResolver().resolveSessionIds(exchange))
.concatMap(this.sessionStore::retrieveSession)
.cast(WebSession.class)
.next();
+ // @formatter:on
}
- private Mono removeSessionIfExpired(ServerWebExchange exchange, WebSession session) {
+ private Mono removeSessionIfExpired(ServerWebExchange exchange,
+ WebSession session) {
if (session.isExpired()) {
this.sessionIdResolver.expireSession(exchange);
return this.sessionStore.removeSession(session.getId()).then(Mono.empty());
@@ -125,10 +141,10 @@ public class SpringSessionWebSessionManager implements WebSessionManager {
private Mono saveSession(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()."));
+ "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()."));
}
if (!session.isStarted()) {
@@ -153,4 +169,5 @@ public class SpringSessionWebSessionManager implements WebSessionManager {
private Mono createSession(ServerWebExchange exchange) {
return this.sessionStore.createSession();
}
+
}
diff --git a/spring-session-core/src/main/java/org/springframework/session/web/server/session/SpringSessionWebSessionStore.java b/spring-session-core/src/main/java/org/springframework/session/web/server/session/SpringSessionWebSessionStore.java
index 427060d5..c73f494c 100644
--- a/spring-session-core/src/main/java/org/springframework/session/web/server/session/SpringSessionWebSessionStore.java
+++ b/spring-session-core/src/main/java/org/springframework/session/web/server/session/SpringSessionWebSessionStore.java
@@ -16,25 +16,39 @@
package org.springframework.session.web.server.session;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+import reactor.core.publisher.Mono;
+
import org.springframework.lang.Nullable;
import org.springframework.session.ReactorSessionRepository;
import org.springframework.session.Session;
import org.springframework.util.Assert;
import org.springframework.web.server.WebSession;
import org.springframework.web.server.session.WebSessionStore;
-import reactor.core.publisher.Mono;
-
-import java.time.Duration;
-import java.time.Instant;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Supplier;
/**
+ * The {@link WebSessionStore} implementation that provides the {@link WebSession}
+ * implementation backed by a {@link Session} returned by the
+ * {@link ReactorSessionRepository}.
+ *
+ * @param the {@link Session} type
* @author Rob Winch
* @since 2.0
*/
class SpringSessionWebSessionStore implements WebSessionStore {
+
private final ReactorSessionRepository sessions;
SpringSessionWebSessionStore(ReactorSessionRepository sessions) {
@@ -48,6 +62,7 @@ class SpringSessionWebSessionStore implements WebSessionStore
public Mono setLastAccessedTime(WebSession session,
Instant lastAccessedTime) {
+ @SuppressWarnings("unchecked")
SpringSessionWebSession springSessionWebSession = (SpringSessionWebSession) session;
springSessionWebSession.session.setLastAccessedTime(lastAccessedTime);
return Mono.just(session);
@@ -80,92 +95,17 @@ class SpringSessionWebSessionStore implements WebSessionStore
@Override
public Mono removeSession(String sessionId) {
- return sessions.delete(sessionId);
- }
-
- private class SpringSessionWebSession implements WebSession {
- private final S session;
-
- private final Map attributes;
-
- private AtomicReference state = new AtomicReference<>();
-
- private volatile transient Supplier> saveOperation = Mono::empty;
-
- SpringSessionWebSession(S session, State state) {
- Assert.notNull(session, "session cannot be null");
- this.session = session;
- this.attributes = new SpringSessionMap(session);
- this.state.set(state);
- }
-
- @Override
- public String getId() {
- return session.getId();
- }
-
- @Override
- public Mono changeSessionId() {
- return Mono.defer(() -> {
- session.changeSessionId();
- return save();
- });
- }
-
- @Override
- public Map getAttributes() {
- return this.attributes;
- }
-
- @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) && !getAttributes().isEmpty()));
- }
-
- @Override
- public Mono save() {
- return this.saveOperation.get();
- }
-
- @Override
- public boolean isExpired() {
- return this.session.isExpired();
- }
-
- @Override
- public Instant getCreationTime() {
- return this.session.getCreationTime();
- }
-
- @Override
- public Instant getLastAccessTime() {
- return this.session.getLastAccessedTime();
- }
-
- @Override
- public void setMaxIdleTime(Duration maxIdleTime) {
- this.session.setMaxInactiveInterval(maxIdleTime);
- }
-
- @Override
- public Duration getMaxIdleTime() {
- return this.session.getMaxInactiveInterval();
- }
+ return this.sessions.delete(sessionId);
}
private enum State {
NEW, STARTED
}
- static class SpringSessionMap implements Map {
+ private static class SpringSessionMap implements Map {
+
private final Session session;
+
private final Collection