最近项目中用到的Session共享场景:两个独立应用,希望实现DB层共享用户,而且用户只需要登录一次。
分析:这种场合,不适用单点,因为用户数据并不需要单独在第三方应用管理,而且添加单点也会增加整个系统的复杂度
两种实现思路:Session数据存在DB中或者缓存Ehcache中
决策:考虑到查询效率问题,使用缓存机制。
步骤如下:(已经过实际项目检验,如您遇到问题,请在评论中回复)
1. ehcache.xml配置<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ehcache>
<ehcache name="shiro" updateCheck="false" monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir/ehcache" />
<!-- 默认缓存配置. 自动失效:最后一次访问时间间隔300秒失效,若没有访问过自创建时间600秒失效。->
<defaultCache maxEntriesLocalHeap="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="600"
overflowToDisk="true" statistics="true" />
<!-- 会话缓存 -->
<cache name="shiro-activeSessionCache" maxEntriesLocalHeap="10000"
eternal="true"
timeToIdleSeconds="0" timeToLiveSeconds="0"
overflowToDisk="true" statistics="true" >
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
</cache>
<!-- 监听服务,用户监听其它应用通过过来的session操作 -->
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=localhost, port=40002,
socketTimeoutMillis=2000">
</cacheManagerPeerListenerFactory>
<!-- 提供服务,当本应用对session操作时,会复制到其它应用(如果是多个应用则需要在rmiUrls属性写多个url,并用中竖线分割 -->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//localhost:40001/shiro-activeSessionCache">
</cacheManagerPeerProviderFactory>
</ehcache>
2. 配置(ini或者config)
1)配置CacheManager
/**
* 核心:SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。
* 依赖项设置:Realm,SessionManager,CacheManager
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager defaultWebSecurityManager(SystemAuthorizingRealm systemAuthorizingRealm,
DefaultWebSessionManager sessionManager, EhCacheManager examCacheManager) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(systemAuthorizingRealm);
defaultWebSecurityManager.setSessionManager(sessionManager);
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
defaultWebSecurityManager.setCacheManager(examCacheManager);
return defaultWebSecurityManager;
}
2)配置SessionDAO
@Bean(name = "sessionDao")
public EnterpriseCacheSessionDAO sessionDao(){
EnterpriseCacheSessionDAO sessionDao = new EnterpriseCacheSessionDAO();
sessionDao.setActiveSessionsCacheName("shiro-activeSessionCache");
return sessionDao;
}
就这么简单!
