如今集群环境已是服务器主流,在集群环境中,session共享一般通过应用服务器的session复制或者存储在公用的缓存服务器上,本文主要介绍通过Shiro管理session,并将session缓存到redis集群版中,这样可以在集群中使用。
Shiro除了在管理session上使用redis,也在可以缓存用户权限,即cacheManager可以通过redis来扩展。
下面从 sessionManager这部分讲解Shiro与Redis的集成,
先看下配置问件:
/cityparlor/cityparlor/**=anon
/cityparlor/**=authc
/common/**=anon
/cityparlor/cityparlor/**=anon
/cityparlor/**=authc /common/**=anon
shiro框架中有一个对session配置管理对象:sessionManager对象,对象中可注入对象参数:sessionDAO,源码如下:
此SessionDao中封装内容如下:
不难发现,里面封装的就是对session的增删改查,因此我们只需对sessionDao进行自己的继承,实现类即可;
自己封装代码如下:
package com.cityparlor.web.admin.realm;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.cityparlor.common.utils.JedisUtils;
public class RedisSessionDAO extends AbstractSessionDAO{
private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
/*private JedisUtils redisManager;*/
private String keyPrefix;
private int expire = 0;
public RedisSessionDAO() {
this.keyPrefix = "shiro_redis_session:";
}
@Override
public void update(Session session) throws UnknownSessionException {
// TODO Auto-generated method stub
this.saveSession(session);
}
/**
* 获取序列化字节id
* TODO
* @param sessionId
* @return
* ============History===========
* 2017年7月17日 LHL 新建
*/
/*
private byte[] getByteKey(Serializable sessionId) {
String preKey = this.keyPrefix + sessionId;
return preKey.getBytes();
}
*/
private String getKey(Serializable sessionId) {
String preKey = this.keyPrefix + sessionId;
return preKey;
}
private void saveSession(Session session) throws UnknownSessionException {
if ((session == null) || (session.getId() == null)) {
logger.error("session or session id is null");
return;
}
String key = getKey(session.getId());
/*byte[] value = SerializeUtils.serialize(session);*/
session.setTimeout(expire * 1000);
JedisUtils.setObject(key, session, this.expire);//this.redisManager.set(key, value, this.redisManager.getExpire());
}
@Override
public void delete(Session session) {
if ((session == null) || (session.getId() == null)) {
logger.error("session or session id is null");
return;
}
JedisUtils.delObject(getKey(session.getId()));//this.redisManager.del(getByteKey(session.getId()));
}
@Override
public Collection getActiveSessions() {
// TODO Auto-generated method stub
Set sessions = new HashSet();
Set keys = JedisUtils.keys(this.keyPrefix + "*");
if ((keys != null) && (keys.size() > 0)) {
for (String key : keys) {
Session s = (Session) JedisUtils.getObject(key);// (Session) SerializeUtils.deserialize(this.redisManager.get(key));
sessions.add(s);
}
}
return sessions;
}
@Override
protected Serializable doCreate(Session session) {
// TODO Auto-generated method stub
Serializable sessionId = generateSessionId(session);
assignSessionId(session, sessionId);
saveSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
// TODO Auto-generated method stub
if (sessionId == null) {
logger.error("session id is null");
return null;
}
Session s =(Session) JedisUtils.getObject(getKey(sessionId)) ;// SerializeUtils.deserialize(this.redisManager.get(getByteKey(sessionId)));
return s;
}
}
这里我们只是将session的增删改查换成了用redis的增删改查;
redis链接工具类代码如下:
/**
*
*/
package com.cityparlor.common.utils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.cityparlor.common.config.Global;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
/**
* Jedis Cache 工具类
*
* @author Administrator
* @version 2015-09-29
*/
public class JedisUtils {
private static Logger logger = LoggerFactory.getLogger(JedisUtils.class);
private static JedisCluster jedisCluster = SpringContextHolder.getBean(JedisCluster.class);
//private static JedisPool jedisPool = SpringContextHolder.getBean(JedisPool.class);
public static final String KEY_PREFIX = Global.getConfig("redis.keyPrefix");
/**
* 利用redis 生成自