spring boot整合redis实现shiro的分布式session共享的方法

 更新时间:2018年01月26日 16:11:32   作者:牛奋lch  
本篇文章主要介绍了spring boot整合redis实现shiro的分布式session共享的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

我们知道,shiro是通过SessionManager来管理Session的,而对于Session的操作则是通过SessionDao来实现的,默认的情况下,shiro实现了两种SessionDao,分别为CachingSessionDAO和MemorySessionDAO,当我们使用EhCache缓存时,则是使用的CachingSessionDAO,不适用缓存的情况下,就会选择基于内存的SessionDao.所以,如果我们想实现基于Redis的分布式Session共享,重点在于重写SessionManager中的SessionDao。我们的重写代码如下:

package com.chhliu.springboot.shiro.cache; 
import java.io.Serializable; 
import java.util.Collection; 
import java.util.concurrent.TimeUnit; 
import org.apache.shiro.session.Session; 
import org.apache.shiro.session.UnknownSessionException; 
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.redis.core.RedisTemplate; 
import org.springframework.stereotype.Service;  
@Service 
@SuppressWarnings({ "rawtypes", "unchecked" }) 
public class RedisSessionDao extends AbstractSessionDAO { 
 
  // Session超时时间,单位为毫秒 
  private long expireTime = 120000; 
 
  @Autowired 
  private RedisTemplate redisTemplate;// Redis操作类,对这个使用不熟悉的,可以参考前面的博客 
 
  public RedisSessionDao() { 
    super(); 
  } 
 
  public RedisSessionDao(long expireTime, RedisTemplate redisTemplate) { 
    super(); 
    this.expireTime = expireTime; 
    this.redisTemplate = redisTemplate; 
  } 
 
  @Override // 更新session 
  public void update(Session session) throws UnknownSessionException { 
    System.out.println("===============update================"); 
    if (session == null || session.getId() == null) { 
      return; 
    } 
    session.setTimeout(expireTime); 
    redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS); 
  } 
 
  @Override // 删除session 
  public void delete(Session session) { 
    System.out.println("===============delete================"); 
    if (null == session) { 
      return; 
    } 
    redisTemplate.opsForValue().getOperations().delete(session.getId()); 
  } 
 
  @Override// 获取活跃的session,可以用来统计在线人数,如果要实现这个功能,可以在将session加入redis时指定一个session前缀,统计的时候则使用keys("session-prefix*")的方式来模糊查找redis中所有的session集合 
  public Collection<Session> getActiveSessions() { 
    System.out.println("==============getActiveSessions================="); 
    return redisTemplate.keys("*"); 
  } 
 
  @Override// 加入session 
  protected Serializable doCreate(Session session) { 
    System.out.println("===============doCreate================"); 
    Serializable sessionId = this.generateSessionId(session); 
    this.assignSessionId(session, sessionId); 
 
    redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS); 
    return sessionId; 
  } 
 
  @Override// 读取session 
  protected Session doReadSession(Serializable sessionId) { 
    System.out.println("==============doReadSession================="); 
    if (sessionId == null) { 
      return null; 
    } 
    return (Session) redisTemplate.opsForValue().get(sessionId); 
  } 
 
  public long getExpireTime() { 
    return expireTime; 
  } 
 
  public void setExpireTime(long expireTime) { 
    this.expireTime = expireTime; 
  } 
 
  public RedisTemplate getRedisTemplate() { 
    return redisTemplate; 
  } 
 
  public void setRedisTemplate(RedisTemplate redisTemplate) { 
    this.redisTemplate = redisTemplate; 
  } 
} 

SessionDao实现完了之后,我们就需要将SessionDao加入SessionManager中了,代码如下:

 @Bean 
  public DefaultWebSessionManager configWebSessionManager(){ 
    DefaultWebSessionManager manager = new DefaultWebSessionManager(); 
    manager.setCacheManager(cacheManager);// 加入缓存管理器 
    manager.setSessionDAO(sessionDao);// 设置SessionDao 
    manager.setDeleteInvalidSessions(true);// 删除过期的session 
    manager.setGlobalSessionTimeout(sessionDao.getExpireTime());// 设置全局session超时时间 
    manager.setSessionValidationSchedulerEnabled(true);// 是否定时检查session 
     
    return manager; 
  } 

最后一步就是将SessionManager配置到SecurityManager中了

@Bean 
  public SecurityManager securityManager(DefaultWebSessionManager webSessionManager) { 
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 
    // 设置realm. 
    securityManager.setRealm(myShiroRealm()); 
 
    // 注入缓存管理器; 
    securityManager.setCacheManager(cacheManager);// 这个如果执行多次,也是同样的一个对象; 
     
    // session管理器 
    securityManager.setSessionManager(webSessionManager); 
     
    //注入记住我管理器; 
    securityManager.setRememberMeManager(rememberMeManager()); 
    return securityManager; 
  } 

测试结果如下:

==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
===============update================ 
==============doReadSession================= 
==============doReadSession================= 
===============update================ 
==============doReadSession================= 
==============doReadSession================= 
==============doReadSession================= 
权限配置-->MyShiroRealm.doGetAuthorizationInfo() 
==============doReadSession================= 

我们会发现,当一个页面中存在多个资源的时候,会不停的调用doReadSession,update方法来读取和更新session,目前这个问题还没有想到比较好的解决方案。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • RxJava的消息发送和线程切换实现原理

    RxJava的消息发送和线程切换实现原理

    这篇文章主要介绍了RxJava的消息发送和线程切换实现原理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • Java详细分析讲解自动装箱自动拆箱与Integer缓存的使用

    Java详细分析讲解自动装箱自动拆箱与Integer缓存的使用

    装箱就是把基本类型转换成包装类,拆箱就是把包装类转换成基本类型,下面这篇文章主要给大家介绍Java中自动装箱、自动拆箱与Integer缓存,需要的朋友可以参考下
    2022-04-04
  • Spring Boot 使用 Disruptor 做内部高性能消息队列

    Spring Boot 使用 Disruptor 做内部高性能消息队列

    这篇文章主要介绍了Spring Boot 使用 Disruptor 做内部高性能消息队列,工作中遇到项目使用Disruptor做消息队列,对你没看错,不是Kafka,也不是rabbitmq。Disruptor有个最大的优点就是快,还有一点它是开源的哦,下面做个简单的记录
    2022-06-06
  • springMVC利用FastJson接口返回json数据相关配置详解

    springMVC利用FastJson接口返回json数据相关配置详解

    本篇文章主要介绍了springMVC利用FastJson接口返回json数据相关配置详解,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • java 微信随机红包算法代码实例

    java 微信随机红包算法代码实例

    这篇文章主要介绍了java 微信随机红包算法的相关资料,并附实例代码,需要的朋友可以参考下
    2016-10-10
  • Java Valhalla Project项目介绍

    Java Valhalla Project项目介绍

    这篇文章主要介绍了Java Valhalla Project项目介绍,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • Java 腾讯验证码平台使用实例

    Java 腾讯验证码平台使用实例

    这篇文章主要介绍了Java 腾讯验证码平台使用实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • IDEA2023常用配置指南(JDK/系统设置等常用配置)

    IDEA2023常用配置指南(JDK/系统设置等常用配置)

    idea很强大,但是初次安装默认的有很多设置并不是满足我们开发的需要,下面这篇文章主要给大家介绍了关于IDEA2023常用配置(JDK/系统设置等常用配置)的相关资料,需要的朋友可以参考下
    2023-12-12
  • java httpclient设置超时时间和代理的方法

    java httpclient设置超时时间和代理的方法

    这篇文章主要介绍了java httpclient设置超时时间和代理的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 详解Java ReentrantLock可重入,可打断,锁超时的实现原理

    详解Java ReentrantLock可重入,可打断,锁超时的实现原理

    前面讲解了ReentrantLock加锁和解锁的原理实现,但是没有阐述它的可重入、可打断以及超时获取锁失败的原理,本文就重点讲解这三种情况,需要的可以了解一下
    2022-10-10

最新评论