shiro实现基于redis的sessionDao
将session持久化到数据库的一个关键步骤是对session对象的序列化和反序列化操作,另外在使用redis保存session时一定要设置过期时间,或在编码中检查过期并及时删除缓存,否则会导致session堆积。
具体代码如下:
/**
* 自定义基于redis的session持久化dao
* @author ah
*/
public class RedisSessionDao extends CachingSessionDAO {
private RedisUtil redisUtil;
public RedisSessionDao(RedisUtil redisUtil) {
this.redisUtil = redisUtil;
}
/**
* 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
* @param session
*/
@Override
protected void doUpdate(Session session) {
if(session instanceof ValidatingSession && !((ValidatingSession)session).isValid()) {
return; //如果会话过期/停止 没必要再更新了
}
redisUtil.set(RC.key(RC.SEN, Arrays.toString(session.getId().toString().getBytes())), sessionToByte(session));
}
/**
* 删除会话;当会话过期/会话停止(如用户退出时)会调用
* @param session
*/
@Override
protected void doDelete(Session session) {
redisUtil.del(RC.key(RC.SEN, Arrays.toString(session.getId().toString().getBytes())));
}
/**
* DefaultSessionManager在创建完session后会调用该方法;保存到关系数据库/文件系统/NoSQL数据库;
* 即可以实现会话的持久化;返回会话ID;主要此处返回的ID.equals(session.getId());
* @param session
* @return
*/
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = generateSessionId(session);
assignSessionId(session, sessionId);
redisUtil.set(RC.key(RC.SEN, Arrays.toString(sessionId.toString().getBytes())), sessionToByte(session), session.getTimeout());
return session.getId();
}
/**
* 根据会话ID获取会话
* @param serializable
* @return
*/
@Override
protected Session doReadSession(Serializable serializable) {
Object obj = redisUtil.get(RC.key(RC.SEN, Arrays.toString(serializable.toString().getBytes())));
if (obj != null) {
byte[] sessionBytes = (byte[]) redisUtil.get(Arrays.toString(serializable.toString().getBytes()));
Session session = byteToSession(sessionBytes);
return session;
}
return null;
}
// 把session对象转化为byte保存到redis中
public byte[] sessionToByte(Session session){
ByteArrayOutputStream bo = new ByteArrayOutputStream();
byte[] bytes = null;
try {
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(session);
bytes = bo.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
// 把byte还原为session
public Session byteToSession(byte[] bytes){
ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
ObjectInputStream in;
SimpleSession session = null;
try {
in = new ObjectInputStream(bi);
session = (SimpleSession) in.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return session;
}
}