我们知道,shiro是通过SessionManager来管理会话的,而对于会话的操作则是通过SessionDao来实现的,默认的情况下,shiro实现了两种SessionDao,分别为CachingSessionDAO和MemorySessionDAO,当我们使用EhCache缓存时,则是使用的CachingSessionDAO,不适用缓存的情况下,就会选择基于内存的SessionDao。所以,如果我们想实现基于复述的分布式会话共享,重点在于重写SessionManager中的SessionDao。我们的重写代码如下:
包com.chhliu.springboot.shiro.cache; 进口java.io.Serializable; 进口java.util.Collection; 进口java.util.concurrent.TimeUnit; 进口org.apache.shiro.session.Session; 进口org.apache.shiro.session.UnknownSessionException; 进口org.apache.shiro.session.mgt.eis.AbstractSessionDAO; 进口org.springframework.beans.factory.annotation.Autowired; 进口org.springframework.data.redis.core.RedisTemplate; 进口org.springframework.stereotype.Service; @ service @SuppressWarnings ({“rawtypes”、“unchecked”}) 公开课RedisSessionDao延伸AbstractSessionDAO {//会话超时时间,单位为毫秒 私人长expireTime=120000; @ autowired 私人RedisTemplate RedisTemplate;//复述,操作类,对这个使用不熟悉的,可以参考前面的博客 公共RedisSessionDao () { 超级(); } 公共RedisSessionDao(长expireTime RedisTemplate RedisTemplate) { 超级(); 这一点。expireTime=expireTime; 这一点。redisTemplate=redisTemplate; } @Override//更新会话 公共空间更新会话(会话)抛出UnknownSessionException { System.out.println(“===============更新================"); 如果(会话==null | | session.getId ()==null) { 返回: } session.setTimeout (expireTime); redisTemplate.opsForValue()这里(session.getId(),会话,expireTime, TimeUnit.MILLISECONDS); } @Override//删除会话 公共空间删除会话(会话){ System.out.println(“===============删除================"); 如果(null==会话){ 返回: } .getOperations redisTemplate.opsForValue () () delete (session.getId ()); } @Override//获取活跃的会话,可以用来统计在线人数,如果要实现这个功能,可以在将会话加入复述时指定一个会议前缀,统计的时候则使用键(“session-prefix *”)的方式来模糊查找复述中所有的会话集合 公共CollectiongetActiveSessions () { System.out.println (“==============getActiveSessions================="); 返回redisTemplate.keys (“*”); } @Override//加入会话 保护Serializable doCreate(会话会话){ System.out.println (“===============doCreate================"); 可序列化的sessionId=this.generateSessionId(会话); 这一点。assignSessionId(会话,sessionId); redisTemplate.opsForValue()这里(session.getId(),会话,expireTime, TimeUnit.MILLISECONDS); 返回sessionId; }//读@Override取会话 保护会话doReadSession(可串行化的sessionId) { System.out.println (“==============doReadSession================="); 如果(sessionId==null) { 返回null; } 返回(会话)redisTemplate.opsForValue () . get (sessionId); } 公共长getExpireTime () { 返回expireTime; } 公共空间setExpireTime(长expireTime) { 这一点。expireTime=expireTime; } 公共RedisTemplate getRedisTemplate () { 返回redisTemplate; } 公共空间setRedisTemplate (RedisTemplate RedisTemplate) { 这一点。redisTemplate=redisTemplate; } } >之前 SessionDao实现完了之后,我们就需要将SessionDao加入SessionManager中了,代码如下:
@ bean 公共DefaultWebSessionManager configWebSessionManager () { DefaultWebSessionManager经理=new DefaultWebSessionManager (); manager.setCacheManager (cacheManager);//加入缓存管理器 manager.setSessionDAO (sessionDao);//设置sessionDao manager.setDeleteInvalidSessions(真正);//删除过期的会话 manager.setGlobalSessionTimeout (sessionDao.getExpireTime());//设置全局会议超时时间 manager.setSessionValidationSchedulerEnabled(真正);//是否定时检查会话 返回经理; } >之前最后一步就是将SessionManager配置到SecurityManager中了
@ bean 公共SecurityManager SecurityManager (DefaultWebSessionManager webSessionManager) { DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager ();//设置领域。 securityManager.setRealm (myShiroRealm ());//注入缓存管理器; securityManager.setCacheManager (cacheManager);//这个如果执行多次,也是同样的一个对象;//会话管理器 securityManager.setSessionManager (webSessionManager);//注入记住我管理器; securityManager.setRememberMeManager (rememberMeManager ()); 返回securityManager; }弹簧引导整合复述,实现shiro的分布式会话共享的方法