1. 背景

传统的session只能保存在内存中,且与Cookie绑定,只能从Cookie中获取sessionId,然后在应用中使用。

但是现在的开发环境中,除了传统的web项目,还有基于分布式的项目,这种项目传统的单体应用session是根本没法使用的
除此之外,现在手机APP也逐步多了起来,基于 CS架构的 应用兴起,而手机是不支持Cookie的,因此,也无法使用传统的Cookie-Session的模式

2. SpringSession

SpringSession 是 Spring 官方开源的框架,旨在提供会话管理的解决方案。它可以与各种后端存储(如内存、数据库、Redis 等)集成,以便将会话数据存储在可扩展的分布式环境中。Spring Session 不仅可以用于传统的 Web 应用程序,还可以用于微服务架构中的分布式系统。

SpringSession实现的session存储不依赖内存,因此,项目重启之后session依然有效。

2.1. Spring Session 的核心概念

在深入研究 Spring Session 之前,让我们了解一些核心概念:

2.1.1. 会话(Session)

会话是一个用户与应用程序之间的交互周期。在 Web 应用程序中,会话通常涉及用户登录、浏览网页、提交表单等操作。会话数据可以包括用户身份验证状态、购物车内容、用户首选项等。

2.1.2. Spring Session Repository

这是 Spring Session 存储会话数据的地方。它可以与多种后端存储集成,包括内存、数据库、Redis 等。

2.1.3. Session ID(会话标识符)

Session ID 是用于标识特定会话的唯一标识符。它通常存储在客户端的 Cookie 中,并用于将客户端请求与服务器端会话关联起来。

2.2. Spring Session 的工作流程

Spring Session 的工作原理相对简单,主要涉及以下步骤:

  • 客户端请求:当客户端发送请求到服务器时,会将 Cookie 或者header中定义的session字段一并发送给服务器 。
  • 请求经过SpringSession过滤器 ,此过滤器专门用于处理转换session。
    • Session Repository 查询:Spring Session 会根据请求中的 Session ID 查询相应的会话数据。这个查询可以通过内存、数据库(redis)或分布式存储来完成。
    • 会话创建或恢复:如果找到与 Session ID 相关联的会话数据,Spring Session 会将其加载到内存中,以供后续请求使用。如果没有找到会话数据,将创建一个新的会话。
    • 处理请求:服务器会使用加载或创建的会话数据来处理客户端的请求。这可以包括读取和修改会话属性。
  • 经过过滤器后session已经被替换了,后续业务正常使用即可。
  • 数据处理完返回经过过滤器时,会更新session至Session Repository存储中。
  • 响应发送:服务器将响应发送给客户端,并在响应中包含更新后的 Session ID(如果会话数据有变化)。

SpringSession通过使用过滤器添加一层过滤来实现session的替换,应用中都完全不用调整。

虽然我也自己通过跟踪源码的方式定位到了,考虑到了使用这一方式来处理,奈何知识有限,只实现到通过header获取session的方式,session里面的细节没有处理。

2.3. 实现方案

SpringSession 实现了 Redis、 JDBC 、Mongodb、Hazelcast、NONE 五方案的存储,其中NONE使用的是内存session,与原本session方案一样。

这五种使用的时候选取一种即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* Supported Spring Session data store types.
*
* @author Tommy Ludwig
* @author Eddú Meléndez
* @author Vedran Pavic
* @since 1.4.0
*/
public enum StoreType {

/**
* Redis backed sessions.
*/
REDIS,

/**
* MongoDB backed sessions.
*/
MONGODB,

/**
* JDBC backed sessions.
*/
JDBC,

/**
* Hazelcast backed sessions.
*/
HAZELCAST,

/**
* No session data-store.
*/
NONE

}

3. 工程实现

这里我们用一个最简单的基于内存的来实现,不用引入其他框架等。

相当于和原来一样,没有变化。

示例工程直接使用springboot,已经做好了各种配置。

3.1. 引入依赖

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>

3.2. application配置文件

1
2
3
spring:
session:
store-type: none

3.3. 启动

配置好启动类,然后直接启动springboot项目即可

1
2
3
4
5
6
@SpringBootApplication
public class D118SpringSessionRedisApp {
public static void main(String[] args) {
SpringApplication.run(D118SpringSessionRedisApp.class, args);
}
}

这样就完成了一个最简单的替换session的方案