0


深入理解 Spring Session:实现分布式会话管理(含详细步骤)

Spring Session 是 Spring 框架的一个扩展,它提供了一种强大的方式来管理应用程序的会话,尤其适用于分布式系统。在这篇博客中,我们将深入探讨 Spring Session 的工作流程、核心原理、使用场景以及如何在您的应用程序中实现分布式会话管理。

什么是 Spring Session?

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

Spring Session 的核心概念

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

  1. 会话(Session):会话是一个用户与应用程序之间的交互周期。在 Web 应用程序中,会话通常涉及用户登录、浏览网页、提交表单等操作。会话数据可以包括用户身份验证状态、购物车内容、用户首选项等。
  2. Spring Session Repository:这是 Spring Session 存储会话数据的地方。它可以与多种后端存储集成,包括内存、数据库、Redis 等。
  3. Session ID(会话标识符):Session ID 是用于标识特定会话的唯一标识符。它通常存储在客户端的 Cookie 中,并用于将客户端请求与服务器端会话关联起来。

Spring Session 的工作流程

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

  1. 客户端请求:当客户端(通常是浏览器)发送请求到服务器时,会将包含 Session ID 的 Cookie 信息一并发送给服务器。
  2. Session Repository 查询:Spring Session 会根据请求中的 Session ID 查询相应的会话数据。这个查询可以通过内存、数据库(redis)或分布式存储来完成,具体取决于您的配置。
  3. 会话创建或恢复:如果找到与 Session ID 相关联的会话数据,Spring Session 会将其加载到内存中,以供后续请求使用。如果没有找到会话数据,将创建一个新的会话。
  4. 处理请求:服务器会使用加载或创建的会话数据来处理客户端的请求。这可以包括读取和修改会话属性。
  5. 响应发送:服务器将响应发送给客户端,并在响应中包含更新后的 Session ID(如果会话数据有变化)。
  6. 客户端 Cookie 更新:客户端接收到服务器响应后,可能会更新 Cookie 中的 Session ID,以便将来的请求能够正确关联到会话。

Spring Session 的核心原理

以redis作为会话存储为例,我们从源代码的层面上去分析SpringSession的核心原理,其关键在于理解@EnableRedisHttpSession做了哪些事情。

1.SessionRepository

@EnableRedisHttpSession除了指定 Spring Session 使用 Redis 作为会话存储之外,还做了一些“隐秘”的操作。既然都用redis存储会话数据了,那很显然我们需要一套类似于MyBatis操作数据库增删改查的repository类来操作相关数据,而在SpringSession里面,SessionRepository就充当了这个角色。具体的,在本例子中是RedisOperationsSessionRepository,

通过查看EnableRedisHttpSession注解的源码,我们发现其导入了一个RedisHttpSessionConfiguration类,在这个类的源码中,向Spring容器提供了RedisOperationsSessionRepository,代码如下:

2.SessionRepositoryFilter

EnableRedisHttpSession注解导入的RedisHttpSessionConfiguration继承了SpringHttpSessionConfiguration,而这个配置类配置了一个SessionRepositoryFilter,通过源码发现其就是一个Filter,他重写了doFilterInternal方法,源码如下:

我们可以发现,对于每一个请求,它将HttpServletRequest和HttpServletResponse都“包装”了一下,包装成了和SessionRepository有关了的“加强”类,在“加强”类中,重写了getSession方法,这里获取到的session就不是原生的session,部分源码如下:

它会有很多基于SessionRepository的操作(可以查看上图完整的源码得知),这样,我们就可以在原来request.getSession().setAttribute(key,value)的用法上,实现基于SpringSession的操作,因为这里的request并不是原始的HttpServletRequest,而是被包装过的SessionRepositoryRequestWrapper,这也就是上文提到的“加强类”,得到的session也是HttpSessionWrapper“加强session”,所以调用的操作就是SpringSession操作redis等等。

3.总结

SpringSession源码的核心就是利用装饰者模式,通过过滤器Filter将Request、Response、Session类包装成“加强”之后的类,这个加强就提供了众多操作外部存储redis的方法。

Spring Session 的使用场景

Spring Session 可以在许多场景下发挥重要作用:

  1. 分布式系统:在微服务架构中,多个服务可能需要共享用户的会话数据。Spring Session 可以将会话数据存储在分布式存储中,确保各个服务之间共享相同的会话状态。
  2. 云原生应用:对于云原生应用,Spring Session 可以使应用程序更易于扩展和部署。它提供了无状态的会话管理,允许应用程序实例之间共享用户的会话数据。
  3. 高可用性和负载均衡:Spring Session 可以与负载均衡和高可用性部署一起使用,以确保在系统故障或应用程序部署期间不会丢失会话数据。

如何在 Spring Boot 中使用 Spring Session

在 Spring Boot 中使用 Spring Session 非常简单,以redis作为存储session数据为例,主要包括以下步骤:

1. 依赖引入

首先,您需要在项目中引入 Spring Session 和 Redis 的相关依赖。通常,您可以在

pom.xml

文件中添加以下依赖:

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-core</artifactId>
    <version>2.5.0</version> <!-- 版本号可能会有变化 -->
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

这些依赖包括 Spring Session 核心库和 Spring Boot 的 Redis 支持。

2. 配置 Redis 连接

接下来,您需要配置 Spring Boot 应用程序以连接到 Redis。通常,在

application.properties

application.yml

中添加 Redis 配置,如下所示:

spring:
  redis:
    host: localhost
    port: 6379

这将告诉 Spring Boot 应用程序连接到本地的 Redis 服务器。

3. Spring Session 配置

接下来配置 Spring Session,以使用 Redis 作为外部会话存储。可以创建一个配置类,如下所示:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("lcc.com");//这样就可以实现lcc.com以及lcc.com子域(如:a.lcc.com、b.lcc.com)下的服务之间session共享
        return cookieSerializer;
    }

    // 可以添加其他配置
}
@EnableRedisHttpSession

注解告诉 Spring Session 使用 Redis 作为会话存储。

在使用

@EnableRedisHttpSession

启用 Spring Session 集成 Redis 作为会话存储时,通常无需再显式配置

spring.session.store-type=redis

。这是因为

@EnableRedisHttpSession

已经隐式指示 Spring Session 使用 Redis 作为会话存储。

4. 会话操作

到这里即可在应用程序中正常操作会话,就像操作本地会话一样。Spring Session 提供了一些接口和工具,如HttpSession,用于处理会话数据。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.stereotype.Service;

@Service
public class SessionService {
    @Autowired
    private SessionRepository sessionRepository;

    public void storeDataInSession(String key, String value) {
        Session session = sessionRepository.findById(key);
        session.setAttribute(key, value);
        sessionRepository.save(session);
    }

    public String getDataFromSession(String key) {
        Session session = sessionRepository.findById(key);
        return session.getAttribute(key);
    }
}

在这个示例中,

SessionService

使用

SessionRepository

来存储和检索会话数据。

标签: spring 分布式 java

本文转载自: https://blog.csdn.net/qq_46248151/article/details/135142857
版权归原作者 Java 第一深情 所有, 如有侵权,请联系我们删除。

“深入理解 Spring Session:实现分布式会话管理(含详细步骤)”的评论:

还没有评论