基于Redis实现分布式Session

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);
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2969659135793040d83002df56c42feb.html