Skip to content

Commit 2fc2dab

Browse files
committed
Fold DefaultWebSession within InMemoryWebSessionStore
InMemoryWebSessionStore is very closely associated to DefaultWebSession passing it to it several fields and functions. Now that the store also creates the session, it makes sense to bring the latter in as an inner, nested class. Issue: SPR-15875, 15876
1 parent c7d54c8 commit 2fc2dab

File tree

4 files changed

+130
-211
lines changed

4 files changed

+130
-211
lines changed

spring-web/src/main/java/org/springframework/web/server/session/DefaultWebSession.java

Lines changed: 0 additions & 176 deletions
This file was deleted.

spring-web/src/main/java/org/springframework/web/server/session/InMemoryWebSessionStore.java

Lines changed: 109 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@
1616
package org.springframework.web.server.session;
1717

1818
import java.time.Clock;
19+
import java.time.Duration;
1920
import java.time.Instant;
2021
import java.time.ZoneId;
2122
import java.util.Map;
2223
import java.util.concurrent.ConcurrentHashMap;
24+
import java.util.concurrent.atomic.AtomicReference;
25+
26+
import reactor.core.publisher.Mono;
2327

2428
import org.springframework.util.Assert;
2529
import org.springframework.util.IdGenerator;
2630
import org.springframework.util.JdkIdGenerator;
27-
import reactor.core.publisher.Mono;
28-
2931
import org.springframework.web.server.WebSession;
3032

3133
/**
@@ -67,6 +69,11 @@ public Clock getClock() {
6769
}
6870

6971

72+
@Override
73+
public Mono<WebSession> createWebSession() {
74+
return Mono.fromSupplier(InMemoryWebSession::new);
75+
}
76+
7077
@Override
7178
public Mono<WebSession> retrieveSession(String id) {
7279
return (this.sessions.containsKey(id) ? Mono.just(this.sessions.get(id)) : Mono.empty());
@@ -78,21 +85,16 @@ public Mono<Void> removeSession(String id) {
7885
return Mono.empty();
7986
}
8087

81-
public Mono<WebSession> createWebSession() {
82-
return Mono.fromSupplier(() ->
83-
new DefaultWebSession(idGenerator, getClock(),
84-
(oldId, session) -> this.changeSessionId(oldId, session),
85-
this::storeSession));
86-
}
87-
8888
public Mono<WebSession> updateLastAccessTime(WebSession webSession) {
8989
return Mono.fromSupplier(() -> {
90-
DefaultWebSession session = (DefaultWebSession) webSession;
90+
InMemoryWebSession session = (InMemoryWebSession) webSession;
9191
Instant lastAccessTime = Instant.now(getClock());
92-
return new DefaultWebSession(session, lastAccessTime);
92+
return new InMemoryWebSession(session, lastAccessTime);
9393
});
9494
}
9595

96+
/* Private methods for InMemoryWebSession */
97+
9698
private Mono<Void> changeSessionId(String oldId, WebSession session) {
9799
this.sessions.remove(oldId);
98100
this.sessions.put(session.getId(), session);
@@ -103,4 +105,100 @@ private Mono<Void> storeSession(WebSession session) {
103105
this.sessions.put(session.getId(), session);
104106
return Mono.empty();
105107
}
108+
109+
110+
private class InMemoryWebSession implements WebSession {
111+
112+
private final AtomicReference<String> id;
113+
114+
private final Map<String, Object> attributes;
115+
116+
private final Instant creationTime;
117+
118+
private final Instant lastAccessTime;
119+
120+
private volatile Duration maxIdleTime;
121+
122+
private volatile boolean started;
123+
124+
125+
InMemoryWebSession() {
126+
this.id = new AtomicReference<>(String.valueOf(idGenerator.generateId()));
127+
this.attributes = new ConcurrentHashMap<>();
128+
this.creationTime = Instant.now(getClock());
129+
this.lastAccessTime = this.creationTime;
130+
this.maxIdleTime = Duration.ofMinutes(30);
131+
}
132+
133+
InMemoryWebSession(InMemoryWebSession existingSession, Instant lastAccessTime) {
134+
this.id = existingSession.id;
135+
this.attributes = existingSession.attributes;
136+
this.creationTime = existingSession.creationTime;
137+
this.lastAccessTime = lastAccessTime;
138+
this.maxIdleTime = existingSession.maxIdleTime;
139+
this.started = existingSession.isStarted(); // Use method (explicit or implicit start)
140+
}
141+
142+
143+
@Override
144+
public String getId() {
145+
return this.id.get();
146+
}
147+
148+
@Override
149+
public Map<String, Object> getAttributes() {
150+
return this.attributes;
151+
}
152+
153+
@Override
154+
public Instant getCreationTime() {
155+
return this.creationTime;
156+
}
157+
158+
@Override
159+
public Instant getLastAccessTime() {
160+
return this.lastAccessTime;
161+
}
162+
163+
@Override
164+
public void setMaxIdleTime(Duration maxIdleTime) {
165+
this.maxIdleTime = maxIdleTime;
166+
}
167+
168+
@Override
169+
public Duration getMaxIdleTime() {
170+
return this.maxIdleTime;
171+
}
172+
173+
174+
@Override
175+
public void start() {
176+
this.started = true;
177+
}
178+
179+
@Override
180+
public boolean isStarted() {
181+
return this.started || !getAttributes().isEmpty();
182+
}
183+
184+
@Override
185+
public Mono<Void> changeSessionId() {
186+
String oldId = this.id.get();
187+
String newId = String.valueOf(idGenerator.generateId());
188+
this.id.set(newId);
189+
return InMemoryWebSessionStore.this.changeSessionId(oldId, this).doOnError(ex -> this.id.set(oldId));
190+
}
191+
192+
@Override
193+
public Mono<Void> save() {
194+
return InMemoryWebSessionStore.this.storeSession(this);
195+
}
196+
197+
@Override
198+
public boolean isExpired() {
199+
return (isStarted() && !this.maxIdleTime.isNegative() &&
200+
Instant.now(getClock()).minus(this.maxIdleTime).isAfter(this.lastAccessTime));
201+
}
202+
}
203+
106204
}

0 commit comments

Comments
 (0)