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,目前这个问题还没有想到比较好的解决方案。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
spring boot整合Shiro实现单点登录的示例代码
-
spring boot整合redis实现shiro的分布式session共享的方法
-
Spring boot集成spring session实现session共享的方法
-
Spring Boot分布式系统实践【扩展1】shiro+redis实现session共享、simplesession反序列化失败的问题定位及反思改进
-
spring boot整合mybatis利用Mysql实现主键UUID的方法
-
浅析PHP分布式中Redis实现Session的方法
-
Spring Boot 整合mybatis 使用多数据源的实现方法
-
Redis快速实现分布式session的方法详解
-
Spring Boot 整合 Redis + Spring Session(实现 Session 共享)
-
PHP分布式中Redis实现Session的方法