热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Redis实现分布式session功能的共享

最近项目设计集群,实现了一下session的共享功能,其原理是将session保存到分布式缓存数据库中如:redis,mem

最近项目设计集群,实现了一下session的共享功能,其原理是将session保存到分布式缓存数据库中如:redis, memcache等,然后多个服务器tomcat
每次请求都通过NoSql数据库查询,如果存在,则获取值;反之存放值。
我是通过redis来实现session的共享,其主要有一下两种方法:
1、通过tomcat服务器的拓展功能实现这种方式比较简单,主要是通过继承session的ManagerBase类,实现重写session相关的方法,这种比较简单,参考源码链接(http://download.csdn.net/detail/fengshizty/9417242)。
2、通过filter拦截request请求实现下面主要介绍这样实现方式:(1)写HttpSessionWrapper实现HttpSession接口,实现里面session相关的方法。(2)写HttpServletRequestWrapper继承javax.servlet.http.HttpServletRequestWrapper类,重写对于session 相关的方法。(3)写SessionFilter拦截配置的请求url,过去COOKIE中的sessionId,如果为空,对此次请求重写生成一个新的sessionId,在sessionId构造新的HttpServletRequestWrapper对象。(4)写SessionService实现session到redis的保存和过去,其key为sessionId,value为session对于的Map。
3、代码实现(1)HttpSessionWrapper

/*** 创建时间:2016年1月21日 下午7:55:41* * @author andy* @version 2.2*/public class HttpSessionWrapper implements HttpSession {private String sid = "";private HttpSession session;private HttpServletRequest request;private HttpServletResponse response;private Map map = null;private SessionService sessionService = (SessionService) SpringContextHolder.getBean("sessionService");public HttpSessionWrapper() {}public HttpSessionWrapper(HttpSession session) {this.session = session;}public HttpSessionWrapper(String sid, HttpSession session) {this(session);this.sid = sid;}public HttpSessionWrapper(String sid, HttpSession session,HttpServletRequest request, HttpServletResponse response) {this(sid, session);this.request = request;this.response = response;}private Map getSessionMap() {if (this.map == null) {this.map = sessionService.getSession(this.sid);}return this.map;}@Overridepublic Object getAttribute(String name) {if (this.getSessionMap() != null) {Object value = this.getSessionMap().get(name);return value;}return null;}@Overridepublic void setAttribute(String name, Object value) {this.getSessionMap().put(name, value);sessionService.saveSession(this.sid, this.getSessionMap());}@Overridepublic void invalidate() {this.getSessionMap().clear();sessionService.removeSession(this.sid);COOKIEUtil.removeCOOKIEValue(this.request,this.response, GlobalConstant.JSESSIONID);}@Overridepublic void removeAttribute(String name) {this.getSessionMap().remove(name);sessionService.saveSession(this.sid, this.getSessionMap()); }@Overridepublic Object getValue(String name) {return this.session.getValue(name);}@SuppressWarnings("unchecked")@Overridepublic Enumeration getAttributeNames() {return (new Enumerator(this.getSessionMap().keySet(), true));}@Overridepublic String[] getValueNames() {return this.session.getValueNames();}@Overridepublic void putValue(String name, Object value) {this.session.putValue(name, value);}@Overridepublic void removeValue(String name) {this.session.removeValue(name);}@Overridepublic long getCreationTime() {return this.session.getCreationTime();}@Overridepublic String getId() {return this.sid;}@Overridepublic long getLastAccessedTime() {return this.session.getLastAccessedTime();}@Overridepublic ServletContext getServletContext() {return this.session.getServletContext();}@Overridepublic void setMaxInactiveInterval(int interval) {this.session.setMaxInactiveInterval(interval);}@Overridepublic int getMaxInactiveInterval() {return this.session.getMaxInactiveInterval();}@Overridepublic HttpSessionContext getSessionContext() {return this.session.getSessionContext();}@Overridepublic boolean isNew() {return this.session.isNew();}}

(2)HttpServletRequestWrapper实现

/*** 创建时间:2016年1月22日 下午7:52:29* * @author andy* @version 2.2*/public class HttpServletRequestWrapper extendsjavax.servlet.http.HttpServletRequestWrapper {private HttpSession session;private HttpServletRequest request;private HttpServletResponse response;private String sid = "";public HttpServletRequestWrapper(HttpServletRequest request) {super(request);}public HttpServletRequestWrapper(String sid, HttpServletRequest request) {super(request);this.sid = sid;}public HttpServletRequestWrapper(String sid, HttpServletRequest request,HttpServletResponse response) {super(request);this.request = request;this.response = response;this.sid = sid;if (this.session == null) {this.session = new HttpSessionWrapper(sid, super.getSession(false),request, response);}}@Overridepublic HttpSession getSession(boolean create) {if (this.session == null) {if (create) {this.session = new HttpSessionWrapper(this.sid,super.getSession(create), this.request, this.response);return this.session;} else {return null;}}return this.session;}@Overridepublic HttpSession getSession() {if (this.session == null) {this.session = new HttpSessionWrapper(this.sid, super.getSession(),this.request, this.response);}return this.session;}}

(3)SessionFilter拦截器的实现

public class SessionFilter extends OncePerRequestFilter implements Filter {private static final Logger LOG = Logger.getLogger(SessionFilter.class);@Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {//从COOKIE中获取sessionId,如果此次请求没有sessionId,重写为这次请求设置一个sessionIdString sid = COOKIEUtil.getCOOKIEValue(request, GlobalConstant.JSESSIONID);if(StringUtils.isEmpty(sid) || sid.length() != 36){sid = StringUtil.getUuid();COOKIEUtil.setCOOKIE(request, response, GlobalConstant.JSESSIONID, sid, 60 * 60); }//交给自定义的HttpServletRequestWrapper处理filterChain.doFilter(new HttpServletRequestWrapper(sid, request, response), response);}}

(4)SessionService实现session从redis的读写存储

public class SessionService {private final static Logger LOG = Logger.getLogger(SessionService.class);private JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer();@Autowiredprivate RedisTemplate redisTemplate;@SuppressWarnings("unchecked")public Map getSession(String sid) {Map session = new HashMap();try {Object obj = redisTemplate.opsForValue().get(RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid);if(obj != null){obj = jdkSerializer.deserialize((byte[])obj);session = (Map) obj;}} catch (Exception e) {LOG.error("Redis获取session异常" + e.getMessage(), e.getCause());}return session;}public void saveSession(String sid, Map session) {try {redisTemplates.opsForValue().set(RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid,jdkSerializer.serialize(session), RedisKeyUtil.SESSION_TIMEOUT,TimeUnit.MINUTES);} catch (Exception e) {LOG.error("Redis保存session异常" + e.getMessage(), e.getCause());}}public void removeSession(String sid) {try {redisTemplates.delete(RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid);} catch (Exception e) {LOG.error("Redis删除session异常" + e.getMessage(), e.getCause());}}
}

(5)Session的拦截配置,一般的我们只需要拦截我们定义的拦截请求拦截,而不需要所有的都需要拦截。在web.xml中配置SessionFilter。

<filter><filter-name>sessionFilterfilter-name><filter-class>org.andy.shop.session.SessionFilterfilter-class>filter><filter-mapping><filter-name>sessionFilterfilter-name>*.dofilter-mapping>


附&#xff1a;设计到的工具类

1、StringUtil工具类

/*** String工具类* * &#64;author andy* &#64;date 2015-5-16 下午4:04:22* */
public class StringUtil {private StringUtil() {super();}/*** 出去null和""* &#64;param src* &#64;return*/public static String formatNull(String src) {return (src &#61;&#61; null || "null".equals(src)) ? "" : src;}/*** 判断字符串是否为空的正则表达式&#xff0c;空白字符对应的unicode编码*/private static final String EMPTY_REGEX &#61; "[\\s\\u00a0\\u2007\\u202f\\u0009-\\u000d\\u001c-\\u001f]&#43;";/*** 验证字符串是否为空* * &#64;param input* &#64;return*/public static boolean isEmpty(String input) {return input &#61;&#61; null || input.equals("") || input.matches(EMPTY_REGEX);}public static boolean isNotEmpty(String input){return !isEmpty(input);}public static String getUuid() {return UUID.randomUUID().toString();}
}

2、COOKIE管理COOKIEUtil工具类

/*** 创建时间&#xff1a;2016年1月22日 下午8:33:56* * &#64;author andy* &#64;version 2.2*/public class COOKIEUtil {private static final String KEY &#61; "jkdflsffff()kldkjapfdY&#61;::$B&#43;DUOWAN";private HttpServletRequest request;private HttpServletResponse response;private static String domain &#61; "andy.com";public COOKIEUtil(HttpServletRequest request, HttpServletResponse response) {this.request &#61; request;this.response &#61; response;}/*** 保存COOKIE* &#64;param request* &#64;param response* &#64;param name COOKIE名称* &#64;param value COOKIE值* &#64;param seconds 过期时间(单位秒) -1代表关闭浏览器时COOKIE即过期*/public static void setCOOKIE(HttpServletRequest request,HttpServletResponse response, String name, String value, int seconds) {if (StringUtils.isEmpty(name) || StringUtils.isEmpty(value))return;COOKIE COOKIE &#61; new COOKIE(name, value);//COOKIE.setDomain(domain);COOKIE.setMaxAge(seconds); COOKIE.setPath("/");response.setHeader("P3P","CP&#61;&#39;IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT&#39;");response.addCOOKIE(COOKIE);}/*** 过去COOKIE中保存的值* &#64;param name* &#64;return* &#64;throws UnsupportedEncodingException*/public String getCOOKIEValue(String name)throws UnsupportedEncodingException {COOKIE COOKIEs[] &#61; request.getCOOKIEs();if (COOKIEs !&#61; null) {for (int i &#61; 0; i if (name.equalsIgnoreCase(COOKIEs[i].getName())) {return COOKIEs[i].getValue();}}}return "";}/*** 设置加密的COOKIE* &#64;param name COOKIE名称* &#64;param value COOKIE值* &#64;param seconds 过期时间 -1代表关闭浏览器时COOKIE即过期*/public void setCheckCodeCOOKIE(String name, String value, int seconds) {if (StringUtils.isEmpty(name) || StringUtils.isEmpty(value)) {return;}String md5Value &#61; MD5Utils.getMD5(KEY &#43; value);COOKIE COOKIE &#61; new COOKIE(name, md5Value);//COOKIE.setDomain(domain);COOKIE.setMaxAge(seconds);COOKIE.setPath("/");response.addCOOKIE(COOKIE);}/*** 校验加密的COOKIE* &#64;param name* &#64;param value* &#64;return*/public boolean checkCodeCOOKIE(String name, String value) {if (StringUtils.isEmpty(name) || StringUtils.isEmpty(value)) {return false;}boolean result &#61; false;String COOKIEValue &#61; getCOOKIEValue(request, name);if (MD5Utils.getMD5(KEY &#43; value).equalsIgnoreCase(COOKIEValue)) {result &#61; true;}return result;}/*** 获取COOKIE值* &#64;param request* &#64;param name* &#64;return*/public static String getCOOKIEValue(HttpServletRequest request, String name) {try {COOKIE COOKIEs[] &#61; request.getCOOKIEs();if (COOKIEs !&#61; null) {for (int i &#61; 0; i if (name.equalsIgnoreCase(COOKIEs[i].getName())) {return COOKIEs[i].getValue();}}}} catch (Exception e) {}return "";}/*** 移除客户端的COOKIE* &#64;param request* &#64;param response* &#64;param name*/public static void removeCOOKIEValue(HttpServletRequest request,HttpServletResponse response, String name) {try {COOKIE COOKIEs[] &#61; request.getCOOKIEs();if (COOKIEs !&#61; null && COOKIEs.length > 0) {for (COOKIE COOKIE : COOKIEs) {if (name.equalsIgnoreCase(COOKIE.getName())) {COOKIE &#61; new COOKIE(name, null);COOKIE.setMaxAge(0);COOKIE.setPath("/");//COOKIE.setDomain(domain);response.addCOOKIE(COOKIE);break;}}}} catch (Exception e) {e.printStackTrace();}}
}

3、redis键key设置类RedisKeyUtil

/*** 创建时间&#xff1a;2015年9月22日 下午4:51:11* * &#64;author andy* &#64;version 2.2*/public class RedisKeyUtil {public static final String SESSION_DISTRIBUTED_SESSIONID &#61; "session:distributed:"; //分布式session sessionid -- sessionvaluepublic static final Integer SESSION_TIMEOUT &#61; 2; //session 失效时间2小时}

4、分布式session常量设置类GlobalConstant

/*** 创建时间&#xff1a;2016年1月23日 上午11:16:56* * 分布式session常量* * &#64;author andy* &#64;version 2.2*/public class GlobalConstant {public static final String USER_SESSION_KEY &#61; "user_session_key";//用户session信息public static final String JSESSIONID &#61; "YHMJSESSIONID"; //jsessionid
}

分布式session在redis执行结果&#xff1a;
redis中session保存结果


推荐阅读
  • 分布式开源任务调度框架 TBSchedule 深度解析与应用实践
    本文深入解析了分布式开源任务调度框架 TBSchedule 的核心原理与应用场景,并通过实际案例详细介绍了其部署与使用方法。首先,从源码下载开始,详细阐述了 TBSchedule 的安装步骤和配置要点。接着,探讨了该框架在大规模分布式环境中的性能优化策略,以及如何通过灵活的任务调度机制提升系统效率。最后,结合具体实例,展示了 TBSchedule 在实际项目中的应用效果,为开发者提供了宝贵的实践经验。 ... [详细]
  • 本文详细解析了如何使用 jQuery 实现一个在浏览器地址栏运行的射击游戏。通过源代码分析,展示了关键的 JavaScript 技术和实现方法,并提供了在线演示链接供读者参考。此外,还介绍了如何在 Visual Studio Code 中进行开发和调试,为开发者提供了实用的技巧和建议。 ... [详细]
  • 浅析PHP中$_SERVER[
    在PHP后端开发中,`$_SERVER["HTTP_REFERER"]` 是一个非常有用的超级全局变量,它可以获取用户访问当前页面之前的URL。本文将详细介绍该变量的使用方法及其在不同场景下的应用,如页面跳转跟踪、安全验证和用户行为分析等。通过实例解析,帮助开发者更好地理解和利用这一功能。 ... [详细]
  • MySQL性能优化与调参指南【数据库管理】
    本文详细探讨了MySQL数据库的性能优化与参数调整技巧,旨在帮助数据库管理员和开发人员提升系统的运行效率。内容涵盖索引优化、查询优化、配置参数调整等方面,结合实际案例进行深入分析,提供实用的操作建议。此外,还介绍了常见的性能监控工具和方法,助力读者全面掌握MySQL性能优化的核心技能。 ... [详细]
  • 为了评估精心优化的模型与策略在实际环境中的表现,Google对其实验框架进行了全面升级,旨在实现更高效、更精准和更快速的在线测试。新的框架支持更多的实验场景,提供更好的数据洞察,并显著缩短了实验周期,从而加速产品迭代和优化过程。 ... [详细]
  • 在过去,我曾使用过自建MySQL服务器中的MyISAM和InnoDB存储引擎(也曾尝试过Memory引擎)。今年初,我开始转向阿里云的关系型数据库服务,并深入研究了其高效的压缩存储引擎TokuDB。TokuDB在数据压缩和处理大规模数据集方面表现出色,显著提升了存储效率和查询性能。通过实际应用,我发现TokuDB不仅能够有效减少存储成本,还能显著提高数据处理速度,特别适用于高并发和大数据量的场景。 ... [详细]
  • 在数据库设计中,谨慎使用外键至关重要。本文探讨了九个关键原因,包括数据完整性的维护、性能优化、系统复杂性的管理、数据迁移的灵活性以及对外部系统的依赖性控制。通过深入分析这些因素,可以帮助开发人员和架构师做出更明智的设计决策,确保数据库系统的高效与稳定。 ... [详细]
  • Java Web开发中的JSP:三大指令、九大隐式对象与动作标签详解
    在Java Web开发中,JSP(Java Server Pages)是一种重要的技术,用于构建动态网页。本文详细介绍了JSP的三大指令、九大隐式对象以及动作标签。三大指令包括页面指令、包含指令和标签库指令,它们分别用于设置页面属性、引入其他文件和定义自定义标签。九大隐式对象则涵盖了请求、响应、会话、应用上下文等关键组件,为开发者提供了便捷的操作接口。动作标签则通过预定义的动作来简化页面逻辑,提高开发效率。这些内容对于理解和掌握JSP技术具有重要意义。 ... [详细]
  • 深入解析Netty:基础理论与IO模型概述
    深入解析Netty:基础理论与IO模型概述 ... [详细]
  • 在《PHP应用性能优化实战指南:从理论到实践的全面解析》一文中,作者分享了一次实际的PHP应用优化经验。文章回顾了先前进行的一次优化项目,指出即使系统运行时间较长后出现的各种问题和性能瓶颈,通过采用一些通用的优化策略仍然能够有效解决。文中不仅详细阐述了优化的具体步骤和方法,还结合实例分析了优化前后的性能对比,为读者提供了宝贵的参考和借鉴。 ... [详细]
  • 从无到有,构建个人专属的操作系统解决方案
    操作系统(OS)被誉为程序员的三大浪漫之一,常被比喻为计算机的灵魂、大脑、内核和基石,其重要性不言而喻。本文将详细介绍如何从零开始构建个人专属的操作系统解决方案,涵盖从需求分析到系统设计、开发与测试的全过程,帮助读者深入理解操作系统的本质与实现方法。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • HBase在金融大数据迁移中的应用与挑战
    随着最后一台设备的下线,标志着超过10PB的HBase数据迁移项目顺利完成。目前,新的集群已在新机房稳定运行超过两个月,监控数据显示,新集群的查询响应时间显著降低,系统稳定性大幅提升。此外,数据消费的波动也变得更加平滑,整体性能得到了显著优化。 ... [详细]
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 数据结构与算法:HyperLogLog 统计、布隆过滤器应用、缓存机制挑战及解决方案、Redis 性能优化与监控、哨兵模式、版本控制工具 Git
    本文探讨了数据结构与算法在实际应用中的多个方面。首先介绍了HyperLogLog算法,用于高效地进行基数统计,能够准确估算大规模数据集中的唯一元素数量。接着讨论了布隆过滤器的应用,该过滤器在空间效率和查询速度上具有显著优势,适用于大数据场景下的快速成员检测。此外,文章分析了缓存机制面临的挑战及其解决方案,包括LRU和LFU等策略,并详细阐述了Redis的性能优化与监控方法,如使用哨兵模式实现高可用性。最后,介绍了版本控制工具Git的基本操作和最佳实践,帮助开发者有效管理代码版本。 ... [详细]
author-avatar
万世一统_425
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有