在互联网时代,系统用户会话管理的设计在一定程度反映系统可伸缩性,如果系统的会话支持无限扩展那么不单可以减轻系统的负担而且可以给用户更快,更好的体验。jeecms v5的会话管理采用会话缓存的方式。方便jeecms v5的会话的扩展。jeecms v5中会话管理可以采用的缓存ehcache,memcache,spymemcache等分布式缓存。
在jeecms中对回话进行Cache和Session的封装以满足分布式情况下的使用。具体代码如下: package com.jeecms.common.web.session; import java.io.Serializable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Session提供者 */ public interface SessionProvider { public Serializable getAttribute(HttpServletRequest request, String name); public void setAttribute(HttpServletRequest request, HttpServletResponse response, String name, Serializable value); public String getSessionId(HttpServletRequest request, HttpServletResponse response); public void logout(HttpServletRequest request, HttpServletResponse response); } package com.jeecms.common.web.session; import java.io.Serializable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * HttpSession提供类 */ public class HttpSessionProvider implements SessionProvider { public Serializable getAttribute(HttpServletRequest request, String name) { HttpSession session = request.getSession(false); if (session != null) { return (Serializable) session.getAttribute(name); } else { return null; } } public void setAttribute(HttpServletRequest request, HttpServletResponse response, String name, Serializable value) { HttpSession session = request.getSession(); session.setAttribute(name, value); } public String getSessionId(HttpServletRequest request, HttpServletResponse response) { return request.getSession().getId(); } public void logout(HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); } } } package com.jeecms.common.web.session; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import com.jeecms.common.web.Constants; import com.jeecms.common.web.RequestUtils; import com.jeecms.common.web.session.cache.SessionCache; import com.jeecms.common.web.session.id.SessionIdGenerator; /** * 使用Memcached分布式缓存实现Session */ public class CacheSessionProvider implements SessionProvider, InitializingBean { public static final String CURRENT_SESSION = "_current_session"; public static final String CURRENT_SESSION_ID = "_current_session_id"; @SuppressWarnings("unchecked") public Serializable getAttribute(HttpServletRequest request, String name) { // 为了避免同一个请求多次获取缓存session,所以将缓存session保存至request中。 Map<String, Serializable> session = (Map<String, Serializable>) request .getAttribute(CURRENT_SESSION); if (session != null) { return session.get(name); } String root = (String) request.getAttribute(CURRENT_SESSION_ID); if (root == null) { root = RequestUtils.getRequestedSessionId(request); } if (StringUtils.isBlank(root)) { request.setAttribute(CURRENT_SESSION, new HashMap<String, Serializable>()); return null; } session = sessionCache.getSession(root); if (session != null) { request.setAttribute(CURRENT_SESSION_ID, root); request.setAttribute(CURRENT_SESSION, session); return session.get(name); } else { return null; } } @SuppressWarnings("unchecked") public void setAttribute(HttpServletRequest request, HttpServletResponse response, String name, Serializable value) { Map<String, Serializable> session = (Map<String, Serializable>) request .getAttribute(CURRENT_SESSION); String root; if (session == null) { root = RequestUtils.getRequestedSessionId(request); if (root != null && root.length() == 32) { session = sessionCache.getSession(root); } if (session == null) { session = new HashMap<String, Serializable>(); do { root = sessionIdGenerator.get(); } while (sessionCache.exist(root)); response.addCookie(createCookie(request, root)); } request.setAttribute(CURRENT_SESSION, session); request.setAttribute(CURRENT_SESSION_ID, root); } else { root = (String) request.getAttribute(CURRENT_SESSION_ID); if (root == null) { do { root = sessionIdGenerator.get(); } while (sessionCache.exist(root)); response.addCookie(createCookie(request, root)); request.setAttribute(CURRENT_SESSION_ID, root); } } session.put(name, value); sessionCache.setSession(root, session, sessionTimeout); } public String getSessionId(HttpServletRequest request, HttpServletResponse response) { String root = (String) request.getAttribute(CURRENT_SESSION_ID); if (root != null) { return root; } root = RequestUtils.getRequestedSessionId(request); if (root == null || root.length() != 32 || !sessionCache.exist(root)) { do { root = sessionIdGenerator.get(); } while (sessionCache.exist(root)); sessionCache.setSession(root, new HashMap<String, Serializable>(), sessionTimeout); response.addCookie(createCookie(request, root)); } request.setAttribute(CURRENT_SESSION_ID, root); return root; } public void logout(HttpServletRequest request, HttpServletResponse response) { request.removeAttribute(CURRENT_SESSION); request.removeAttribute(CURRENT_SESSION_ID); String root = RequestUtils.getRequestedSessionId(request); if (!StringUtils.isBlank(root)) { sessionCache.clear(root); Cookie cookie = createCookie(request, null); cookie.setMaxAge(0); response.addCookie(cookie); } } private Cookie createCookie(HttpServletRequest request, String value) { Cookie cookie = new Cookie(Constants.JSESSION_COOKIE, value); String ctx = request.getContextPath(); cookie.setPath(StringUtils.isBlank(ctx) ? "/" : ctx); return cookie; } public void afterPropertiesSet() throws Exception { Assert.notNull(sessionCache); Assert.notNull(sessionIdGenerator); } private SessionCache sessionCache; private SessionIdGenerator sessionIdGenerator; private int sessionTimeout = 30; public void setSessionCache(SessionCache sessionCache) { this.sessionCache = sessionCache; } /** * 设置session过期时间 * * @param sessionTimeout * 分钟 */ public void setSessionTimeout(int sessionTimeout) { Assert.isTrue(sessionTimeout > 0); this.sessionTimeout = sessionTimeout; } public void setSessionIdGenerator(SessionIdGenerator sessionIdGenerator) { this.sessionIdGenerator = sessionIdGenerator; } } package com.jeecms.common.web.session.cache; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; public class EhcacheSessionCache implements SessionCache, InitializingBean { @SuppressWarnings("unchecked") public Map<String, Serializable> getSession(String root) { Element e = cache.get(root); return e != null ? (HashMap<String, Serializable>) e.getValue() : null; } public void setSession(String root, Map<String, Serializable> session, int exp) { cache.put(new Element(root, session)); } public Serializable getAttribute(String root, String name) { Map<String, Serializable> session = getSession(root); return session != null ? session.get(name) : null; } public void setAttribute(String root, String name, Serializable value, int exp) { Map<String, Serializable> session = getSession(root); if (session == null) { session = new HashMap<String, Serializable>(); } session.put(name, value); cache.put(new Element(root, session)); } public void clear(String root) { cache.remove(root); } public boolean exist(String root) { return cache.isKeyInCache(root); } public void afterPropertiesSet() throws Exception { Assert.notNull(cache); } private Ehcache cache; public void setCache(Ehcache cache) { this.cache = cache; } } package com.jeecms.common.web.session.cache; import java.io.Serializable; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.InitializingBean; import com.danga.MemCached.MemCachedClient; import com.danga.MemCached.SockIOPool; public class MemcachedDangaCache implements SessionCache, InitializingBean { private MemCachedClient client; private String[] servers; private Integer[] weights; @SuppressWarnings("unchecked") public HashMap<String, Serializable> getSession(String root) { return (HashMap<String, Serializable>) client.get(root); } public void setSession(String root, Map<String, Serializable> session, int exp) { client.set(root, session, new Date(System.currentTimeMillis() + exp * 60 * 1000)); } public Serializable getAttribute(String root, String name) { HashMap<String, Serializable> session = getSession(root); return session != null ? session.get(name) : null; } public void setAttribute(String root, String name, Serializable value, int exp) { HashMap<String, Serializable> session = getSession(root); if (session == null) { session = new HashMap<String, Serializable>(); } session.put(name, value); Date expDate = new Date(System.currentTimeMillis() + exp * 60 * 1000); client.set(root, session, expDate); } public void clear(String root) { client.delete(root); } public boolean exist(String root) { return client.keyExists(root); } public void afterPropertiesSet() throws Exception { client = new MemCachedClient(); // grab an instance of our connection pool SockIOPool pool = SockIOPool.getInstance(); // set the servers and the weights pool.setServers(servers); pool.setWeights(weights); // set some basic pool settings // 5 initial, 5 min, and 250 max conns // and set the max idle time for a conn // to 6 hours pool.setInitConn(5); pool.setMinConn(5); pool.setMaxConn(250); pool.setMaxIdle(1000 * 60 * 60 * 6); // set the sleep for the maint thread // it will wake up every x seconds and // maintain the pool size pool.setMaintSleep(30); // set some TCP settings // disable nagle // set the read timeout to 3 secs // and don't set a connect timeout pool.setNagle(false); pool.setSocketTO(3000); pool.setSocketConnectTO(0); // initialize the connection pool pool.initialize(); // lets set some compression on for the client // compress anything larger than 64k client.setCompressEnable(true); client.setCompressThreshold(64 * 1024); } public String[] getServers() { return servers; } public void setServers(String[] servers) { this.servers = servers; } public Integer[] getWeights() { return weights; } public void setWeights(Integer[] weights) { this.weights = weights; } } package com.jeecms.common.web.session.cache; import java.io.Serializable; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.spy.memcached.MemcachedClient; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; public class MemcachedSpyCache implements SessionCache, InitializingBean, DisposableBean { private MemcachedClient client; private String[] servers; private Integer[] weights; @SuppressWarnings("unchecked") public HashMap<String, Serializable> getSession(String root) { return (HashMap<String, Serializable>) client.get(root); } public void setSession(String root, Map<String, Serializable> session, int exp) { client.set(root, exp * 60, session); } public Serializable getAttribute(String root, String name) { HashMap<String, Serializable> session = getSession(root); return session != null ? session.get(name) : null; } public void setAttribute(String root, String name, Serializable value, int exp) { HashMap<String, Serializable> session = getSession(root); if (session == null) { session = new HashMap<String, Serializable>(); } session.put(name, value); client.set(root, exp * 60, session); } public void clear(String root) { client.delete(root); } public boolean exist(String root) { return client.get(root) != null; } public void afterPropertiesSet() throws Exception { List<InetSocketAddress> addr = new ArrayList<InetSocketAddress>( servers.length); int index; for (String s : servers) { index = s.indexOf(":"); addr.add(new InetSocketAddress(s.substring(0, index), Integer .parseInt(s.substring(index + 1)))); } client = new MemcachedClient(addr); } public void destroy() throws Exception { client.shutdown(); } public String[] getServers() { return servers; } public void setServers(String[] servers) { this.servers = servers; } public Integer[] getWeights() { return weights; } public void setWeights(Integer[] weights) { this.weights = weights; } } package com.jeecms.common.web.session.cache; import java.io.Serializable; import java.util.Map; public interface SessionCache { public Serializable getAttribute(String root, String name); public void setAttribute(String root, String name, Serializable value, int exp); public void clear(String root); public boolean exist(String root); public Map<String, Serializable> getSession(String root); public void setSession(String root, Map<String, Serializable> session, int exp); }