第十章 会话管理(四) 会话存储/持久化

来源:互联网 发布:阿里云部署微信公众号 编辑:程序博客网 时间:2024/06/05 15:28

第十章 Demo(待完善)


Shiro 提供SessionDAO 用于会话的CRUD,即DAO(Data Access Object)模式实现:

1. 如DefaultSessionManager 在创建完session 后会调用该方法;如保存到关系数据库/文件系统/NoSQL 数据库;即可以实现会话的持久化;返回会话ID;主要此处返回的ID.equals(session.getId());

Serializable create(Session session);

2. 根据会话ID获取会话

Session readSession(Serializable sessionId) throws UnknownSessionException;

3. 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用

void update(Session session) throws UnknownSessionException;

4. 删除会话;当会话过期/会话停止(如用户退出时)会调用

void delete(Session session);

5. 获取当前所有活跃用户,如果用户量多此方法影响性能

Collection<Session> getActiveSessions();

Shiro 内嵌了如下SessionDAO 实现:


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

CachingSessionDAO提供了对开发者透明的会话缓存的功能,只需要设置相应的CacheManager 即可;

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

EnterpriseCacheSessionDAO 提供了缓存功能的会话维护,默认情况下使用MapCache 实现,内部使用ConcurrentHashMap 保存缓存的会话。


可以通过如下配置设置SessionDAO:

sessionDAO=org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAOsessionManager.sessionDAO=$sessionDAO

一、 Shiro 提供了使用Ehcache 进行会话存储,Ehcache 可以配合TerraCotta 实现容器无关的分布式集群。

首先在pom.xml里添加如下依赖:

<dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-ehcache</artifactId>    <version>1.2.2</version></dependency>


接着配置shiro-web.ini文件:

sessionDAO=org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAOsessionDAO.activeSessionsCacheName=shiro-activeSessionCachesessionIdGenerator=org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGeneratorsessionDAO.sessionIdGenerator=$sessionIdGeneratorsessionManager.sessionDAO=$sessionDAOcacheManager=org.apache.shiro.cache.ehcache.EhCacheManagercacheManager.cacheManagerConfigFile=classpath:ehcache.xmlsecurityManager.cacheManager=$cacheManagersecurityManager.sessionManager=$sessionManager

sessionDAO. activeSessionsCacheName : 设置Session 缓存名字, 默认就是shiro-activeSessionCache;

cacheManager:缓存管理器,用于管理缓存的,此处使用Ehcache实现;

cacheManager.cacheManagerConfigFile:设置ehcache缓存的配置文件;

securityManager.cacheManager:设置SecurityManager的cacheManager,会自动设置实现了CacheManagerAware接口的相应对象,如SessionDAO 的cacheManager;


然后配置ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?><ehcache name="es"><!--     <diskStore path="java.io.tmpdir"/> -->    <cache name="shiro-activeSessionCache"           maxEntriesLocalHeap="10000"           overflowToDisk="false"           eternal="false"           diskPersistent="false"           timeToLiveSeconds="0"           timeToIdleSeconds="0"           statistics="true"/></ehcache>

Cache的名字为shiro-activeSessionCache,即设置的sessionDAO的activeSessionsCacheName属性值。

另外可以通过如下ini配置设置会话ID 生成器:

sessionIdGenerator=org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGeneratorsessionDAO.sessionIdGenerator=$sessionIdGenerator

用于生成会话ID,默认就是JavaUuidSessionIdGenerator,使用java.util.UUID生成。


如果自定义实现SessionDAO,继承CachingSessionDAO 即可:

public class MySessionDao extends CachingSessionDAO{private JdbcTemplate jdbcTemplate = JdbcTemplateUtils.jdbcTemplate();protected Serializable doCreate(Session session) {System.out.println("doCreate");Serializable sessionId = generateSessionId(session);assignSessionId(session, sessionId);String sql = "insert into sessions (id,session) values (?,?)";jdbcTemplate.update(sql, sessionId,SerializableUtils.serialize(session));return session.getId();}protected void doUpdate(Session session) {System.out.println("doUpdate");if(session instanceof ValidatingSession && !((ValidatingSession)session).isValid()){return;//如果会话过期/停止,没必要再更新了}String sql = "update sessions set session=? where id=?";jdbcTemplate.update(sql,SerializableUtils.serialize(session),session.getId());}protected void doDelete(Session session) {System.out.println("doDelete");String sql="delete from sessions where id = ?";jdbcTemplate.update(sql,session.getId());}protected Session doReadSession(Serializable sessionId) {System.out.println("doReadSession");String sql = "select session from sessions where id = ?";List<String> sessionStrList = jdbcTemplate.queryForList(sql,String.class,sessionId);if(sessionStrList.size()==0) return null;return SerializableUtils.deserialize(sessionStrList.get(0));}}

doCreate/doUpdate/doDelete/doReadSession 分别代表创建/修改/删除/读取会话;此处通过把会话序列化后存储到数据库实现;接着在shiro-web.ini中配置:

sessionDAO=session.dao.MySessionDao

其他设置和之前一样,因为继承了CachingSessionDAO;所有在读取时会先查缓存中是否存在,如果找不到才到数据库中查找。