浏览 4585 次
精华帖 (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<String, Object> getAttributesInternal() { return this.data; } void setAttributesInternal( final Map<String, Object> 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<String, Object> 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); 即可解决。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2014-06-16
不错不错,思路清晰
|
|
返回顶楼 | |