1、为什么要用

在传统单机web应用中,一般使用tomcat/jetty等web容器时,用户的session都是由容器管理。浏览器使用cookie中记录sessionId,容器根据sessionId判断用户是否存在会话session。这里的限制是,session存储在web容器中,被单台服务器容器管理。
但是网站主键演变,分布式应用和集群是趋势(提高性能)。此时用户的请求可能被负载分发至不同的服务器,此时传统的web容器管理用户会话session的方式即行不通。除非集群或者分布式web应用能够共享session,尽管tomcat等支持这样做。但是这样存在以下两点问题:

  • 需要侵入web容器,提高问题的复杂
  • web容器之间共享session,集群机器之间势必要交互耦合

基于这些,必须提供新的可靠的集群分布式/集群session的解决方案,突破traditional-session单机限制(即web容器session方式,下面简称traditional-session),spring-session应用而生。

2、比较传统方案

下图展示了traditional-session和spring-session的区别
Spring Session - 图1
传统模式中,当request进入web容器,根据reqest获取session时,如果web容器中存在session则返回,如果不存在,web容器则创建一个session。然后返回response时,将sessonId作为response的head一并返回给客户端或者浏览器。
但是上节中说明了traditional-session的局限性在于:单机session。在此限制的相反面,即将session从web容器中抽出来,形成独立的模块,以便分布式应用或者集群都能共享,即能解决。
spring-session的核心思想在于此:将session从web容器中剥离,存储在独立的存储服务器中。目前支持多种形式的session存储器:Redis、Database、MogonDB等。session的管理责任委托给spring-session承担。当request进入web容器,根据request获取session时,由spring-session负责存存储器中获取session,如果存在则返回,如果不存在则创建并持久化至存储器中。

3、JSR340规范与spring-session的透明继承

JSR340是Java Servlet 3.1的规范提案,其中定义了大量的api,包括:servlet、servletRequest/HttpServletRequest/HttpServletRequestWrapper、servletResponse/HttpServletResponse/HttpServletResponseWrapper、Filter、Session等,是标准的web容器需要遵循的规约,如tomcat/jetty/weblogic等等。
在日常的应用开发中,develpers也在频繁的使用servlet-api,比如:
以下的方式获取请求的session:
HttpServletRequest request = …
HttpSession session = request.getSession(false);

  • 接口适配:仍然使用HttpServletRequest获取session,获取到的session仍然是HttpSession类型——适配器模式
  • 类型包装增强:Session不能存储在web容器内,要外化存储——装饰模式让人兴奋的是,以上的需求在Servlet规范中的扩展性都是予以支持!Servlet规范中定义一系列的接口都是支持扩展,同时提供Filter支撑扩展点。4、Spring-session特点spring-session在无需绑定web容器的情况下提供对集群session的支持。并提供对以下情况的透明集成:
    • HttpSession:容许替换web容器的HttpSession
    • WebSocket:使用WebSocket通信时,提供Session的活跃
    • WebSession:容许以应用中立的方式替换webflux的webSession
  • 5、Spring-session工作原理
    再详细阅读源码之前先来看张图,介绍下spring-session中的核心模块以及之间的交互。
    Spring Session - 图2
    spring-session分为以下核心模块:
    • SessionRepositoryFilter:Servlet规范中Filter的实现,用来切换HttpSession至Spring Session,包装HttpServletRequest和HttpServletResponse
    • HttpServerletRequest/HttpServletResponse/HttpSessionWrapper包装器:包装原有的HttpServletRequest、HttpServletResponse和Spring Session,实现切换Session和透明继承HttpSession的关键之所在
    • Session:Spring Session模块
    • SessionRepository:管理Spring Session的模块
    • HttpSessionStrategy:映射HttpRequst和HttpResponse到Session的策略
  • 更多参考:https://www.cnblogs.com/lxyit/p/9672097.html
    6、使用
    在项目添加依赖:
  1. <!--spring session redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-redis</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.session</groupId>
  8. <artifactId>spring-session-data-redis</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.apache.commons</groupId>
  12. <artifactId>commons-pool2</artifactId>
  13. </dependency>
  14. <dependency>
  15. <groupId>redis.clients</groupId>
  16. <artifactId>jedis</artifactId>
  17. </dependency>
  • 添加redis配置:
  1. spring
  2. redis:
  3. host: 192.168.56.100
  4. port: 6379
  5. password: 123456
  6. jedis:
  7. pool:
  8. max-idle: 100
  9. min-idle: 10
  • 添加注解@EnableRedisHttpSession

实现第一种方案的关键点在于做到透明和兼容
两种方案都可以实现,但是显然第一种更友好,且具有兼容性。spring-session正是第一种方案的实现。

  • 遵循servlet规范,同样方式获取session,对应用代码无侵入且对于developers透明化
  • 全新实现一套session规范,定义一套新的api和session管理机制

其中HttpServletRequest和HttpSession都是servlet规范中定义的接口,web容器实现的标准。那如果引入spring-session,要如何获取session?