SessionDao系列源码

sessionDao接口的源码如下,通过名字就可以知道方法的作用,就不翻译解释了

public interface SessionDAO {
   
    Serializable create(Session session);

    Session readSession(Serializable sessionId) throws UnknownSessionException;

    void update(Session session) throws UnknownSessionException;

    void delete(Session session);

    Collection<Session> getActiveSessions();
}

在shiro中实现该接口的类的结构如如下

AbstractSessionDao,它对会话创建和读取执行一些健全性检查,并在需要时允许可插入自己的会话ID生成策略。
update和delete方法留给了子类实现,readSession和create方法也没有实现,代用了自己的抽象方法doReadSession和doCreate,需要子类实现。 

/**
 * An abstract {@code SessionDAO} implementation that performs some sanity checks on session creation and reading and
 * allows for pluggable Session ID generation strategies if desired.  The {@code SessionDAO}
 * {@link SessionDAO#update update} and {@link SessionDAO#delete delete} methods are left to
 * subclasses.
 * 一个抽象的 {@code SessionDAO}实现,它对会话创建和读取执行一些健全性检查,并在需要时允许可插入的会话ID生成策略。
 * {@code SessionDAO} {@link SessionDAO#update update} 和 {@link SessionDAO#delete delete}方法留给了子类。
 *
 * <h3>Session ID Generation</h3>
 * This class also allows for plugging in a {@link SessionIdGenerator} for custom ID generation strategies.  This is
 * optional, as the default generator is probably sufficient for most cases.  Subclass implementations that do use a
 * generator (default or custom) will want to call the
 * {@link #generateSessionId(org.apache.shiro.session.Session)} method from within their {@link #doCreate}
 * implementations.
 * 此类还允许插入 {@link SessionIdGenerator}以实现自定义ID生成策略。 这是可选的,因为默认生成器可能足以满足大多数情况。 
 * 使用生成器(默认或自定义)的子类实现将希望从 {@link #doCreate}实现中调用 
 * {@link #generateSessionId(org.apache.shiro.session.Session)}方法。
 * <p/>
 *
 * Subclass implementations that rely on the EIS data store to generate the ID automatically (e.g. when the session
 * ID is also an auto-generated primary key), they can simply ignore the {@code SessionIdGenerator} concept
 * entirely and just return the data store's ID from the {@link #doCreate} implementation.
 * 依赖于EIS数据存储自动生成ID的子类实现(例如,当会话ID也是自动生成的主键时),
 * 他们可以完全忽略 {@code SessionIdGenerator}概念,只返回数据存储的ID {@link #doCreate}实现。
 *
 * @since 1.0
 */
public abstract class AbstractSessionDAO implements SessionDAO {

    private SessionIdGenerator sessionIdGenerator;
    public AbstractSessionDAO() {
        this.sessionIdGenerator = new JavaUuidSessionIdGenerator();
    }
    public SessionIdGenerator getSessionIdGenerator() {
        return sessionIdGenerator;
    }
    public void setSessionIdGenerator(SessionIdGenerator sessionIdGenerator) {
        this.sessionIdGenerator = sessionIdGenerator;
    }
    protected Serializable generateSessionId(Session session) {
        if (this.sessionIdGenerator == null) {
            String msg = "sessionIdGenerator attribute has not been configured.";
            throw new IllegalStateException(msg);
        }
        return this.sessionIdGenerator.generateId(session);
    }

    public Serializable create(Session session) {
        Serializable sessionId = doCreate(session);
        verifySessionId(sessionId);
        return sessionId;
    }

    private void verifySessionId(Serializable sessionId) {
        if (sessionId == null) {
            String msg = "sessionId returned from doCreate implementation is null.  Please verify the implementation.";
            throw new IllegalStateException(msg);
        }
    }

    protected void assignSessionId(Session session, Serializable sessionId) {
        ((SimpleSession) session).setId(sessionId);
    }

    /**
     * Subclass hook to actually persist the given <tt>Session</tt> instance to the underlying EIS.
     *
     * @param session the Session instance to persist to the EIS.
     * @return the id of the session created in the EIS (i.e. this is almost always a primary key and should be the
     *         value returned from {@link org.apache.shiro.session.Session#getId() Session.getId()}.
     */
    protected abstract Serializable doCreate(Session session);

    public Session readSession(Serializable sessionId) throws UnknownSessionException {
        Session s = doReadSession(sessionId);
        if (s == null) {
            throw new UnknownSessionException("There is no session with id [" + sessionId + "]");
        }
        return s;
    }

    /**
     * Subclass implementation hook that retrieves the Session object from the underlying EIS or {@code null} if a
     * session with that ID could not be found.
     *
     * @param sessionId the id of the <tt>Session</tt> to retrieve.
     * @return the Session in the EIS identified by <tt>sessionId</tt> or {@code null} if a
     *         session with that ID could not be found.
     */
    protected abstract Session doReadSession(Serializable sessionId);

}

MemorySessionDao是通过ConcurrentHashMap来实现的基于内容的session的存储的,DefaultSessionManager默认使用的就是MemorySessionDao

/**
 * Simple memory-based implementation of the SessionDAO that stores all of its sessions in an in-memory
 * {@link ConcurrentMap}.  <b>This implementation does not page to disk and is therefore unsuitable for applications
 * that could experience a large amount of sessions</b> and would therefore cause {@code OutOfMemoryException}s.  It is
 * <em>not</em> recommended for production use in most environments.
 * SessionDAO是简单基于内存的实现,它将所有会话存储在内存中 {@link ConcurrentMap}中。 
 * 此实现不会分页到磁盘,因此不适合可能遇到大量会话的应用程序,因此会导致 {@code OutOfMemoryException}。 
 * 不建议在大多数环境中进行生产使用。
 *
 * <h2>Memory Restrictions</h2>
 * If your application is expected to host many sessions beyond what can be stored in the
 * memory available to the JVM, it is highly recommended to use a different {@code SessionDAO} implementation which
 * uses a more expansive or permanent backing data store.
 * 如果您的应用程序需要承载超出可存储在JVM可用内存中的多个会话,
 * 强烈建议使用不同的 {@code SessionDAO}实现,该实现使用更广泛或永久的后备数据存储。
 * <p/>
 * 
 * In this case, it is recommended to instead use a custom
 * {@link CachingSessionDAO} implementation that communicates with a higher-capacity data store of your choice
 * (file system, database, etc).
 * 在这种情况下,建议使用自定义的 {@link CachingSessionDAO}实现,
 * 该实现与您选择的更高容量的数据存储(文件系统,数据库等)进行通信。
 *
 * <h2>Changes in 1.0</h2>
 * This implementation prior to 1.0 used to subclass the {@link CachingSessionDAO}, but this caused problems with many
 * cache implementations that would expunge entries due to TTL settings, resulting in Sessions that would be randomly
 * (and permanently) lost.  The Shiro 1.0 release refactored this implementation to be 100% memory-based (without
 * {@code Cache} usage to avoid this problem.
 * 1.0之前的这个实现用于子类 {@link CachingSessionDAO},但是这导致了许多缓存实现的问题,这些缓存实现会因TTL设置而清除条目,
 * 从而导致随机(和永久)丢失的Sessions。 
 * Shiro 1.0版本重构了这个实现是100%基于内存的用法来避免这个问题。
 *
 * @see CachingSessionDAO
 * @since 0.1
 */
public class MemorySessionDAO extends AbstractSessionDAO {

    private static final Logger log = LoggerFactory.getLogger(MemorySessionDAO.class);

    private ConcurrentMap<Serializable, Session> sessions;

    public MemorySessionDAO() {
        this.sessions = new ConcurrentHashMap<Serializable, Session>();
    }

    protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        storeSession(sessionId, session);
        return sessionId;
    }

    protected Session storeSession(Serializable id, Session session) {
        if (id == null) {
            throw new NullPointerException("id argument cannot be null.");
        }
        return sessions.putIfAbsent(id, session);
    }

    protected Session doReadSession(Serializable sessionId) {
        return sessions.get(sessionId);
    }

    public void update(Session session) throws UnknownSessionException {
        storeSession(session.getId(), session);
    }

    public void delete(Session session) {
        if (session == null) {
            throw new NullPointerException("session argument cannot be null.");
        }
        Serializable id = session.getId();
        if (id != null) {
            sessions.remove(id);
        }
    }

    public Collection<Session> getActiveSessions() {
        Collection<Session> values = sessions.values();
        if (CollectionUtils.isEmpty(values)) {
            return Collections.emptySet();
        } else {
            return Collections.unmodifiableCollection(values);
        }
    }

}

CachingSessionDAO也是一个抽象方法,继承了AbstractSessionDao,并且实现了CacheManagerAware方法。

/**
 * An CachingSessionDAO is a SessionDAO that provides a transparent caching layer between the components that
 * use it and the underlying EIS (Enterprise Information System) session backing store (for example, filesystem,
 * database, enterprise grid/cloud, etc).
 * CachingSessionDAO是一个SessionDAO,它在使用它的组件和底层EIS(企业信息系统)
 * 会话存储(例如,文件系统,数据库,企业网格/云等)系统之间提供了一层透明的缓存层。
 * 注:这样就可以减少对于底层缓存系统中对session的频繁读取等操作
 * <p/>
 *
 * This implementation caches all active sessions in a configured
 * {@link #getActiveSessionsCache() activeSessionsCache}.  This property is {@code null} by default and if one is
 * not explicitly set, a {@link #setCacheManager cacheManager} is expected to be configured which will in turn be used
 * to acquire the {@code Cache} instance to use for the {@code activeSessionsCache}.
 * 此实现将所有活动会话缓存在已配置的activeSessionsCache中。 
 * 默认情况下并且未明确设置activeSessions,此属性为 {@code null}。
 * 需要配置 cacheManager,然后将通过getActiveSessionsCache来获取要用的缓存实例。
 * 
 * <p/>
 * All {@code SessionDAO} methods are implemented by this class to employ
 * caching behavior and delegates the actual EIS operations to respective do* methods to be implemented by
 * subclasses (doCreate, doRead, etc).
 * 所有SessionDAO方法都由此类实现,以用来做缓存行为,
 * 并将实际的EIS操作委托给由子类实现的各个do *方法(doCreate,doRead等)。
 *
 * @since 0.2
 */
public abstract class CachingSessionDAO extends AbstractSessionDAO implements CacheManagerAware {

    /**
     * The default active sessions cache name, equal to {@code shiro-activeSessionCache}.
     */
    public static final String ACTIVE_SESSION_CACHE_NAME = "shiro-activeSessionCache";

    /**
     * The CacheManager to use to acquire the Session cache.
     * cacheManager用于获取session缓存
     */
    private CacheManager cacheManager;

    /**
     * The Cache instance responsible for caching Sessions.
     * 用于缓存session的Cache实例
     */
    private Cache<Serializable, Session> activeSessions;

    /**
     * The name of the session cache, defaults to {@link #ACTIVE_SESSION_CACHE_NAME}.
     * session缓存的名字
     */
    private String activeSessionsCacheName = ACTIVE_SESSION_CACHE_NAME;

    /**
     * Default no-arg constructor.
     */
    public CachingSessionDAO() {
    }

    /**
     * Sets the cacheManager to use for acquiring the {@link #getActiveSessionsCache() activeSessionsCache} if
     * one is not configured.
     *
     * @param cacheManager the manager to use for constructing the session cache.
     */
    public void setCacheManager(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    public CacheManager getCacheManager() {
        return cacheManager;
    }

    public String getActiveSessionsCacheName() {
        return activeSessionsCacheName;
    }

    /**
     * Sets the name of the active sessions cache to be returned by the {@code CacheManager}.  Defaults to
     * {@link #ACTIVE_SESSION_CACHE_NAME}.
     *
     * @param activeSessionsCacheName the name of the active sessions cache to be returned by the {@code CacheManager}.
     */
    public void setActiveSessionsCacheName(String activeSessionsCacheName) {
        this.activeSessionsCacheName = activeSessionsCacheName;
    }

    /**
     * Returns the cache instance to use for storing active sessions.  If one is not available (it is {@code null}),
     * it will be {@link CacheManager#getCache(String) acquired} from the {@link #setCacheManager configured}
     * {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}.
     *
     * @return the cache instance to use for storing active sessions or {@code null} if the {@code Cache} instance
     *         should be retrieved from the
     */
    public Cache<Serializable, Session> getActiveSessionsCache() {
        return this.activeSessions;
    }

    /**
     * Sets the cache instance to use for storing active sessions.  If one is not set (it remains {@code null}),
     * it will be {@link CacheManager#getCache(String) acquired} from the {@link #setCacheManager configured}
     * {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}.
     *
     * @param cache the cache instance to use for storing active sessions or {@code null} if the cache is to be
     *              acquired from the {@link #setCacheManager configured} {@code CacheManager}.
     */
    public void setActiveSessionsCache(Cache<Serializable, Session> cache) {
        this.activeSessions = cache;
    }

    /**
     * Returns the active sessions cache, but if that cache instance is null, first lazily creates the cache instance
     * via the {@link #createActiveSessionsCache()} method and then returns the instance.
     * <p/>
     * Note that this method will only return a non-null value code if the {@code CacheManager} has been set.  If
     * not set, there will be no cache.
     * 返回活动会话缓存,但如果该缓存实例为null,
     * 则首先通过 {@link #createActiveSessionsCache()}方法懒惰地创建缓存实例,然后返回实例。
     * 请注意,如果已设置 {@code CacheManager},则此方法仅返回非空值代码。 如果未设置,则不会有缓存。
     * 
     * @return the active sessions cache instance.
     */
    private Cache<Serializable, Session> getActiveSessionsCacheLazy() {
        if (this.activeSessions == null) {
            this.activeSessions = createActiveSessionsCache();
        }
        return activeSessions;
    }

    /**
     *
     * @return a cache instance used to store active sessions, or {@code null} if the {@code CacheManager} has
     *         not been set.
     * 返回一个实例用来存储活动会话,如果没有设置cacheManger,则返回null,也就是不缓存活动会话
     */
    protected Cache<Serializable, Session> createActiveSessionsCache() {
        Cache<Serializable, Session> cache = null;
        CacheManager mgr = getCacheManager();
        if (mgr != null) {
            String name = getActiveSessionsCacheName();
            cache = mgr.getCache(name);
        }
        return cache;
    }

    /**
     * Calls {@code super.create(session)}, then caches the session keyed by the returned {@code sessionId}, and then
     * returns this {@code sessionId}.
     *
     * @param session Session object to create in the EIS and then cache.
     */
    public Serializable create(Session session) {
        Serializable sessionId = super.create(session);
        cache(session, sessionId);
        return sessionId;
    }

    /**
     * Returns the cached session with the corresponding {@code sessionId} or {@code null} if there is
     * no session cached under that id (or if there is no Cache).
     *
     * @param sessionId the id of the cached session to acquire.
     * @return the cached session with the corresponding {@code sessionId}, or {@code null} if the session
     *         does not exist or is not cached.
     */
    protected Session getCachedSession(Serializable sessionId) {
        Session cached = null;
        if (sessionId != null) {
            Cache<Serializable, Session> cache = getActiveSessionsCacheLazy();
            if (cache != null) {
                cached = getCachedSession(sessionId, cache);
            }
        }
        return cached;
    }

    /**
     * Returns the Session with the specified id from the specified cache.  This method simply calls
     * {@code cache.get(sessionId)} and can be overridden by subclasses for custom acquisition behavior.
     *
     * @param sessionId the id of the session to acquire.
     * @param cache     the cache to acquire the session from
     * @return the cached session, or {@code null} if the session wasn't in the cache.
     */
    protected Session getCachedSession(Serializable sessionId, Cache<Serializable, Session> cache) {
        return cache.get(sessionId);
    }

    /**
     * Caches the specified session under the cache entry key of {@code sessionId}.
     *
     * @param session   the session to cache
     * @param sessionId the session id, to be used as the cache entry key.
     * @since 1.0
     */
    protected void cache(Session session, Serializable sessionId) {
        if (session == null || sessionId == null) {
            return;
        }
        Cache<Serializable, Session> cache = getActiveSessionsCacheLazy();
        if (cache == null) {
            return;
        }
        cache(session, sessionId, cache);
    }

    /**
     * Caches the specified session in the given cache under the key of {@code sessionId}.  This implementation
     * simply calls {@code cache.put(sessionId,session)} and can be overridden for custom behavior.
     *
     * @param session   the session to cache
     * @param sessionId the id of the session, expected to be the cache key.
     * @param cache     the cache to store the session
     */
    protected void cache(Session session, Serializable sessionId, Cache<Serializable, Session> cache) {
        cache.put(sessionId, session);
    }

    /**
     * Attempts to acquire the Session from the cache first using the session ID as the cache key.  If no session
     * is found, {@code super.readSession(sessionId)} is called to perform the actual retrieval.
     *
     * @param sessionId the id of the session to retrieve from the EIS.
     * @return the session identified by {@code sessionId} in the EIS.
     * @throws UnknownSessionException if the id specified does not correspond to any session in the cache or EIS.
     */
    public Session readSession(Serializable sessionId) throws UnknownSessionException {
        Session s = getCachedSession(sessionId);
        if (s == null) {
            s = super.readSession(sessionId);
        }
        return s;
    }

    /**
     * Updates the state of the given session to the EIS by first delegating to
     * {@link #doUpdate(org.apache.shiro.session.Session)}.  If the session is a {@link ValidatingSession}, it will
     * be added to the cache only if it is {@link ValidatingSession#isValid()} and if invalid, will be removed from the
     * cache.  If it is not a {@code ValidatingSession} instance, it will be added to the cache in any event.
     *
     * @param session the session object to update in the EIS.
     * @throws UnknownSessionException if no existing EIS session record exists with the
     *                                 identifier of {@link Session#getId() session.getId()}
     */
    public void update(Session session) throws UnknownSessionException {
        doUpdate(session);
        if (session instanceof ValidatingSession) {
            if (((ValidatingSession) session).isValid()) {
                cache(session, session.getId());
            } else {
                uncache(session);
            }
        } else {
            cache(session, session.getId());
        }
    }

    /**
     * Subclass implementation hook to actually persist the {@code Session}'s state to the underlying EIS.
     *
     * @param session the session object whose state will be propagated to the EIS.
     */
    protected abstract void doUpdate(Session session);

    /**
     * Removes the specified session from any cache and then permanently deletes the session from the EIS by
     * delegating to {@link #doDelete}.
     *
     * @param session the session to remove from caches and permanently delete from the EIS.
     */
    public void delete(Session session) {
        uncache(session);
        doDelete(session);
    }

    /**
     * Subclass implementation hook to permanently delete the given Session from the underlying EIS.
     *
     * @param session the session instance to permanently delete from the EIS.
     */
    protected abstract void doDelete(Session session);

    /**
     * Removes the specified Session from the cache.
     *
     * @param session the session to remove from the cache.
     */
    protected void uncache(Session session) {
        if (session == null) {
            return;
        }
        Serializable id = session.getId();
        if (id == null) {
            return;
        }
        Cache<Serializable, Session> cache = getActiveSessionsCacheLazy();
        if (cache != null) {
            cache.remove(id);
        }
    }

    /**
     * Returns all active sessions in the system.
     * <p/>
     * <p>This implementation merely returns the sessions found in the activeSessions cache.  Subclass implementations
     * may wish to override this method to retrieve them in a different way, perhaps by an RDBMS query or by other
     * means.
     *
     * @return the sessions found in the activeSessions cache.
     */
    public Collection<Session> getActiveSessions() {
        Cache<Serializable, Session> cache = getActiveSessionsCacheLazy();
        if (cache != null) {
            return cache.values();
        } else {
            return Collections.emptySet();
        }
    }
}
/**
 * SessionDAO implementation that relies on an enterprise caching product as the EIS system of record for all sessions.
 * It is expected that an injected {@link org.apache.shiro.cache.Cache Cache} or
 * {@link org.apache.shiro.cache.CacheManager CacheManager} is backed by an enterprise caching product that can support
 * all application sessions and/or provide disk paging for resilient data storage.
 * SessionDAO实现依赖于企业缓存产品作为EIS系统来记录所有会话。 
 * 要求注入的 Cache或 CacheManager对象需要是企业缓存产品支持的。 
 * 这样可以用来支持所有应用会话,并且(或者)为弹性数据存储提供磁盘分页。
 *
 * <h2>Production Note</h2>
 * This implementation defaults to using an in-memory map-based {@code CacheManager}, which is great for testing but
 * will typically not scale for production environments and could easily cause {@code OutOfMemoryException}s.  Just
 * don't forget to configure<b>*</b> an instance of this class with a production-grade {@code CacheManager} that can
 * handle disk paging for large numbers of sessions and you'll be fine.
 * 此实现默认使用基于内存映射的 CacheManager,使用ConcurrentHashMap来实现的 
 * 这非常适合测试,但通常不会针对生产环境进行扩展,并且很容易导致 {@code OutOfMemoryException}。 
 * 只是不要忘记使用生产级的CacheManager配置这个类的实例,它可以处理大量会话的磁盘分页,你会没事的。
 *
 * <p/>
 * <b>*</b>If you configure Shiro's {@code SecurityManager} instance with such a {@code CacheManager}, it will be
 * automatically applied to an instance of this class and you won't need to explicitly set it in configuration.
 * 如果您使用这样的 {@code CacheManager}配置Shiro的 {@code SecurityManager}实例,
 * 它将自动应用于此类的实例,您无需在配置中明确设置它。
 * 
 * <h3>Implementation Details</h3>
 * This implementation relies heavily on the {@link CachingSessionDAO parent class}'s transparent caching behavior for
 * all storage operations with the enterprise caching product.  Because the parent class uses a {@code Cache} or
 * {@code CacheManager} to perform caching, and the cache is considered the system of record, nothing further needs to
 * be done for the {@link #doReadSession}, {@link #doUpdate} and {@link #doDelete} method implementations.  This class
 * implements those methods as required by the parent class, but they essentially do nothing.
 * 此实现在很大程度上依赖于父类CachingSessionDAO对企业缓存产品的所有存储操作的透明缓存行为。 
 * 因为父类使用 Cache 或 CacheManager 来执行缓存,并且缓存被认为是记录系统,所以不需要为doReadSession,doUpdate 和 doDelete方法实现做任何进一步的工作。
 * 此类实现父类所需的那些方法,但它们基本上什么都不做。
 * @since 1.0
 */
public class EnterpriseCacheSessionDAO extends CachingSessionDAO {

    public EnterpriseCacheSessionDAO() {
        setCacheManager(new AbstractCacheManager() {
            @Override
            protected Cache<Serializable, Session> createCache(String name) throws CacheException {
                return new MapCache<Serializable, Session>(name, new ConcurrentHashMap<Serializable, Session>());
            }
        });
    }

    protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        return sessionId;
    }

    protected Session doReadSession(Serializable sessionId) {
        return null; //should never execute because this implementation relies on parent class to access cache, which
        //is where all sessions reside - it is the cache implementation that determines if the
        //cache is memory only or disk-persistent, etc.
	//这些方法从来不会执行的,因为这个实现依赖于父类来操作缓存
    }

    protected void doUpdate(Session session) {
        //does nothing - parent class persists to cache.
	//什么都不做,父类操作存到缓存中
    }

    protected void doDelete(Session session) {
        //does nothing - parent class removes from cache.
	//什么都不做,父类操作从缓存中删除
    }
}

总结来说

AbstractSessionDAO提供了SessionDAO的基础实现,如生成会话ID等;

MemorySessionDAO直接在内存中进行会话维护;

CachingSessionDAO提供了对开发者透明的会话缓存的功能,需要设置相应的CacheManager即可,用来缓存活动的会话;这里他比MemorySessionDAO多了一个就是会话缓存功能的这个中间层。

在CachingSessionDAO中,他对

1.create(Session session)的实现是,真实的创建session的工作交给了父类super,它只是缓存下来了所创建的session

2.readSession(Serializable sessionId)的时候,先从自己所缓存的session找,如果找不到了,则从父类super中读取sesion

3.update(Session session)的时候,先调用自己的抽象doUpdate(Session session)方法,然后根据情况操作自己的缓存。

    protected abstract void doUpdate(Session session);

4.delete(Session session)的时候,先删除自己这边的缓存,然后调用自己的doDelete方法,这个方法是抽象方法

protected abstract void doDelete(Session session);需要子类实现。

EnterpriseCacheSessionDAO提供了会话缓存功能CacheManger默认实现,默认情况下使用ConcurrentHashMap保存所缓存的会话。这里他没有实现Session的会话维护(这个就需要根据企业的会话存储特点来做了,比如存储到redis中),而是使用了缓存来维护这些会话了,所以他就没有实现会话的read,update,delete;

如果我们要将会话维护到一个集群间可以共享的缓存中,比如redis中的时候,我们可以继承CachingSessionDAO,并实现session在redis中的增加,删除,更新,查询。

sessionManager在这两类的sessionDao实现中调用过程如下

1.sessionManager->MemorySessionDao(做会话维护存储,查询,更新,删除)

2.sessionManager->CachingSessionDao(做了一层缓存)->EnterpriseCacheSessionDAO或自己实现是会话Dao(做会话维护存储,查询,更新,删除);该方法需要注意的是,中间的缓存层(CachingSessionDao)的session的缓存时间一定要短于后面维护层存储的session的有效时间,保证后面的维护层中session过期时,cache中的session一定过期

猜你喜欢

转载自blog.csdn.net/ystyaoshengting/article/details/82725403