Skip to content

Commit 849c05e

Browse files
committed
Extract RedisSessionMapper
1 parent 52f59a8 commit 849c05e

File tree

6 files changed

+298
-164
lines changed

6 files changed

+298
-164
lines changed

spring-session-data-redis/src/main/java/org/springframework/session/data/redis/ReactiveRedisOperationsSessionRepository.java

Lines changed: 11 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2018 the original author or authors.
2+
* Copyright 2014-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@
2121
import java.util.HashMap;
2222
import java.util.Map;
2323
import java.util.Set;
24-
import java.util.function.Function;
2524

2625
import org.reactivestreams.Publisher;
2726
import reactor.core.publisher.Mono;
@@ -47,29 +46,6 @@ public class ReactiveRedisOperationsSessionRepository implements
4746
*/
4847
public static final String DEFAULT_NAMESPACE = "spring:session";
4948

50-
/**
51-
* The key in the Hash representing {@link Session#getCreationTime()}.
52-
*/
53-
static final String CREATION_TIME_KEY = "creationTime";
54-
55-
/**
56-
* The key in the Hash representing {@link Session#getLastAccessedTime()}.
57-
*/
58-
static final String LAST_ACCESSED_TIME_KEY = "lastAccessedTime";
59-
60-
/**
61-
* The key in the Hash representing {@link Session#getMaxInactiveInterval()} .
62-
*/
63-
static final String MAX_INACTIVE_INTERVAL_KEY = "maxInactiveInterval";
64-
65-
/**
66-
* The prefix of the key used for session attributes. The suffix is the name of
67-
* the session attribute. For example, if the session contained an attribute named
68-
* attributeName, then there would be an entry in the hash named
69-
* sessionAttr:attributeName that mapped to its value.
70-
*/
71-
static final String ATTRIBUTE_PREFIX = "sessionAttr:";
72-
7349
private final ReactiveRedisOperations<String, Object> sessionRedisOperations;
7450

7551
/**
@@ -171,7 +147,7 @@ public Mono<RedisSession> findById(String id) {
171147
return this.sessionRedisOperations.opsForHash().entries(sessionKey)
172148
.collectMap((e) -> e.getKey().toString(), Map.Entry::getValue)
173149
.filter((map) -> !map.isEmpty())
174-
.map(new SessionMapper(id))
150+
.map(new RedisSessionMapper(id))
175151
.filter((session) -> !session.isExpired())
176152
.map(RedisSession::new)
177153
.switchIfEmpty(Mono.defer(() -> deleteById(id).then(Mono.empty())));
@@ -186,7 +162,7 @@ public Mono<Void> deleteById(String id) {
186162
}
187163

188164
private static String getAttributeKey(String attributeName) {
189-
return ATTRIBUTE_PREFIX + attributeName;
165+
return RedisSessionMapper.ATTRIBUTE_PREFIX + attributeName;
190166
}
191167

192168
private String getSessionKey(String sessionId) {
@@ -215,10 +191,12 @@ final class RedisSession implements Session {
215191
*/
216192
RedisSession() {
217193
this(new MapSession());
218-
this.delta.put(CREATION_TIME_KEY, getCreationTime().toEpochMilli());
219-
this.delta.put(MAX_INACTIVE_INTERVAL_KEY,
194+
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY,
195+
getCreationTime().toEpochMilli());
196+
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
220197
(int) getMaxInactiveInterval().getSeconds());
221-
this.delta.put(LAST_ACCESSED_TIME_KEY, getLastAccessedTime().toEpochMilli());
198+
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
199+
getLastAccessedTime().toEpochMilli());
222200
this.isNew = true;
223201
this.flushImmediateIfNecessary();
224202
}
@@ -275,7 +253,8 @@ public Instant getCreationTime() {
275253
@Override
276254
public void setLastAccessedTime(Instant lastAccessedTime) {
277255
this.cached.setLastAccessedTime(lastAccessedTime);
278-
putAndFlush(LAST_ACCESSED_TIME_KEY, getLastAccessedTime().toEpochMilli());
256+
putAndFlush(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
257+
getLastAccessedTime().toEpochMilli());
279258
}
280259

281260
@Override
@@ -286,7 +265,7 @@ public Instant getLastAccessedTime() {
286265
@Override
287266
public void setMaxInactiveInterval(Duration interval) {
288267
this.cached.setMaxInactiveInterval(interval);
289-
putAndFlush(MAX_INACTIVE_INTERVAL_KEY,
268+
putAndFlush(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
290269
(int) getMaxInactiveInterval().getSeconds());
291270
}
292271

@@ -358,36 +337,4 @@ private Mono<Void> saveChangeSessionId() {
358337

359338
}
360339

361-
private static final class SessionMapper
362-
implements Function<Map<String, Object>, MapSession> {
363-
364-
private final String id;
365-
366-
private SessionMapper(String id) {
367-
this.id = id;
368-
}
369-
370-
@Override
371-
public MapSession apply(Map<String, Object> map) {
372-
MapSession session = new MapSession(this.id);
373-
374-
session.setCreationTime(
375-
Instant.ofEpochMilli((long) map.get(CREATION_TIME_KEY)));
376-
session.setLastAccessedTime(
377-
Instant.ofEpochMilli((long) map.get(LAST_ACCESSED_TIME_KEY)));
378-
session.setMaxInactiveInterval(
379-
Duration.ofSeconds((int) map.get(MAX_INACTIVE_INTERVAL_KEY)));
380-
381-
map.forEach((name, value) -> {
382-
if (name.startsWith(ATTRIBUTE_PREFIX)) {
383-
session.setAttribute(name.substring(ATTRIBUTE_PREFIX.length()),
384-
value);
385-
}
386-
});
387-
388-
return session;
389-
}
390-
391-
}
392-
393340
}

spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -264,33 +264,6 @@ public class RedisOperationsSessionRepository implements
264264
*/
265265
public static final String DEFAULT_NAMESPACE = "spring:session";
266266

267-
/**
268-
* The key in the Hash representing
269-
* {@link org.springframework.session.Session#getCreationTime()}.
270-
*/
271-
static final String CREATION_TIME_ATTR = "creationTime";
272-
273-
/**
274-
* The key in the Hash representing
275-
* {@link org.springframework.session.Session#getMaxInactiveInterval()}
276-
* .
277-
*/
278-
static final String MAX_INACTIVE_ATTR = "maxInactiveInterval";
279-
280-
/**
281-
* The key in the Hash representing
282-
* {@link org.springframework.session.Session#getLastAccessedTime()}.
283-
*/
284-
static final String LAST_ACCESSED_ATTR = "lastAccessedTime";
285-
286-
/**
287-
* The prefix of the key used for session attributes. The suffix is the name of
288-
* the session attribute. For example, if the session contained an attribute named
289-
* attributeName, then there would be an entry in the hash named
290-
* sessionAttr:attributeName that mapped to its value.
291-
*/
292-
static final String SESSION_ATTR_PREFIX = "sessionAttr:";
293-
294267
private int database = RedisOperationsSessionRepository.DEFAULT_DATABASE;
295268

296269
/**
@@ -480,17 +453,18 @@ private MapSession loadSession(String id, Map<Object, Object> entries) {
480453
MapSession loaded = new MapSession(id);
481454
for (Map.Entry<Object, Object> entry : entries.entrySet()) {
482455
String key = (String) entry.getKey();
483-
if (CREATION_TIME_ATTR.equals(key)) {
456+
if (RedisSessionMapper.CREATION_TIME_KEY.equals(key)) {
484457
loaded.setCreationTime(Instant.ofEpochMilli((long) entry.getValue()));
485458
}
486-
else if (MAX_INACTIVE_ATTR.equals(key)) {
459+
else if (RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY.equals(key)) {
487460
loaded.setMaxInactiveInterval(Duration.ofSeconds((int) entry.getValue()));
488461
}
489-
else if (LAST_ACCESSED_ATTR.equals(key)) {
462+
else if (RedisSessionMapper.LAST_ACCESSED_TIME_KEY.equals(key)) {
490463
loaded.setLastAccessedTime(Instant.ofEpochMilli((long) entry.getValue()));
491464
}
492-
else if (key.startsWith(SESSION_ATTR_PREFIX)) {
493-
loaded.setAttribute(key.substring(SESSION_ATTR_PREFIX.length()),
465+
else if (key.startsWith(RedisSessionMapper.ATTRIBUTE_PREFIX)) {
466+
loaded.setAttribute(
467+
key.substring(RedisSessionMapper.ATTRIBUTE_PREFIX.length()),
494468
entry.getValue());
495469
}
496470
}
@@ -689,7 +663,7 @@ private BoundHashOperations<Object, Object, Object> getSessionBoundHashOperation
689663
* @return the attribute key name
690664
*/
691665
static String getSessionAttrNameKey(String attributeName) {
692-
return SESSION_ATTR_PREFIX + attributeName;
666+
return RedisSessionMapper.ATTRIBUTE_PREFIX + attributeName;
693667
}
694668

695669
/**
@@ -719,9 +693,12 @@ final class RedisSession implements Session {
719693
RedisSession(Duration maxInactiveInterval) {
720694
this(new MapSession());
721695
this.cached.setMaxInactiveInterval(maxInactiveInterval);
722-
this.delta.put(CREATION_TIME_ATTR, getCreationTime().toEpochMilli());
723-
this.delta.put(MAX_INACTIVE_ATTR, (int) getMaxInactiveInterval().getSeconds());
724-
this.delta.put(LAST_ACCESSED_ATTR, getLastAccessedTime().toEpochMilli());
696+
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY,
697+
getCreationTime().toEpochMilli());
698+
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
699+
(int) getMaxInactiveInterval().getSeconds());
700+
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
701+
getLastAccessedTime().toEpochMilli());
725702
this.isNew = true;
726703
}
727704

@@ -745,7 +722,8 @@ public void setNew(boolean isNew) {
745722
@Override
746723
public void setLastAccessedTime(Instant lastAccessedTime) {
747724
this.cached.setLastAccessedTime(lastAccessedTime);
748-
this.putAndFlush(LAST_ACCESSED_ATTR, getLastAccessedTime().toEpochMilli());
725+
this.putAndFlush(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
726+
getLastAccessedTime().toEpochMilli());
749727
}
750728

751729
@Override
@@ -780,7 +758,8 @@ public Instant getLastAccessedTime() {
780758
@Override
781759
public void setMaxInactiveInterval(Duration interval) {
782760
this.cached.setMaxInactiveInterval(interval);
783-
this.putAndFlush(MAX_INACTIVE_ATTR, (int) getMaxInactiveInterval().getSeconds());
761+
this.putAndFlush(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
762+
(int) getMaxInactiveInterval().getSeconds());
784763
}
785764

786765
@Override
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2014-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.session.data.redis;
18+
19+
import java.time.Duration;
20+
import java.time.Instant;
21+
import java.util.Map;
22+
import java.util.function.Function;
23+
24+
import org.springframework.session.MapSession;
25+
import org.springframework.session.Session;
26+
import org.springframework.util.Assert;
27+
28+
/**
29+
* A {@link Function} that converts a {@link Map} representing Redis hash to a
30+
* {@link MapSession}.
31+
*
32+
* @author Vedran Pavic
33+
* @since 2.2.0
34+
*/
35+
final class RedisSessionMapper implements Function<Map<String, Object>, MapSession> {
36+
37+
/**
38+
* The key in the hash representing {@link Session#getCreationTime()}.
39+
*/
40+
static final String CREATION_TIME_KEY = "creationTime";
41+
42+
/**
43+
* The key in the hash representing {@link Session#getLastAccessedTime()}.
44+
*/
45+
static final String LAST_ACCESSED_TIME_KEY = "lastAccessedTime";
46+
47+
/**
48+
* The key in the hash representing {@link Session#getMaxInactiveInterval()}.
49+
*/
50+
static final String MAX_INACTIVE_INTERVAL_KEY = "maxInactiveInterval";
51+
52+
/**
53+
* The prefix of the key in the hash used for session attributes. For example, if the
54+
* session contained an attribute named {@code attributeName}, then there would be an
55+
* entry in the hash named {@code sessionAttr:attributeName} that mapped to its value.
56+
*/
57+
static final String ATTRIBUTE_PREFIX = "sessionAttr:";
58+
59+
private final String sessionId;
60+
61+
RedisSessionMapper(String sessionId) {
62+
Assert.hasText(sessionId, "sessionId must not be empty");
63+
this.sessionId = sessionId;
64+
}
65+
66+
@Override
67+
public MapSession apply(Map<String, Object> map) {
68+
Assert.notEmpty(map, "map must not be empty");
69+
MapSession session = new MapSession(this.sessionId);
70+
Long creationTime = (Long) map.get(CREATION_TIME_KEY);
71+
if (creationTime == null) {
72+
handleMissingKey(CREATION_TIME_KEY);
73+
}
74+
session.setCreationTime(Instant.ofEpochMilli(creationTime));
75+
Long lastAccessedTime = (Long) map.get(LAST_ACCESSED_TIME_KEY);
76+
if (lastAccessedTime == null) {
77+
handleMissingKey(LAST_ACCESSED_TIME_KEY);
78+
}
79+
session.setLastAccessedTime(Instant.ofEpochMilli(lastAccessedTime));
80+
Integer maxInactiveInterval = (Integer) map.get(MAX_INACTIVE_INTERVAL_KEY);
81+
if (maxInactiveInterval == null) {
82+
handleMissingKey(MAX_INACTIVE_INTERVAL_KEY);
83+
}
84+
session.setMaxInactiveInterval(Duration.ofSeconds(maxInactiveInterval));
85+
map.forEach((name, value) -> {
86+
if (name.startsWith(ATTRIBUTE_PREFIX)) {
87+
session.setAttribute(name.substring(ATTRIBUTE_PREFIX.length()), value);
88+
}
89+
});
90+
return session;
91+
}
92+
93+
private static void handleMissingKey(String key) {
94+
throw new IllegalStateException(key + " key must not be null");
95+
}
96+
97+
}

0 commit comments

Comments
 (0)