Memcached保存sessionId
1、把sessionId存放在cookie中,并设定一个有效期;
2、把经过Serializable序列化的对象存放在memcached中,同时设置一个失效时间,比如1小时;
3、每次取会话信息时,先从cookie中取sessionId,如果cookie不存在,则说明会话已过期;如果会话存在,则从memcached中读取会话信息,如果会话信息不存在,则从数据库中读取相关信息,然后放在memcached中,同时设置失效时间;
4、设置一个filter,在每次请求时,更新会话cookie的失效时间;
5、登录时设置一个隐藏的随机数;
6、退出时删除会话cookie,同时从memcached中删除相关的会话;
代码如下:
RequestUtils.java
package com.util;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*对cookie读写
*/
public class RequestUtils
{
public static String cookieDomain = "";
public static String cookiePath = "/";
/**
* 获取COOKIE
* @param request
* @param name
*/
public static Cookie getCookie(HttpServletRequest request, String name) {
Cookie[] cookies = request.getCookies();
if(cookies == null)
return null;
for (int i = 0; i < cookies.length; i++) {
if (name.equals(cookies[i].getName())) {
return cookies[i];
}
}
return null;
}
/**
* 设置COOKIE
* @param request
* @param response
* @param name
* @param value
* @param maxAge
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String name,
String value, int maxAge)
{
Cookie cookie = new Cookie(name, value);
cookie.setMaxAge(maxAge);
if(cookieDomain!=null && cookieDomain.indexOf('.')!=-1){
cookie.setDomain('.' + cookieDomain);
}
cookie.setPath(cookiePath);
response.addCookie(cookie);
}
}
//
SessionCookieFilter.java
package com.mem.session;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.RequestUtils;
/**
*对每次动态页面的请求时,更新会话cookie的有效期
*/
public class SessionCookieFilter extends HttpServlet implements Filter
{
/**
*
*/
private static final long serialVersionUID = -6516046520244652987L;
private String sessionId = "sid";
private int expiryDate = 30*60;//seconeds
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
Cookie cookie = RequestUtils.getCookie(request, sessionId);
if (cookie != null)
{
String sid = cookie.getValue();
//设置cookie的有效期
RequestUtils.setCookie(request, response, sessionId, sid, expiryDate);
}
filterChain.doFilter(request,response);
}
public void init(FilterConfig filterConfig) throws ServletException
{
this.sessionId = filterConfig.getInitParameter("sessionId");
com.util.RequestUtils.cookieDomain = filterConfig.getInitParameter("cookieDomain");
if (com.util.RequestUtils.cookieDomain == null)
{
com.util.RequestUtils.cookieDomain = "";
}
com.util.RequestUtils.cookiePath = filterConfig.getInitParameter("cookiePath");
if (com.util.RequestUtils.cookiePath == null || com.util.RequestUtils.cookiePath.length() == 0)
{
com.util.RequestUtils.cookiePath = "/";
}
}
}
//
SessionService.java
package com.mem.session;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Calendar;
import java.util.Date;
import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;
/**
*对memcached的操作
*/
public class SessionService {
private static SessionService instance = null;
private SockIOPool pool = null;
private String poolName = "sidsock";
private int expiryTime = 60;//minutes
private Date getExpiryDate()
{
Calendar calendar = Calendar.getInstance();
long time = calendar.getTimeInMillis();
time += expiryTime * 60 * 1000;
calendar.setTimeInMillis(time);
return calendar.getTime();
}
public static synchronized SessionService getInstance() {
if (instance == null) {
instance = new SessionService();
}
return instance;
}
private SessionService() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream input = cl.getResourceAsStream("memcached.properties");
Properties props = new Properties();
String serverlist = "127.0.0.1:11211";
try {
props.load(input);
serverlist = props.getProperty("serverlist", "127.0.0.1:11211");
poolName = props.getProperty("poolname", "sidsock");
} catch (Exception e) {
e.printStackTrace();
}
String[] servers = serverlist.split(",");
pool = SockIOPool.getInstance(poolName);
pool.setServers(servers);
pool.setFailover(true);
pool.setInitConn(10);
pool.setMinConn(5);
pool.setMaxConn(250);
pool.setMaintSleep(30);
pool.setNagle(false);
pool.setSocketTO(3000);
pool.setAliveCheck(true);
pool.initialize();
}
public boolean sessionExists(String id)
{
MemCachedClient mc = this.getMemCachedClient();
return mc.keyExists(id);
}
public Map getSession(String id,boolean create)
{
MemCachedClient mc = this.getMemCachedClient();
Map session = (Map) mc.get(id);
if(session == null)
{
if(create)
{
session = new HashMap(5);
mc.add(id, session,getExpiryDate());
}
}
return session;
}
public void saveSession(String id, Map session)
{
MemCachedClient mc = this.getMemCachedClient();
if(mc.keyExists(id))
{
mc.replace(id, session);
}
else
{
mc.add(id, session);
}
}
public void saveSession(String id, Map session,Date expiryDate)
{
MemCachedClient mc = this.getMemCachedClient();
if(mc.keyExists(id))
{
mc.replace(id, session,expiryDate);
}
else
{
mc.add(id, session,expiryDate);
}
}
public void removeSession(String id)
{
MemCachedClient mc = this.getMemCachedClient();
mc.delete(id);
}
public void updateExpiryDate(String id)
{
MemCachedClient mc = this.getMemCachedClient();
Map session = (Map) mc.get(id);
if(session != null)
{
mc.replace(id, session,getExpiryDate());
}
}
private MemCachedClient getMemCachedClient()
{
MemCachedClient mc = new MemCachedClient();
mc.setPoolName(poolName);
mc.setCompressEnable(false);
mc.setCompressThreshold(0);
return mc;
}
protected void finalize()
{
if (this.pool != null)
{
this.pool.shutDown();
}
}
}
//
MemSession.java
package com.mem.session;
import java.util.Map;
/**
*对会话的操作
*/
public class MemSession
{
//会话ID
private String sid = "";
//存放本会话的所有信息
private Map map = null;
public static MemSession getSession(String sid)
{
MemSession session = null;
session = new MemSession(sid,true);
return session;
}
public static MemSession getSession(String sid,boolean create)
{
MemSession session = null;
session = new MemSession(sid,create);
return session;
}
private MemSession(String sid,boolean create)
{
this.sid = sid;
this.map = SessionService.getInstance().getSession(sid,create);
}
public static boolean sessionExists(String sid)
{
return SessionService.getInstance().sessionExists(sid);
}
public Object getAttribute(String arg0)
{
return this.map.get(arg0);
}
public void invalidate()
{
this.map.clear();
SessionService.getInstance().removeSession(this.sid);
}
public void removeAttribute(String arg0)
{
if(arg0 == null || arg0.trim().length() <= 0)
{
return;
}
this.map.remove(arg0);
SessionService.getInstance().saveSession(this.sid, this.map);
}
public void setAttribute(String arg0, Object arg1)
{
if(arg0 == null || arg0.trim().length() <= 0 || arg1 == null)
{
return ;
}
this.map.put(arg0, arg1);
SessionService.getInstance().saveSession(this.sid, this.map);
}
public void updateExpiryDate(String sid)
{
SessionService.getInstance().updateExpiryDate(sid);
}
}
//SessionUtil.java
package com.mem.session;
import java.io.Serializable;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.util.RequestUtils;
import com.mem.session.MemSession;
public class SessionUtil
{
public static UserInfo getUserInfo(HttpServletRequest request)
{
Cookie cookie = RequestUtils.getCookie(request, "sid");
if(cookie != null)
{
String sid = cookie.getValue();
MemSession session = MemSession.getSession(sid);
UserInfo userInfo = (UserInfo)session.getAttribute("user_session_flag");
if(userInfo == null)
{
//缓存中已经不存在,则要从数据库中读取,同时存放在缓存中
userInfo = new UserInfo("hpt321",1,"hpt321");//要从数据库中读取
session.setAttribute("user_session_flag", userInfo);
return userInfo;
}
}
return null;
}
public static void setUserInfo(UserInfo userInfo,HttpServletRequest request,HttpServletResponse response)
{
setAttribute(request, "user_session_flag", userInfo);
}
/**
* 登录返回true;未登录返回false;
* @param request
* @return
*/
public static boolean valideLogin(HttpServletRequest request)
{
Cookie cookie = RequestUtils.getCookie(request, "sid");
if(cookie == null)
{
return false;
}
else
{
return true;
}
}
public static void setAttribute(String sid,String key,Object value)
{
//把置放入缓存中
MemSession session = MemSession.getSession(sid);
session.setAttribute(key, value);
}
public static void setAttribute(HttpServletRequest request,String key,Object value)
{
Cookie cookie = RequestUtils.getCookie(request, "sid");
if(cookie != null)
{
// 取出session的ID
String sid = cookie.getValue();
//把置放入缓存中
MemSession session = MemSession.getSession(sid);
session.setAttribute(key, value);
}
}
public static Object getAttribute(String sid,String key)
{
//把置放入缓存中
MemSession session = MemSession.getSession(sid);
return session.getAttribute(key);
}
public static Object getAttribute(HttpServletRequest request,String key)
{
Cookie cookie = RequestUtils.getCookie(request, "sid");
if(cookie != null)
{
//取出session的ID
String sid = cookie.getValue();
//把置放入缓存中
MemSession session = MemSession.getSession(sid);
return session.getAttribute(key);
}
return null;
}
public static void removeAttribute(HttpServletRequest request,String key)
{
Cookie cookie = RequestUtils.getCookie(request, "sid");
if(cookie != null)
{
//取出session的ID
String sid = cookie.getValue();
//把置放入缓存中
MemSession session = MemSession.getSession(sid);
session.removeAttribute(key);
}
}
public static void invalidate(HttpServletRequest request)
{
Cookie cookie = RequestUtils.getCookie(request, "sid");
if(cookie != null)
{
//取出session的ID
String sid = cookie.getValue();
//把置放入缓存中
MemSession session = MemSession.getSession(sid);
session.invalidate();
}
}
}
//
登录
synchronized(信号量)
{
//验证隐藏的验证码,同时删除随机验证码,避免重复登录
}
//1、此处先得到cookie中已有的会话ID,以便登录后清除memached中的会话信息;
//2、清除前一个登录的会话信息
String sid = java.util.UUID.randomUUID().toString()+serverName+"_"+userId;
//加入serverName,是为了区分多台服务器产生的randomUUID可能相同
com.util.RequestUtils.setCookie(request, response, "sid", sid, 30*60);
com.mem.session.SessionUtil.setAttribute(sid, "user_session_flag", userInfo);
//退出
删除会话cookie同时删除memcached中的会话信息
com.mem.session.SessionUtil.invalidate(request);