Session
类继承图

Session

ValidatingSession

SimpleSession
SimpleSession 将Attribute 保存在 map对象中
1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one |
3 | * or more contributor license agreements. See the NOTICE file |
4 | * distributed with this work for additional information |
5 | * regarding copyright ownership. The ASF licenses this file |
6 | * to you under the Apache License, Version 2.0 (the |
7 | * "License"); you may not use this file except in compliance |
8 | * with the License. You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, |
13 | * software distributed under the License is distributed on an |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | * KIND, either express or implied. See the License for the |
16 | * specific language governing permissions and limitations |
17 | * under the License. |
18 | */ |
19 | package org.apache.shiro.session.mgt; |
20 | |
21 | import org.apache.shiro.session.ExpiredSessionException; |
22 | import org.apache.shiro.session.InvalidSessionException; |
23 | import org.apache.shiro.session.StoppedSessionException; |
24 | import org.apache.shiro.util.CollectionUtils; |
25 | import org.slf4j.Logger; |
26 | import org.slf4j.LoggerFactory; |
27 | |
28 | import java.io.IOException; |
29 | import java.io.ObjectInputStream; |
30 | import java.io.ObjectOutputStream; |
31 | import java.io.Serializable; |
32 | import java.text.DateFormat; |
33 | import java.util.*; |
34 | |
35 | |
36 | /** |
37 | * Simple {@link org.apache.shiro.session.Session} JavaBeans-compatible POJO implementation, intended to be used on the |
38 | * business/server tier. |
39 | * |
40 | * @since 0.1 |
41 | */ |
42 | public class SimpleSession implements ValidatingSession, Serializable { |
43 | |
44 | // Serialization reminder: |
45 | // You _MUST_ change this number if you introduce a change to this class |
46 | // that is NOT serialization backwards compatible. Serialization-compatible |
47 | // changes do not require a change to this number. If you need to generate |
48 | // a new number in this case, use the JDK's 'serialver' program to generate it. |
49 | private static final long serialVersionUID = -7125642695178165650L; |
50 | |
51 | //TODO - complete JavaDoc |
52 | private transient static final Logger log = LoggerFactory.getLogger(SimpleSession.class); |
53 | |
54 | protected static final long MILLIS_PER_SECOND = 1000; |
55 | protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND; |
56 | protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE; |
57 | |
58 | //serialization bitmask fields. DO NOT CHANGE THE ORDER THEY ARE DECLARED! |
59 | static int bitIndexCounter = 0; |
60 | private static final int ID_BIT_MASK = 1 << bitIndexCounter++; |
61 | private static final int START_TIMESTAMP_BIT_MASK = 1 << bitIndexCounter++; |
62 | private static final int STOP_TIMESTAMP_BIT_MASK = 1 << bitIndexCounter++; |
63 | private static final int LAST_ACCESS_TIME_BIT_MASK = 1 << bitIndexCounter++; |
64 | private static final int TIMEOUT_BIT_MASK = 1 << bitIndexCounter++; |
65 | private static final int EXPIRED_BIT_MASK = 1 << bitIndexCounter++; |
66 | private static final int HOST_BIT_MASK = 1 << bitIndexCounter++; |
67 | private static final int ATTRIBUTES_BIT_MASK = 1 << bitIndexCounter++; |
68 | |
69 | // ============================================================== |
70 | // NOTICE: |
71 | // |
72 | // The following fields are marked as transient to avoid double-serialization. |
73 | // They are in fact serialized (even though 'transient' usually indicates otherwise), |
74 | // but they are serialized explicitly via the writeObject and readObject implementations |
75 | // in this class. |
76 | // |
77 | // If we didn't declare them as transient, the out.defaultWriteObject(); call in writeObject would |
78 | // serialize all non-transient fields as well, effectively doubly serializing the fields (also |
79 | // doubling the serialization size). |
80 | // |
81 | // This finding, with discussion, was covered here: |
82 | // |
83 | // http://mail-archives.apache.org/mod_mbox/shiro-user/201109.mbox/%3C4E81BCBD.8060909@metaphysis.net%3E |
84 | // |
85 | // ============================================================== |
86 | private transient Serializable id; |
87 | private transient Date startTimestamp; |
88 | private transient Date stopTimestamp; |
89 | private transient Date lastAccessTime; |
90 | private transient long timeout; |
91 | private transient boolean expired; |
92 | private transient String host; |
93 | private transient Map<Object, Object> attributes; |
94 | |
95 | public SimpleSession() { |
96 | this.timeout = DefaultSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT; //TODO - remove concrete reference to DefaultSessionManager |
97 | this.startTimestamp = new Date(); |
98 | this.lastAccessTime = this.startTimestamp; |
99 | } |
100 | |
101 | public SimpleSession(String host) { |
102 | this(); |
103 | this.host = host; |
104 | } |
105 | |
106 | ...... |
107 | // getter setter |
108 | |
109 | public void touch() { |
110 | this.lastAccessTime = new Date(); |
111 | } |
112 | |
113 | public void stop() { |
114 | if (this.stopTimestamp == null) { |
115 | this.stopTimestamp = new Date(); |
116 | } |
117 | } |
118 | |
119 | protected boolean isStopped() { |
120 | return getStopTimestamp() != null; |
121 | } |
122 | |
123 | protected void expire() { |
124 | stop(); |
125 | this.expired = true; |
126 | } |
127 | |
128 | /** |
129 | * @since 0.9 |
130 | */ |
131 | public boolean isValid() { |
132 | return !isStopped() && !isExpired(); |
133 | } |
134 | |
135 | /** |
136 | * Determines if this session is expired. |
137 | * |
138 | * @return true if the specified session has expired, false otherwise. |
139 | */ |
140 | protected boolean isTimedOut() { |
141 | |
142 | if (isExpired()) { |
143 | return true; |
144 | } |
145 | |
146 | long timeout = getTimeout(); |
147 | |
148 | if (timeout >= 0l) { |
149 | |
150 | Date lastAccessTime = getLastAccessTime(); |
151 | |
152 | if (lastAccessTime == null) { |
153 | String msg = "session.lastAccessTime for session with id [" + |
154 | getId() + "] is null. This value must be set at " + |
155 | "least once, preferably at least upon instantiation. Please check the " + |
156 | getClass().getName() + " implementation and ensure " + |
157 | "this value will be set (perhaps in the constructor?)"; |
158 | throw new IllegalStateException(msg); |
159 | } |
160 | |
161 | // Calculate at what time a session would have been last accessed |
162 | // for it to be expired at this point. In other words, subtract |
163 | // from the current time the amount of time that a session can |
164 | // be inactive before expiring. If the session was last accessed |
165 | // before this time, it is expired. |
166 | long expireTimeMillis = System.currentTimeMillis() - timeout; |
167 | Date expireTime = new Date(expireTimeMillis); |
168 | return lastAccessTime.before(expireTime); |
169 | } else { |
170 | if (log.isTraceEnabled()) { |
171 | log.trace("No timeout for session with id [" + getId() + |
172 | "]. Session is not considered expired."); |
173 | } |
174 | } |
175 | |
176 | return false; |
177 | } |
178 | |
179 | public void validate() throws InvalidSessionException { |
180 | //check for stopped: |
181 | if (isStopped()) { |
182 | //timestamp is set, so the session is considered stopped: |
183 | String msg = "Session with id [" + getId() + "] has been " + |
184 | "explicitly stopped. No further interaction under this session is " + |
185 | "allowed."; |
186 | throw new StoppedSessionException(msg); |
187 | } |
188 | |
189 | //check for expiration |
190 | if (isTimedOut()) { |
191 | expire(); |
192 | |
193 | //throw an exception explaining details of why it expired: |
194 | Date lastAccessTime = getLastAccessTime(); |
195 | long timeout = getTimeout(); |
196 | |
197 | Serializable sessionId = getId(); |
198 | |
199 | DateFormat df = DateFormat.getInstance(); |
200 | String msg = "Session with id [" + sessionId + "] has expired. " + |
201 | "Last access time: " + df.format(lastAccessTime) + |
202 | ". Current time: " + df.format(new Date()) + |
203 | ". Session timeout is set to " + timeout / MILLIS_PER_SECOND + " seconds (" + |
204 | timeout / MILLIS_PER_MINUTE + " minutes)"; |
205 | if (log.isTraceEnabled()) { |
206 | log.trace(msg); |
207 | } |
208 | throw new ExpiredSessionException(msg); |
209 | } |
210 | } |
211 | |
212 | private Map<Object, Object> getAttributesLazy() { |
213 | Map<Object, Object> attributes = getAttributes(); |
214 | if (attributes == null) { |
215 | attributes = new HashMap<Object, Object>(); |
216 | setAttributes(attributes); |
217 | } |
218 | return attributes; |
219 | } |
220 | |
221 | public Collection<Object> getAttributeKeys() throws InvalidSessionException { |
222 | Map<Object, Object> attributes = getAttributes(); |
223 | if (attributes == null) { |
224 | return Collections.emptySet(); |
225 | } |
226 | return attributes.keySet(); |
227 | } |
228 | |
229 | public Object getAttribute(Object key) { |
230 | Map<Object, Object> attributes = getAttributes(); |
231 | if (attributes == null) { |
232 | return null; |
233 | } |
234 | return attributes.get(key); |
235 | } |
236 | |
237 | public void setAttribute(Object key, Object value) { |
238 | if (value == null) { |
239 | removeAttribute(key); |
240 | } else { |
241 | getAttributesLazy().put(key, value); |
242 | } |
243 | } |
244 | |
245 | public Object removeAttribute(Object key) { |
246 | Map<Object, Object> attributes = getAttributes(); |
247 | if (attributes == null) { |
248 | return null; |
249 | } else { |
250 | return attributes.remove(key); |
251 | } |
252 | } |
253 | |
254 | /** |
255 | * Returns {@code true} if the specified argument is an {@code instanceof} {@code SimpleSession} and both |
256 | * {@link #getId() id}s are equal. If the argument is a {@code SimpleSession} and either 'this' or the argument |
257 | * does not yet have an ID assigned, the value of {@link #onEquals(SimpleSession) onEquals} is returned, which |
258 | * does a necessary attribute-based comparison when IDs are not available. |
259 | * <p/> |
260 | * Do your best to ensure {@code SimpleSession} instances receive an ID very early in their lifecycle to |
261 | * avoid the more expensive attributes-based comparison. |
262 | * |
263 | * @param obj the object to compare with this one for equality. |
264 | * @return {@code true} if this object is equivalent to the specified argument, {@code false} otherwise. |
265 | */ |
266 | |
267 | public boolean equals(Object obj) { |
268 | if (this == obj) { |
269 | return true; |
270 | } |
271 | if (obj instanceof SimpleSession) { |
272 | SimpleSession other = (SimpleSession) obj; |
273 | Serializable thisId = getId(); |
274 | Serializable otherId = other.getId(); |
275 | if (thisId != null && otherId != null) { |
276 | return thisId.equals(otherId); |
277 | } else { |
278 | //fall back to an attribute based comparison: |
279 | return onEquals(other); |
280 | } |
281 | } |
282 | return false; |
283 | } |
284 | |
285 | /** |
286 | * Provides an attribute-based comparison (no ID comparison) - incurred <em>only</em> when 'this' or the |
287 | * session object being compared for equality do not have a session id. |
288 | * |
289 | * @param ss the SimpleSession instance to compare for equality. |
290 | * @return true if all the attributes, except the id, are equal to this object's attributes. |
291 | * @since 1.0 |
292 | */ |
293 | protected boolean onEquals(SimpleSession ss) { |
294 | return (getStartTimestamp() != null ? getStartTimestamp().equals(ss.getStartTimestamp()) : ss.getStartTimestamp() == null) && |
295 | (getStopTimestamp() != null ? getStopTimestamp().equals(ss.getStopTimestamp()) : ss.getStopTimestamp() == null) && |
296 | (getLastAccessTime() != null ? getLastAccessTime().equals(ss.getLastAccessTime()) : ss.getLastAccessTime() == null) && |
297 | (getTimeout() == ss.getTimeout()) && |
298 | (isExpired() == ss.isExpired()) && |
299 | (getHost() != null ? getHost().equals(ss.getHost()) : ss.getHost() == null) && |
300 | (getAttributes() != null ? getAttributes().equals(ss.getAttributes()) : ss.getAttributes() == null); |
301 | } |
302 | |
303 | /** |
304 | * Returns the hashCode. If the {@link #getId() id} is not {@code null}, its hashcode is returned immediately. |
305 | * If it is {@code null}, an attributes-based hashCode will be calculated and returned. |
306 | * <p/> |
307 | * Do your best to ensure {@code SimpleSession} instances receive an ID very early in their lifecycle to |
308 | * avoid the more expensive attributes-based calculation. |
309 | * |
310 | * @return this object's hashCode |
311 | * @since 1.0 |
312 | */ |
313 | |
314 | public int hashCode() { |
315 | Serializable id = getId(); |
316 | if (id != null) { |
317 | return id.hashCode(); |
318 | } |
319 | int hashCode = getStartTimestamp() != null ? getStartTimestamp().hashCode() : 0; |
320 | hashCode = 31 * hashCode + (getStopTimestamp() != null ? getStopTimestamp().hashCode() : 0); |
321 | hashCode = 31 * hashCode + (getLastAccessTime() != null ? getLastAccessTime().hashCode() : 0); |
322 | hashCode = 31 * hashCode + Long.valueOf(Math.max(getTimeout(), 0)).hashCode(); |
323 | hashCode = 31 * hashCode + Boolean.valueOf(isExpired()).hashCode(); |
324 | hashCode = 31 * hashCode + (getHost() != null ? getHost().hashCode() : 0); |
325 | hashCode = 31 * hashCode + (getAttributes() != null ? getAttributes().hashCode() : 0); |
326 | return hashCode; |
327 | } |
328 | |
329 | /** |
330 | * Returns the string representation of this SimpleSession, equal to |
331 | * <code>getClass().getName() + ",id=" + getId()</code>. |
332 | * |
333 | * @return the string representation of this SimpleSession, equal to |
334 | * <code>getClass().getName() + ",id=" + getId()</code>. |
335 | * @since 1.0 |
336 | */ |
337 | |
338 | public String toString() { |
339 | StringBuilder sb = new StringBuilder(); |
340 | sb.append(getClass().getName()).append(",id=").append(getId()); |
341 | return sb.toString(); |
342 | } |
343 | |
344 | /** |
345 | * Serializes this object to the specified output stream for JDK Serialization. |
346 | * |
347 | * @param out output stream used for Object serialization. |
348 | * @throws IOException if any of this object's fields cannot be written to the stream. |
349 | * @since 1.0 |
350 | */ |
351 | private void writeObject(ObjectOutputStream out) throws IOException { |
352 | out.defaultWriteObject(); |
353 | short alteredFieldsBitMask = getAlteredFieldsBitMask(); |
354 | out.writeShort(alteredFieldsBitMask); |
355 | if (id != null) { |
356 | out.writeObject(id); |
357 | } |
358 | if (startTimestamp != null) { |
359 | out.writeObject(startTimestamp); |
360 | } |
361 | if (stopTimestamp != null) { |
362 | out.writeObject(stopTimestamp); |
363 | } |
364 | if (lastAccessTime != null) { |
365 | out.writeObject(lastAccessTime); |
366 | } |
367 | if (timeout != 0l) { |
368 | out.writeLong(timeout); |
369 | } |
370 | if (expired) { |
371 | out.writeBoolean(expired); |
372 | } |
373 | if (host != null) { |
374 | out.writeUTF(host); |
375 | } |
376 | if (!CollectionUtils.isEmpty(attributes)) { |
377 | out.writeObject(attributes); |
378 | } |
379 | } |
380 | |
381 | /** |
382 | * Reconstitutes this object based on the specified InputStream for JDK Serialization. |
383 | * |
384 | * @param in the input stream to use for reading data to populate this object. |
385 | * @throws IOException if the input stream cannot be used. |
386 | * @throws ClassNotFoundException if a required class needed for instantiation is not available in the present JVM |
387 | * @since 1.0 |
388 | */ |
389 | ({"unchecked"}) |
390 | private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
391 | in.defaultReadObject(); |
392 | short bitMask = in.readShort(); |
393 | |
394 | if (isFieldPresent(bitMask, ID_BIT_MASK)) { |
395 | this.id = (Serializable) in.readObject(); |
396 | } |
397 | if (isFieldPresent(bitMask, START_TIMESTAMP_BIT_MASK)) { |
398 | this.startTimestamp = (Date) in.readObject(); |
399 | } |
400 | if (isFieldPresent(bitMask, STOP_TIMESTAMP_BIT_MASK)) { |
401 | this.stopTimestamp = (Date) in.readObject(); |
402 | } |
403 | if (isFieldPresent(bitMask, LAST_ACCESS_TIME_BIT_MASK)) { |
404 | this.lastAccessTime = (Date) in.readObject(); |
405 | } |
406 | if (isFieldPresent(bitMask, TIMEOUT_BIT_MASK)) { |
407 | this.timeout = in.readLong(); |
408 | } |
409 | if (isFieldPresent(bitMask, EXPIRED_BIT_MASK)) { |
410 | this.expired = in.readBoolean(); |
411 | } |
412 | if (isFieldPresent(bitMask, HOST_BIT_MASK)) { |
413 | this.host = in.readUTF(); |
414 | } |
415 | if (isFieldPresent(bitMask, ATTRIBUTES_BIT_MASK)) { |
416 | this.attributes = (Map<Object, Object>) in.readObject(); |
417 | } |
418 | } |
419 | |
420 | /** |
421 | * Returns a bit mask used during serialization indicating which fields have been serialized. Fields that have been |
422 | * altered (not null and/or not retaining the class defaults) will be serialized and have 1 in their respective |
423 | * index, fields that are null and/or retain class default values have 0. |
424 | * |
425 | * @return a bit mask used during serialization indicating which fields have been serialized. |
426 | * @since 1.0 |
427 | */ |
428 | private short getAlteredFieldsBitMask() { |
429 | int bitMask = 0; |
430 | bitMask = id != null ? bitMask | ID_BIT_MASK : bitMask; |
431 | bitMask = startTimestamp != null ? bitMask | START_TIMESTAMP_BIT_MASK : bitMask; |
432 | bitMask = stopTimestamp != null ? bitMask | STOP_TIMESTAMP_BIT_MASK : bitMask; |
433 | bitMask = lastAccessTime != null ? bitMask | LAST_ACCESS_TIME_BIT_MASK : bitMask; |
434 | bitMask = timeout != 0l ? bitMask | TIMEOUT_BIT_MASK : bitMask; |
435 | bitMask = expired ? bitMask | EXPIRED_BIT_MASK : bitMask; |
436 | bitMask = host != null ? bitMask | HOST_BIT_MASK : bitMask; |
437 | bitMask = !CollectionUtils.isEmpty(attributes) ? bitMask | ATTRIBUTES_BIT_MASK : bitMask; |
438 | return (short) bitMask; |
439 | } |
440 | |
441 | /** |
442 | * Returns {@code true} if the given {@code bitMask} argument indicates that the specified field has been |
443 | * serialized and therefore should be read during deserialization, {@code false} otherwise. |
444 | * |
445 | * @param bitMask the aggregate bitmask for all fields that have been serialized. Individual bits represent |
446 | * the fields that have been serialized. A bit set to 1 means that corresponding field has |
447 | * been serialized, 0 means it hasn't been serialized. |
448 | * @param fieldBitMask the field bit mask constant identifying which bit to inspect (corresponds to a class attribute). |
449 | * @return {@code true} if the given {@code bitMask} argument indicates that the specified field has been |
450 | * serialized and therefore should be read during deserialization, {@code false} otherwise. |
451 | * @since 1.0 |
452 | */ |
453 | private static boolean isFieldPresent(short bitMask, int fieldBitMask) { |
454 | return (bitMask & fieldBitMask) != 0; |
455 | } |
456 | |
457 | } |
DelegatingSession
1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one |
3 | * or more contributor license agreements. See the NOTICE file |
4 | * distributed with this work for additional information |
5 | * regarding copyright ownership. The ASF licenses this file |
6 | * to you under the Apache License, Version 2.0 (the |
7 | * "License"); you may not use this file except in compliance |
8 | * with the License. You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, |
13 | * software distributed under the License is distributed on an |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | * KIND, either express or implied. See the License for the |
16 | * specific language governing permissions and limitations |
17 | * under the License. |
18 | */ |
19 | package org.apache.shiro.session.mgt; |
20 | |
21 | import org.apache.shiro.session.InvalidSessionException; |
22 | import org.apache.shiro.session.Session; |
23 | |
24 | import java.io.Serializable; |
25 | import java.util.Collection; |
26 | import java.util.Date; |
27 | |
28 | /** |
29 | * A DelegatingSession is a client-tier representation of a server side |
30 | * {@link org.apache.shiro.session.Session Session}. |
31 | * This implementation is basically a proxy to a server-side {@link NativeSessionManager NativeSessionManager}, |
32 | * which will return the proper results for each method call. |
33 | * <p/> |
34 | * <p>A <tt>DelegatingSession</tt> will cache data when appropriate to avoid a remote method invocation, |
35 | * only communicating with the server when necessary. |
36 | * <p/> |
37 | * <p>Of course, if used in-process with a NativeSessionManager business POJO, as might be the case in a |
38 | * web-based application where the web classes and server-side business pojos exist in the same |
39 | * JVM, a remote method call will not be incurred. |
40 | * |
41 | * @since 0.1 |
42 | */ |
43 | public class DelegatingSession implements Session, Serializable { |
44 | |
45 | //TODO - complete JavaDoc |
46 | |
47 | private final SessionKey key; |
48 | |
49 | //cached fields to avoid a server-side method call if out-of-process: |
50 | private Date startTimestamp = null; |
51 | private String host = null; |
52 | |
53 | /** |
54 | * Handle to the target NativeSessionManager that will support the delegate calls. |
55 | */ |
56 | private final transient NativeSessionManager sessionManager; |
57 | |
58 | |
59 | public DelegatingSession(NativeSessionManager sessionManager, SessionKey key) { |
60 | if (sessionManager == null) { |
61 | throw new IllegalArgumentException("sessionManager argument cannot be null."); |
62 | } |
63 | if (key == null) { |
64 | throw new IllegalArgumentException("sessionKey argument cannot be null."); |
65 | } |
66 | if (key.getSessionId() == null) { |
67 | String msg = "The " + DelegatingSession.class.getName() + " implementation requires that the " + |
68 | "SessionKey argument returns a non-null sessionId to support the " + |
69 | "Session.getId() invocations."; |
70 | throw new IllegalArgumentException(msg); |
71 | } |
72 | this.sessionManager = sessionManager; |
73 | this.key = key; |
74 | } |
75 | |
76 | /** |
77 | * @see org.apache.shiro.session.Session#getId() |
78 | */ |
79 | public Serializable getId() { |
80 | return key.getSessionId(); |
81 | } |
82 | |
83 | /** |
84 | * @see org.apache.shiro.session.Session#getStartTimestamp() |
85 | */ |
86 | public Date getStartTimestamp() { |
87 | if (startTimestamp == null) { |
88 | startTimestamp = sessionManager.getStartTimestamp(key); |
89 | } |
90 | return startTimestamp; |
91 | } |
92 | |
93 | /** |
94 | * @see org.apache.shiro.session.Session#getLastAccessTime() |
95 | */ |
96 | public Date getLastAccessTime() { |
97 | //can't cache - only business pojo knows the accurate time: |
98 | return sessionManager.getLastAccessTime(key); |
99 | } |
100 | |
101 | public long getTimeout() throws InvalidSessionException { |
102 | return sessionManager.getTimeout(key); |
103 | } |
104 | |
105 | public void setTimeout(long maxIdleTimeInMillis) throws InvalidSessionException { |
106 | sessionManager.setTimeout(key, maxIdleTimeInMillis); |
107 | } |
108 | |
109 | public String getHost() { |
110 | if (host == null) { |
111 | host = sessionManager.getHost(key); |
112 | } |
113 | return host; |
114 | } |
115 | |
116 | /** |
117 | * @see org.apache.shiro.session.Session#touch() |
118 | */ |
119 | public void touch() throws InvalidSessionException { |
120 | sessionManager.touch(key); |
121 | } |
122 | |
123 | /** |
124 | * @see org.apache.shiro.session.Session#stop() |
125 | */ |
126 | public void stop() throws InvalidSessionException { |
127 | sessionManager.stop(key); |
128 | } |
129 | |
130 | /** |
131 | * @see org.apache.shiro.session.Session#getAttributeKeys |
132 | */ |
133 | public Collection<Object> getAttributeKeys() throws InvalidSessionException { |
134 | return sessionManager.getAttributeKeys(key); |
135 | } |
136 | |
137 | /** |
138 | * @see org.apache.shiro.session.Session#getAttribute(Object key) |
139 | */ |
140 | public Object getAttribute(Object attributeKey) throws InvalidSessionException { |
141 | return sessionManager.getAttribute(this.key, attributeKey); |
142 | } |
143 | |
144 | /** |
145 | * @see Session#setAttribute(Object key, Object value) |
146 | */ |
147 | public void setAttribute(Object attributeKey, Object value) throws InvalidSessionException { |
148 | if (value == null) { |
149 | removeAttribute(attributeKey); |
150 | } else { |
151 | sessionManager.setAttribute(this.key, attributeKey, value); |
152 | } |
153 | } |
154 | |
155 | /** |
156 | * @see Session#removeAttribute(Object key) |
157 | */ |
158 | public Object removeAttribute(Object attributeKey) throws InvalidSessionException { |
159 | return sessionManager.removeAttribute(this.key, attributeKey); |
160 | } |
161 | } |
这是个门面类,它所有的方法实现都是调用 sessionManager 的相应方法
SessionFactory

只有一个方法: createSession()
1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one |
3 | * or more contributor license agreements. See the NOTICE file |
4 | * distributed with this work for additional information |
5 | * regarding copyright ownership. The ASF licenses this file |
6 | * to you under the Apache License, Version 2.0 (the |
7 | * "License"); you may not use this file except in compliance |
8 | * with the License. You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, |
13 | * software distributed under the License is distributed on an |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | * KIND, either express or implied. See the License for the |
16 | * specific language governing permissions and limitations |
17 | * under the License. |
18 | */ |
19 | package org.apache.shiro.session.mgt; |
20 | |
21 | import org.apache.shiro.session.Session; |
22 | |
23 | /** |
24 | * {@code SessionFactory} implementation that generates {@link SimpleSession} instances. |
25 | * |
26 | * @since 1.0 |
27 | */ |
28 | public class SimpleSessionFactory implements SessionFactory { |
29 | |
30 | /** |
31 | * Creates a new {@link SimpleSession SimpleSession} instance retaining the context's |
32 | * {@link SessionContext#getHost() host} if one can be found. |
33 | * |
34 | * @param initData the initialization data to be used during {@link Session} creation. |
35 | * @return a new {@link SimpleSession SimpleSession} instance |
36 | */ |
37 | public Session createSession(SessionContext initData) { |
38 | if (initData != null) { |
39 | String host = initData.getHost(); |
40 | if (host != null) { |
41 | return new SimpleSession(host); |
42 | } |
43 | } |
44 | return new SimpleSession(); |
45 | } |
46 | } |