分布式cookie-session的实现(spring-session)
分布式cookie-session的实现(spring-session)
本文使用的spring-session版本为 1.0.0,地址为: https://github.com/spring-projects/spring-session
1 session存储策略
存储,即在后台使用session的setAttribute,getAttribute等方法时,这些内部存放的数据最终存储至什么位置。比如在默认的tomcat实现中,相应的数据即存储在内存中,并在停止之后会序列化至磁盘中。
可以使用内存存储和第三方存储,如redis。对于集群式的session存储,那么肯定会使用第三方存储的实现。
在spring-session中,对session存储单独作了一个定义,但定义上基本保证与http session一致,主要的目的在于它可以支持在非http的环境中模拟使用。因此不直接使用http session接口。
先看定义:
1
2
3
4
5
6
7
8
|
public interface Session { /** 获取惟一的id,可以理解为即将每个session当作一个实体对象 */ String getId(); <T> T getAttribute(String attributeName); Set<String> getAttributeNames(); void setAttribute(String attributeName, Object attributeValue); void removeAttribute(String attributeName); } |
从这个定义来看,如果要使用httpSession,如果实现了这个session接口,那么实现上就可以全部实现httpSession对于存储的要求。对于非httpSession场景,使用这个也可以达到session存储的目的。
当然,为了保证在会话场景中会使用到失效,最后访问时间,最大不活跃时间的目的,spring-session也有一个继承于session接口的expiringSession接口。
1.0 id主键的生成
对于id,即理解为session实体对象惟一键,可以采用任意的一种惟一key生成策略。比如,使用uuid来生成惟一键。同时,也可以将这个id认为就是在http中sessionCookie的值
1.1 map存储
如果是map来存储,那么 set,get,remove就可以直接使用map的相应实现即可。在spring-session实现中MapSession,即采用内部的一个hashmap来进行存储。
1.2 redis存储
在sprng-session中,将属性的存储和整体的存储分开,使用专门的仓库来处理session实体的处理。对于从领域模型的概念来说,set,get,removeAttribute只是对属性的处理,处理的是一个内部状态的变化,对于整体的实体来说,并没有整体上的处理。具体到实现,在redis的存储实现中,spring-session内部使用了一个 mapSession来存储相应的属性信息。
在一个实体被创建之后,相应的属性信息被全部设置至mapSession中,然后接下来的属性访问均通过mapSession来处理。为了最终存储相应的数据值,redis实现使用了一个额外的deltaMap来存放变化了的数据,并在重新保存时,一次性地将所有属性put至redis中。
从这个实现来看,spring-session的实现并不是实时地与redis进行交互,这种实现方式在解决同一session设置冲突属性时可能存在问题。因此存在这种场景的,需要重新实现相应的逻辑。
2 session仓库策略
之所以将存储策略和仓库策略分开,也是spring-session的一个设计思想。spring将session设计为一个实体,因此将实体对象的操作和属性的操作进行拆分。在前面的存储策略已经描述了属性的操作,因此这里的仓库策略主要处理实体的创建,获取,更新,删除等,即CRUD。如下的定义所示:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public interface SessionRepository<S extends Session> { /** 新建 */ S createSession(); /** 保存或更新 */ void save(S session); /** 获取 */ S getSession(String id); /** 删除 */ void delete(String id); } |
2.1 本地仓库
如果是本地仓库,那么可以使用一个本地全局的globalMap,然后使用sessionId作为key,mapSession作为value来实现即可。
2.2 redis仓库
如果是resi仓库,那么在新建时,只是在本地创建一个redisSession对象,然后在redis存储中使用一个 hash结构来进行存储。即<I,<K,V>>的结构。其中I即表示sessionId,<k,V>表示具体的redisSession对象。其中getSession,delete都是针对I的操作,而save则在在指定I的情况下,直接保持<K,V>即可。
为了在一定程度上进行优化,以及解决在一定程序上的覆盖问题,在redis实现时。spring-session只对修改过的属性作存储,即当使用setAttribute处理属性时,spring-session使用额外的delta来保存修改过的属性,最后进行save时,只操作这部分数据即可。并且redis也支持调用hSet来保存或更新修改过的数据。
3 session传输策略
3.1 cookie传输
常规的实现也是使用cookie传输,比如tomcat,jetty等。在这种情况下,后端在创建session时,如果这是新的session,会自动调用原生response.addCookie以创建一个新的cookie信息。为保证安全,采用httpOnly进行创建。在发送给客户端之后的每次交互,浏览器会自动将这些信息传输至服务器端。然后服务器端直接从cookie中获取到sessionId,再进一步操作即可。
对于这种实现,应用程序开发不需要作任何的调整,浏览器会自动处理cookie的传输。
3.2 header传输
header传输,即在创建新session时,往response header中使用addHeader添加一个新的响应头,如session头,headerValue中存放相应的sessionId值。
在客户端实现中,客户端代码需要手动地将响应值进行记录,并在请求时加入到请求头当中。并且需要监听响应头值的变化,比如sessionId值的变化处理。相比cookie传输来说,这种实现对于开发更复杂一点。
4 http协议兼容
4.1 为保证http协议兼容,在session信息准备好之后,其必须在响应头之后进行处理
不管是使用cookie传输还是header传输,在响应时都需要保证在响应body输出时,相应的头信息都应该先被处理。(cookie也是一种特殊的header)。如果像以下的代码,就不能保证session响应被正确地处理
1
2
3
4
|
X implements Filter { filterChain.doFilter(request,response) // do session logic } |
在这种实现中,如果在应用代码中直接使用response的outputStream进行输出时,这里的过滤器实现中的do Session操作就不能实现相应的逻辑。因为http协议中的消息机制已经不再允许再输出body之后输出header信息了。
在spring-session的实现中,我们只需要保证在调用response处理响应body时,能够处理session逻辑即可。那么可以使用一种hack的技术,针对在response输出时,判定是否在处理body或应该结束响应时,加入特定的hack以处理我们的do session操作。因此提供了 OnCommittedResponseWrapper 以便在特定的时机进行处理,在具体的 onResponseCommitted中,处理session的delete响应和save等即可。
4.2 为支持多浏览器访问,因此在特定的路径信息处理时,应当自动地处理相应的browser参数
关于多browser支持,可以先看看此篇文章。
http://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-multi
在多browser支持时,主要即在请求参数中增加相应的浏览器识别参数_s,那么在需要进行界面跳转或其它地址处理时,后台应该能够自动地处理相应的参数信息。在spring-session中,为了对应用程序透明,通过重写response的encodeURL和encodeRedirectURL时,增加对相应_s的处理即达到相应的处理透明即可。
转载请标明出处:i flym
本文地址:http://www.iflym.com/index.php/code/201503170001.html
分布式cookie-session的实现(spring-session)的更多相关文章
- Spring Session实现分布式session的简单示例
前面有用 tomcat-redis-session-manager来实现分布式session管理,但是它有一定的局限性,主要是跟tomcat绑定太紧了,这里改成用Spring Session来管理分布 ...
- 使用Spring Session实现Spring Boot水平扩展
小编说:本文使用Spring Session实现了Spring Boot水平扩展,每个Spring Boot应用与其他水平扩展的Spring Boot一样,都能处理用户请求.如果宕机,Nginx会将请 ...
- Re:从零开始的Spring Session(一)
Session和Cookie这两个概念,在学习java web开发之初,大多数人就已经接触过了.最近在研究跨域单点登录的实现时,发现对于Session和Cookie的了解,并不是很深入,所以打算写两篇 ...
- 通过Spring Session实现新一代的Session管理
长期以来,session管理就是企业级Java中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原生云应 ...
- 转:通过Spring Session实现新一代的Session管理
长期以来,session管理就是企业级Java中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原生云应 ...
- 大话 Spring Session 共享
javaweb中我们项目稍微正规点,都会用到单点登录这个技术.实现它的方法各家有各界的看法.这几天由于公司项目需求正在研究.下面整理一下最近整理的心得. 简介 在分布式项目中另我们头疼的是多项目之间的 ...
- Spring Session工作原理
本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/KCOFv0nRuymkX79-RZi9eg 作者:张正林 目录:1.引入背景2.使用方法3.工作流程 ...
- 通过 Spring Session 实现新一代的 Session 管理
长期以来,session 管理就是企业级 Java 中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原 ...
- 实战开发,使用 Spring Session 与 Spring security 完成网站登录改造!!
上次小黑在文章中介绍了四种分布式一致性 Session 的实现方式,在这四种中最常用的就是后端集中存储方案,这样即使 web 应用重启或者扩容,Session 都没有丢失的风险. 今天我们就使用这种方 ...
- spring session 和 spring security整合
背景: 我要做的系统前面放置zuul. 使用自己公司提供的单点登录服务.后面的业务应用也是spring boot支撑的rest服务. 目标: 使用spring security管理权限包括权限.用户请 ...
随机推荐
- OpenGL学习--------颜色的选择
OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式.无论哪种颜色模式,计算机都必须为每一个像素保存一些数据.不同的是,RGBA模式中,数据直接就代表了颜色:而颜色索引模式中,数据代表的是 ...
- JSON & XML 简析
转载自:http://my.oschina.net/aofe/blog/269260 JSON: XML: JSON格式说明: HTML & XML 的对比 HTML: XML: HTML5新 ...
- UITableviewCell 重用内存
转载自:http://www.cnblogs.com/tangbinblog/p/3371545.html 重用实现分析 查看UITableView头文件,会找到NSMutableArray* vi ...
- 通过ant调用shell脚本执行adb命令
在Hudson或者Jenkins中利用ant的exec 来调用shell命令,通过shell脚本来执行adb shell命令,可以正常执行,不会出现在ant中直接调用adb shell出现的假死情况. ...
- 只有mdf 没有 日志 恢复数据库
1.先建一个与你要恢复的数据库名称一样的数据库.2.停止sql server,把你的数据库替换这个数据库.3.重启sql server,把数据库设置为紧急状态. sp_configure 'allo ...
- Ubuntu 开启SSH 以及LAMP环境安装
1. 更新 apt-get sudo apt-get update 2.安装 openssh sudo apt-get install openssh-server 3.设置root账号密码 sudo ...
- angularJS 系列(三)- 自定义 Service
参考:http://viralpatel.net/blogs/angularjs-service-factory-tutorial/ https://www.pluralsight.com/blog/ ...
- (简单) POJ 1426 Find The Multiple,BFS+同余。
Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose ...
- CORBA技术及实例
CORBA技术及实例 CORBA是一种规范,它定义了分布式对象如何实现互操作.在WorldWideWeb盛行之前,非凡是java编程语言风靡之前,C++开发者基本将CORBA作为其高端分布式对象的解决 ...
- iOS 简易环形进度条
demo下载地址:https://github.com/haozheMa/LoopProgressDemo/tree/master ViewController中的代码 #import "V ...