Session Storage
為了方便應(yīng)用程序能隨時(shí)訪問Session镇防,Session在創(chuàng)建或更新之后膊毁,需要將其持久化辉阶。與持久化類似储狭,當(dāng)Session無效且使用時(shí)間較長時(shí),需要?jiǎng)h除Session泉懦,以防止Session的存儲(chǔ)空間耗盡拯欧。
SessionDAO
Session的增、刪籽懦、改、查等操作都由SessionManager的實(shí)現(xiàn)類委托給其內(nèi)部組件SessionDAO完成氛魁。
當(dāng)你使用的是native session
時(shí)暮顺,session的默認(rèn)存儲(chǔ)在內(nèi)存中。其實(shí)你還可以將Session存儲(chǔ)在文件系統(tǒng)中秀存、關(guān)系數(shù)據(jù)庫或非關(guān)系型數(shù)據(jù)中等地方捶码。
因?yàn)?code>session的所有操作都是由SessionDAO
完成的,所以或链,如果你想自定義session
的存儲(chǔ)位置惫恼,那么你需要編寫SessionDAO
的實(shí)現(xiàn)類。
其實(shí)澳盐,Shiro本身已經(jīng)提供了SessionDAO
的實(shí)現(xiàn)類祈纯,比如:AbstractSessionDAO
令宿,CachingSessionDAO
,EnterpriseCacheSessionDAO
腕窥,MemorySessionDAO
等粒没,所以你只需要根據(jù)你的實(shí)際需要繼承它們即可。
SessionDAO應(yīng)用
自定義session
的存儲(chǔ)位置有什么用呢簇爆?其實(shí)癞松,當(dāng)你的應(yīng)用程序部署多個(gè)節(jié)點(diǎn),即使用了負(fù)載均衡入蛆,為了在多個(gè)節(jié)點(diǎn)之間共享session
响蓉,你需要將session
信息存儲(chǔ)至緩存中。這時(shí)哨毁,你就需要自定義session
的存儲(chǔ)位置了厕妖。
下面顯示了如何在多個(gè)節(jié)點(diǎn)之間共享session,示例代碼中使用Redis作為session的存儲(chǔ)媒介挑庶,示例代碼如下言秸。
java 代碼
public class RedisSessionDAO extends AbstractSessionDAO {
private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
/**
* The Redis key prefix for the sessions
*/
private String keyPrefix = "shiro_session:";
/**
* shiro-redis的session對象前綴
*/
private RedisManager redisManager;
@Override
public void update(Session session) throws UnknownSessionException {
this.saveSession(session);
}
/**
* save session
*
* @param session
* @throws UnknownSessionException
*/
private void saveSession(Session session) throws UnknownSessionException {
if(session == null || session.getId() == null) {
logger.error("session or session id is null");
return;
}
byte[] key = getByteKey(session.getId());
byte[] value = SerializeUtils.serialize(session);
session.setTimeout(redisManager.getExpire());
this.redisManager.set(key, value, redisManager.getExpire());
}
@Override
public void delete(Session session) {
if(session == null || session.getId() == null) {
logger.error("session or session id is null");
return;
}
redisManager.del(this.getByteKey(session.getId()));
}
@Override
public Collection<Session> getActiveSessions() {
Set<Session> sessions = new HashSet<Session>();
Set<byte[]> keys = redisManager.keys(this.keyPrefix + "*");
if(keys != null && keys.size() > 0) {
for(byte[] key : keys) {
Session s = (Session) SerializeUtils.deserialize(redisManager.get(key));
sessions.add(s);
}
}
return sessions;
}
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
this.saveSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
if(sessionId == null) {
logger.error("session id is null");
return null;
}
Session s = (Session) SerializeUtils.deserialize(redisManager.get(this.getByteKey(sessionId)));
return s;
}
/**
* 獲得byte[]型的key
*
* @param sessionId
*/
private byte[] getByteKey(Serializable sessionId) {
String preKey = this.keyPrefix + sessionId;
return preKey.getBytes();
}
public RedisManager getRedisManager() {
return redisManager;
}
public void setRedisManager(RedisManager redisManager) {
this.redisManager = redisManager;
this.redisManager.init();
}
/**
* Returns the Redis session keys prefix.
*
* @return The prefix
*/
public String getKeyPrefix() {
return keyPrefix;
}
/**
* Sets the Redis sessions key prefix.
*
* @param keyPrefix The prefix
*/
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
}
ini 配置代碼
sessionDAO = com.xxx.xxx.RedisSessionDAO
securityManager.sessionManager.sessionDAO = $sessionDAO