spring boot整合redis實現(xiàn)shiro的分布式session共享的方法
我們知道,shiro是通過SessionManager來管理Session的,而對于Session的操作則是通過SessionDao來實現(xiàn)的,默認的情況下,shiro實現(xiàn)了兩種SessionDao,分別為CachingSessionDAO和MemorySessionDAO,當我們使用EhCache緩存時,則是使用的CachingSessionDAO,不適用緩存的情況下,就會選擇基于內(nèi)存的SessionDao.所以,如果我們想實現(xiàn)基于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,可以用來統(tǒng)計在線人數(shù),如果要實現(xiàn)這個功能,可以在將session加入redis時指定一個session前綴,統(tǒng)計的時候則使用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實現(xiàn)完了之后,我們就需要將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);// 這個如果執(zhí)行多次,也是同樣的一個對象;
// 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=================
我們會發(fā)現(xiàn),當一個頁面中存在多個資源的時候,會不停的調(diào)用doReadSession,update方法來讀取和更新session,目前這個問題還沒有想到比較好的解決方案。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
詳解java實現(xiàn)簡單掃碼登錄功能(模仿微信網(wǎng)頁版掃碼)
這篇文章主要介紹了java實現(xiàn)簡單掃碼登錄功能(模仿微信網(wǎng)頁版掃碼),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-05-05
完美解決在Servlet中出現(xiàn)一個輸出中文亂碼的問題
下面小編就為大家?guī)硪黄昝澜鉀Q在Servlet中出現(xiàn)一個輸出中文亂碼的問題。小編覺得挺不錯的現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01
Java 實戰(zhàn)項目之教材管理系統(tǒng)的實現(xiàn)流程
讀萬卷書不如行萬里路,只學書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+jsp+mysql+maven實現(xiàn)教材管理系統(tǒng),大家可以在過程中查缺補漏,提升水平2021-11-11
java?JVM方法分派模型靜態(tài)分派動態(tài)分派全面講解
這篇文章主要為大家介紹了java?JVM方法分派模型靜態(tài)分派動態(tài)分派全面講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
SpringCloud Config使用本地倉庫及map注入
這篇文章主要介紹了SpringCloud Config使用本地倉庫及map注入,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09

