memcache缓存共享session实现

一、session共享问题介绍

    session主要用于服务端存储用户会话信息,cookie用于浏览器存储用户会话信息。单系统服务session都存在同一个web容器中,例如tomcat中,用户请求都只访问这个容器中的session信息,除非容器挂了,否者不存在session取不到的情况。随着业务的扩展,应用用户的增加,当个容器存放系统应用消耗服务的cup和内存会不断增加,导致应用性能下降。此时考虑用nginx集群做应用的负载均衡请求分发,假设用ngnix集群三个服务,分别用A、B、C表示。按照未做session共享,仍然使用Servlet中HttpSession情景,假设此时访问的是A服务,那么session将存储在A服务中,此处如果A服务宕机,ngnix会将用户的请求分发到B或者C服务,但是B和C服务中没有存A存放的Session信息,那么用户访问的数据将会丢失。为了解决session数据丢失,需要将session共享,主流做法是将session存储在nosql数据库中,例如memcache、redis等。也有很多人通过spring session 实现共享,原理大致一样,下面主要实现了memcache缓存session共享。

二、核心代码:

1、ShareSession.java 

package com.gccode.sso.session;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.gccode.sso.cache.BaseCache;
import com.gccode.sso.common.CookieUtils;

/**
 * Title: 缓存共享session实现类
 *
 */
public class ShareSession {
	
	/**
	 * 存到缓存中的共享session容器
	 */
	private Map<String,Object> sessionWrapper;
	
	/**
	 * session对象
	 */
	private static ShareSession session;
	
	/**
	 * 浏览器请求回话id
	 */
	private String sessionId;
	
	/**
	 * 缓存
	 */
    private BaseCache cache;
    
    /**
     * 构造函数初始化参数
     * @param request
     */
	public ShareSession(HttpServletRequest request){
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
		this.cache = (BaseCache) wac.getBean("cache");
		this.sessionId =  CookieUtils.getCookieId(request);
		this.sessionWrapper = new HashMap<String, Object>();
	}
	
	/**
	 * 获取session对象
	 * @param request
	 * @return
	 */
	public static synchronized ShareSession get(HttpServletRequest request){
		if(session == null){
			session = new ShareSession(request);
		}
		return session;
	}

	/**
	 * 设置session,带超时时间
	 * @param key
	 * @param value
	 * @param outTime
	 * @return sessionId
	 */
	public String setSession(String key,Object value,int outTime) {
		sessionWrapper.put(key, value);
		cache.put(sessionId,sessionWrapper,outTime);
		return sessionId;
	}
	
	/**
	 * 设置session
	 * @param key
	 * @param value
	 * @return
	 */
	public String setSession(String key,Object value) {
		sessionWrapper.put(key, value);
		cache.put(sessionId, sessionWrapper);
		return sessionId;
	}

	/**
	 * 设置session,不带超时时间
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public  Map<String, Object> getSession() {
		return (Map<String, Object>)cache.get(sessionId);
	}

	/**
	 * 删除session中的值
	 * @param key
	 */
	public void removeSession(String key) {
		Map<String,Object> session = getSession();
		session.remove(key);
		cache.put(sessionId,session);
	}

}

2、ShareSessionIntercept.java

package com.gccode.sso.session;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.gccode.sso.cache.BaseCache;
import com.gccode.sso.common.CookieUtils;

/**
 * Title: 缓存共享session实现类
 *
 */
public class ShareSession {
	
	/**
	 * 存到缓存中的共享session容器
	 */
	private Map<String,Object> sessionWrapper;
	
	/**
	 * session对象
	 */
	private static ShareSession session;
	
	/**
	 * 浏览器请求回话id
	 */
	private String sessionId;
	
	/**
	 * 缓存
	 */
    private BaseCache cache;
    
    /**
     * 构造函数初始计划参数
     * @param request
     */
	public ShareSession(HttpServletRequest request){
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
		this.cache = (BaseCache) wac.getBean("cache");
		this.sessionId =  CookieUtils.getCookieId(request);
		this.sessionWrapper = new HashMap<String, Object>();
	}
	
	/**
	 * 获取session对象
	 * @param request
	 * @return
	 */
	public static synchronized ShareSession get(HttpServletRequest request){
		if(session == null){
			session = new ShareSession(request);
		}
		return session;
	}

	/**
	 * 设置session,带超时时间
	 * @param key
	 * @param value
	 * @param outTime
	 * @return sessionId
	 */
	public String setSession(String key,Object value,int outTime) {
		sessionWrapper.put(key, value);
		cache.put(sessionId,sessionWrapper,outTime);
		return sessionId;
	}
	
	/**
	 * 设置session
	 * @param key
	 * @param value
	 * @return
	 */
	public String setSession(String key,Object value) {
		sessionWrapper.put(key, value);
		cache.put(sessionId, sessionWrapper);
		return sessionId;
	}

	/**
	 * 设置session,不带超时时间
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public  Map<String, Object> getSession() {
		return (Map<String, Object>)cache.get(sessionId);
	}

	/**
	 * 删除session中的值
	 * @param key
	 */
	public void removeSession(String key) {
		Map<String,Object> session = getSession();
		session.remove(key);
		cache.put(sessionId,session);
	}

}

3、SSOUserFilter.java

package com.gccode.sso.session;

import java.io.IOException;
import java.util.Map;

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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.Cache;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.gccode.sso.common.Constant;
import com.gccode.sso.common.CookieUtils;


/**
 * Title: 用户请求过滤
 *
 */
public class SSOUserFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
		String sessionId = CookieUtils.getCookieId(request);
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(req.getServletContext());
		Cache cache = (Cache) wac.getBean("cache");
		if (StringUtils.isEmpty(sessionId) || null == cache.get(sessionId)) {
			request.getRequestDispatcher("/logout.html").forward(request,
					response);
		} else {
			@SuppressWarnings("unchecked")
			Map<String, Object> session = (Map<String, Object>) cache.get(
					sessionId).get();
			if (session.get(Constant.SESSION_USER_KEY) == null) {
				request.getRequestDispatcher("/logout.html").forward(request,
						response);
			} else {
				chain.doFilter(req, res);
			}
		}
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值