Skip to content

Commit dff0e79

Browse files
committed
Merge pull request #1507 from rwinch/websessionmanager
2 parents dcdb0b4 + 2fc2dab commit dff0e79

File tree

9 files changed

+406
-489
lines changed

9 files changed

+406
-489
lines changed

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

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

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

Lines changed: 12 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,12 @@
1515
*/
1616
package org.springframework.web.server.session;
1717

18-
import java.time.Clock;
19-
import java.time.Instant;
20-
import java.time.ZoneId;
2118
import java.util.List;
2219

2320
import reactor.core.publisher.Flux;
2421
import reactor.core.publisher.Mono;
2522

2623
import org.springframework.util.Assert;
27-
import org.springframework.util.IdGenerator;
28-
import org.springframework.util.JdkIdGenerator;
2924
import org.springframework.web.server.ServerWebExchange;
3025
import org.springframework.web.server.WebSession;
3126

@@ -36,19 +31,15 @@
3631
* {@link WebSessionStore}
3732
*
3833
* @author Rossen Stoyanchev
34+
* @author Rob Winch
3935
* @since 5.0
4036
*/
4137
public class DefaultWebSessionManager implements WebSessionManager {
4238

43-
private static final IdGenerator idGenerator = new JdkIdGenerator();
44-
45-
4639
private WebSessionIdResolver sessionIdResolver = new CookieWebSessionIdResolver();
4740

4841
private WebSessionStore sessionStore = new InMemoryWebSessionStore();
4942

50-
private Clock clock = Clock.system(ZoneId.of("GMT"));
51-
5243

5344
/**
5445
* Configure the id resolution strategy.
@@ -84,89 +75,53 @@ public WebSessionStore getSessionStore() {
8475
return this.sessionStore;
8576
}
8677

87-
/**
88-
* Configure the {@link Clock} to use to set lastAccessTime on every created
89-
* session and to calculate if it is expired.
90-
* <p>This may be useful to align to different timezone or to set the clock
91-
* back in a test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))}
92-
* in order to simulate session expiration.
93-
* <p>By default this is {@code Clock.system(ZoneId.of("GMT"))}.
94-
* @param clock the clock to use
95-
*/
96-
public void setClock(Clock clock) {
97-
Assert.notNull(clock, "'clock' is required.");
98-
this.clock = clock;
99-
}
100-
101-
/**
102-
* Return the configured clock for session lastAccessTime calculations.
103-
*/
104-
public Clock getClock() {
105-
return this.clock;
106-
}
107-
10878

10979
@Override
11080
public Mono<WebSession> getSession(ServerWebExchange exchange) {
11181
return Mono.defer(() ->
11282
retrieveSession(exchange)
11383
.flatMap(session -> removeSessionIfExpired(exchange, session))
114-
.map(session -> {
115-
Instant lastAccessTime = Instant.now(getClock());
116-
return new DefaultWebSession(session, lastAccessTime, s -> saveSession(exchange, s));
117-
})
118-
.switchIfEmpty(createSession(exchange))
119-
.doOnNext(session -> exchange.getResponse().beforeCommit(session::save)));
84+
.flatMap(this.getSessionStore()::updateLastAccessTime)
85+
.switchIfEmpty(this.sessionStore.createWebSession())
86+
.doOnNext(session -> exchange.getResponse().beforeCommit(() -> save(exchange, session))));
12087
}
12188

122-
private Mono<DefaultWebSession> retrieveSession(ServerWebExchange exchange) {
89+
private Mono<WebSession> retrieveSession(ServerWebExchange exchange) {
12390
return Flux.fromIterable(getSessionIdResolver().resolveSessionIds(exchange))
12491
.concatMap(this.sessionStore::retrieveSession)
125-
.cast(DefaultWebSession.class)
12692
.next();
12793
}
12894

129-
private Mono<DefaultWebSession> removeSessionIfExpired(ServerWebExchange exchange, DefaultWebSession session) {
95+
private Mono<WebSession> removeSessionIfExpired(ServerWebExchange exchange, WebSession session) {
13096
if (session.isExpired()) {
13197
this.sessionIdResolver.expireSession(exchange);
13298
return this.sessionStore.removeSession(session.getId()).then(Mono.empty());
13399
}
134100
return Mono.just(session);
135101
}
136102

137-
private Mono<Void> saveSession(ServerWebExchange exchange, WebSession session) {
103+
private Mono<Void> save(ServerWebExchange exchange, WebSession session) {
138104
if (session.isExpired()) {
139105
return Mono.error(new IllegalStateException(
140106
"Sessions are checked for expiration and have their " +
141-
"lastAccessTime updated when first accessed during request processing. " +
142-
"However this session is expired meaning that maxIdleTime elapsed " +
143-
"before the call to session.save()."));
107+
"lastAccessTime updated when first accessed during request processing. " +
108+
"However this session is expired meaning that maxIdleTime elapsed " +
109+
"before the call to session.save()."));
144110
}
145111

146112
if (!session.isStarted()) {
147113
return Mono.empty();
148114
}
149115

150-
// Force explicit start
151-
session.start();
152-
153116
if (hasNewSessionId(exchange, session)) {
154-
this.sessionIdResolver.setSessionId(exchange, session.getId());
117+
DefaultWebSessionManager.this.sessionIdResolver.setSessionId(exchange, session.getId());
155118
}
156119

157-
return this.sessionStore.storeSession(session);
120+
return session.save();
158121
}
159122

160123
private boolean hasNewSessionId(ServerWebExchange exchange, WebSession session) {
161124
List<String> ids = getSessionIdResolver().resolveSessionIds(exchange);
162125
return ids.isEmpty() || !session.getId().equals(ids.get(0));
163126
}
164-
165-
private Mono<DefaultWebSession> createSession(ServerWebExchange exchange) {
166-
return Mono.fromSupplier(() ->
167-
new DefaultWebSession(idGenerator, getClock(),
168-
(oldId, session) -> this.sessionStore.changeSessionId(oldId, session),
169-
session -> saveSession(exchange, session)));
170-
}
171-
172127
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,23 @@
2626
* Request and response header-based {@link WebSessionIdResolver}.
2727
*
2828
* @author Greg Turnquist
29+
* @author Rob Winch
2930
* @since 5.0
3031
*/
3132
public class HeaderWebSessionIdResolver implements WebSessionIdResolver {
3233

33-
private String headerName = "SESSION";
34+
/** Default value for {@link #setHeaderName(String)}. */
35+
public static final String DEFAULT_HEADER_NAME = "SESSION";
36+
37+
38+
private String headerName = DEFAULT_HEADER_NAME;
3439

3540

3641
/**
3742
* Set the name of the session header to use for the session id.
3843
* The name is used to extract the session id from the request headers as
3944
* well to set the session id on the response headers.
40-
* <p>By default set to {@literal "SESSION"}.
45+
* <p>By default set to {@code DEFAULT_HEADER_NAME}
4146
* @param headerName the header name
4247
*/
4348
public void setHeaderName(String headerName) {
@@ -47,6 +52,7 @@ public void setHeaderName(String headerName) {
4752

4853
/**
4954
* Return the configured header name.
55+
* @return the configured header name
5056
*/
5157
public String getHeaderName() {
5258
return this.headerName;

0 commit comments

Comments
 (0)