springboot整合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 urrent.TimeUnit;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.is.AbstractSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.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();
}
@Override // 更新session
public void update(Session session) throws UnknownSessionException {
System.out.println("===============update================");
if (session == null || Id() == null) {
return;
}
session.setTimeout(expireTime);
redisTemplate.opsForValue().Id(), session, expireTime, TimeUnit.MILLISECONDS);
}
@Override // 删除session
public void delete(Session session) {
System.out.println("===============delete================");
if (null == session) {
return;
}
redisTemplate.opsForValue().getOperations().Id());
}
@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 = ateSessionId(session);
this.assignSessionId(session, sessionId);
redisTemplate.opsForValue().Id(), 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) {
}
public RedisTemplate getRedisTemplate() {session如何设置和读取
return redisTemplate;
}
public void setRedisTemplate(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.ExpireTime());// 设置全局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,⽬前这个问题还没有想到⽐较好的解决⽅案。以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论