16
16
package org .springframework .web .server .session ;
17
17
18
18
import java .time .Clock ;
19
+ import java .time .Duration ;
19
20
import java .time .Instant ;
20
21
import java .time .ZoneId ;
21
22
import java .util .Map ;
22
23
import java .util .concurrent .ConcurrentHashMap ;
24
+ import java .util .concurrent .atomic .AtomicReference ;
25
+
26
+ import reactor .core .publisher .Mono ;
23
27
24
28
import org .springframework .util .Assert ;
25
29
import org .springframework .util .IdGenerator ;
26
30
import org .springframework .util .JdkIdGenerator ;
27
- import reactor .core .publisher .Mono ;
28
-
29
31
import org .springframework .web .server .WebSession ;
30
32
31
33
/**
@@ -67,6 +69,11 @@ public Clock getClock() {
67
69
}
68
70
69
71
72
+ @ Override
73
+ public Mono <WebSession > createWebSession () {
74
+ return Mono .fromSupplier (InMemoryWebSession ::new );
75
+ }
76
+
70
77
@ Override
71
78
public Mono <WebSession > retrieveSession (String id ) {
72
79
return (this .sessions .containsKey (id ) ? Mono .just (this .sessions .get (id )) : Mono .empty ());
@@ -78,21 +85,16 @@ public Mono<Void> removeSession(String id) {
78
85
return Mono .empty ();
79
86
}
80
87
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
-
88
88
public Mono <WebSession > updateLastAccessTime (WebSession webSession ) {
89
89
return Mono .fromSupplier (() -> {
90
- DefaultWebSession session = (DefaultWebSession ) webSession ;
90
+ InMemoryWebSession session = (InMemoryWebSession ) webSession ;
91
91
Instant lastAccessTime = Instant .now (getClock ());
92
- return new DefaultWebSession (session , lastAccessTime );
92
+ return new InMemoryWebSession (session , lastAccessTime );
93
93
});
94
94
}
95
95
96
+ /* Private methods for InMemoryWebSession */
97
+
96
98
private Mono <Void > changeSessionId (String oldId , WebSession session ) {
97
99
this .sessions .remove (oldId );
98
100
this .sessions .put (session .getId (), session );
@@ -103,4 +105,100 @@ private Mono<Void> storeSession(WebSession session) {
103
105
this .sessions .put (session .getId (), session );
104
106
return Mono .empty ();
105
107
}
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
+
106
204
}
0 commit comments