论坛首页 Java企业应用论坛

让 memcached-session-filter 摆脱 spring 和 Java 序列化接口

浏览 4551 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2014-06-09  

memcached-session-filter 项目是在 java 服务器(例如:tomcat)集群的情况下,通过 filter 实现 session 共享。
项目地址:http://code.google.com/p/memcached-session-filter/

非常棒的东东,但是需要在 spring 下使用,而且 session 中的对象必须实现 java 序列化接口。
刚好现有的项目中不幸被以上两点限制了,只能自己动手修改一下。

首先有三点小的调整和修复了一个小的问题:
1、原有 memcached 的 java 客户端使用的 xmemcached 修改为 spymemcached 。
2、对于 commons-lang 包,作者只使用了 StringUtils.isEmpty 的方法,所以也被替换掉了。
3、将日志组件从 log4j 改为 slf4j 。

小问题放在后面说。

一、摆脱 spring
涉及 MemcachedSessionManager 和 MemcachedSessionFilter 两个类。
MemcachedSessionManager 类:
<pre name="code" class="java">
    // 此接口在 filter 中设置 memcachedClient 对象
    public void setMemcachedClient(MemcachedClient memcachedClient) {
        this.memcachedClient = memcachedClient;
    }
    // 此接口在 filter 中设置 session 过期时间
    public void setMaxInactiveInterval(int maxInactiveInterval) {
        this.maxInactiveInterval = maxInactiveInterval;
    }
</pre>
MemcachedSessionFilter 类:
<pre name="code" class="java">
    public void init(FilterConfig filterConfig) throws ServletException {
    // 创建 sessionManager
    sessionManager = new MemcachedSessionManager();
    // 解析配置参数,设置 session 过期时间
    String maxInactiveInterval = filterConfig.getInitParameter("maxInactiveInterval");
    if(maxInactiveInterval != null) {
    try {
    int i = Integer.valueOf(maxInactiveInterval);
    sessionManager.setMaxInactiveInterval(i*60);
    } catch(Exception e) {
    e.printStackTrace();
    }
    }
// 设置 memcached 服务节点
    String memcachedNodes = filterConfig.getInitParameter("memcachedNodes");
    if(memcachedNodes != null) {
    this.memcachedNodes = memcachedNodes;
    }
    try {
        MemcachedClient client = new MemcachedClient(AddrUtil.getAddresses(this.memcachedNodes));
    sessionManager.setMemcachedClient(client);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
</pre>

二、摆脱 java 序列化接口
序列化使用了javolution 包,项目地址:http://www.javolution.org/
主要参考了 memcached-session-manager 的序列化的实现,项目地址:http://code.google.com/p/memcached-session-manager
代码比较多,以下主要说一下思路和主要修改的 java 文件。

MemcachedHttpSession 类:增加新的方法,用于操作 session 内部的 Map 数据
<pre name="code" class="java">
    public Map&lt;String, Object&gt; getAttributesInternal() {
        return this.data;
    }
   
    void setAttributesInternal( final Map&lt;String, Object&gt; attributes ) {
        this.data = attributes;
    }
</pre>

TranscoderService 类:序列化 session 对象
<pre name="code" class="java">
    // 需要根据 MemcachedHttpSession 的结构进行相应的修改
    static final int NUM_BYTES = 8 // creationTime: long
            + 8 // lastAccessedTime: long
            + 4 // maxInactiveInterval: int
            + 0; // isNew: boolean
</pre>

【注】serializeSessionFields 和 deserializeSessionFields 等方法也要相应调整。

JavolutionTranscoder 类:该类实现了 spymemcached 的 SerializingTranscoder 用于取出 session 对象时反序列化操作;另外,负责对象和 XML 之间的相互转化


MemcachedSessionManager 类:
<pre name="code" class="java">
    private SerializingTranscoder upgradeSupportTranscoder = new JavolutionTranscoder();
    private TranscoderService transcoderService = new TranscoderService(new JavolutionTranscoder());
    // 过期删除
            if(session.expired) {
                memcachedClient.delete(generatorSessionKey(session.id));
            } else {
            try {
                final Map&lt;String, Object&gt; attributes = session.getAttributesInternal();
    // 序列化
                final byte[] attributesData = transcoderService.serializeAttributes( session, attributes );
                final byte[] data = transcoderService.serialize( session, attributesData );
    // 保存 session 到 memcached
                    memcachedClient.set(generatorSessionKey(session.id), session.maxInactiveInterval+expirationUpdateInterval, data);
            } catch(Exception e) {
                //
            }
            }
    ....
    // 从 memcached 取得 session 对象,并且对它反序列化
    Object obj = memcachedClient.get(generatorSessionKey(sessionId), this.upgradeSupportTranscoder);
</pre>

【注】前面说的一个问题:
后面在使用的过程中,发现使用 绿色浏览器 时,session 无法保存到 memcached 中。
原因很简单,该组件通过 cookie 保存 session id ,在创建 cookie 时,未设置过期时间,所以通过 cookie.setMaxAge(maxInactiveInterval); 即可解决。





   发表时间:2014-06-16  
不错不错,思路清晰
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics