1、概述
我们可以自己实现类似Session的机制,采用 Redis 等分布式缓存中间件来实现。Redis是独立于应用服务器的,基于Redis实现的Session机制自动具备了分布式属性。Redis可以很方便地做集群配置,则Session避免了单点故障。
2、实现
实现代码极其简单,如下所示。
/**
* @author liuhailong2008#foxmail
*/
public class ApiSession implements Serializable {
private static final long serialVersionUID = 1055965810150154404L;
/**Session ID*/
private final String id;
/**Session创建时间*/
private long creationTime;
/**Session最后一次访问时间*/
private long lastAccessedTime;
/**Session的最大空闲时间间隔*/
private int maxInactiveInterval;
/**是否是新建Session*/
private boolean newSession;
private static final String SESSION_KEY_PREFIX = "SESS_";
//private Set<String> attrNameSet = Collections.synchronizedSet(new HashSet<String>());
private final String sessionKey ;
/**
* 创建新的Session。
* @param maxIdleSeconds
*/
public ApiSession(int maxIdleSeconds){
id = StringUtil.getUUID();
long now = System.currentTimeMillis();
creationTime = now;
lastAccessedTime = now;
this.maxInactiveInterval = maxIdleSeconds;
newSession = true;
//this.attrNameSet.clear();
sessionKey = SESSION_KEY_PREFIX + id;
CacheBlock cb = CacheManager.getBlock(Const.CACHE_BLOCK_INDEX);
CacheElement ce = new CacheElement(sessionKey,this);
ce.setTimeToIdleSeconds(this.getMaxInactiveInterval());
cb.put(ce);
}
/**
* 通过Session id获取已经存在的Session,如果没有,返回null。
* @return
*/
public static ApiSession get(String id){
String sessionKey = SESSION_KEY_PREFIX + id;
CacheBlock cb = CacheManager.getBlock(Const.CACHE_BLOCK_INDEX);
ApiSession ret = (ApiSession) cb.get(sessionKey);
if(ret!=null){
ret.newSession = false;
ret.refresh();
}
return ret;
}
/**
* 更新 lastAccessedTime 。
*/
public void refresh() {
this.lastAccessedTime = System.currentTimeMillis();
CacheBlock cb = CacheManager.getBlock(Const.CACHE_BLOCK_INDEX);
CacheElement ce = new CacheElement(sessionKey,this);
ce.setTimeToIdleSeconds(this.getMaxInactiveInterval());
cb.put(ce);
}
/**
* 是否超时过期。
*
* @param session
* @return
*/
public boolean isExpired() {
CacheBlock cb = CacheManager.getBlock(Const.CACHE_BLOCK_INDEX);
ApiSession _this = (ApiSession) cb.get(this.sessionKey);
// 先查看缓存层面的超时控制
if(_this==null){
return false;
}
long now = System.currentTimeMillis();
long last = this.getLastAccessedTime();
long interal = now - last;
if(interal>this.getMaxInactiveInterval()){
this.invalidate();
return true;
}else{
return false;
}
}
/**
* 强制Session立即失效。
*/
public synchronized void invalidate() {
CacheBlock cb = CacheManager.getBlock(Const.CACHE_BLOCK_INDEX);
cb.remove(this.sessionKey);
}