1. 简介

在本文中,我们将学习如何将 Spring Session 与 Spring WebFlux 结合使用。重点在于 Spring WebSession 的使用方式,它是 Spring Session 与 Spring Boot 2 中引入的 WebFlux 框架集成的核心组件。

Spring Session 的本质是一个简化的键值对(name-value)Map 结构,用于管理 HTTP 会话中的一些关键信息,比如用户身份(User)、认证主体(Principal)等。通过结合 WebFlux 的响应式类型 MonoFlux,我们可以实现非阻塞的会话管理。此外,Spring Session 支持多种容器环境(而不仅限于 Tomcat),灵活性更高。

如果你对 Spring Session 还不太熟悉,可以先参考 Baeldung 的 这篇文章 做个基础了解。

2. Maven 依赖配置

首先,我们需要配置好项目的依赖。这里以 Spring Boot 3.x 为例,添加以下两个核心依赖:

✅ 基础依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <version>3.1.5</version>
</dependency>
<dependency> 
    <groupId>org.springframework.session</groupId> 
    <artifactId>spring-session-core</artifactId> 
    <version>3.1.5</version> 
</dependency>

这两个依赖是使用内存会话管理的最低要求。

🔄 如果使用 Redis 作为会话存储

还需要引入以下两个依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>3.1.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
    <version>3.1.5</version>
</dependency>

3. 内存会话配置

如果选择使用内存存储会话信息,可以添加如下配置类:

@Configuration
@EnableSpringWebSession
public class SessionConfig {
 
    @Bean
    public ReactiveSessionRepository reactiveSessionRepository() {
        return new ReactiveMapSessionRepository(new ConcurrentHashMap<>());
    }
}

这个配置类通过 @EnableSpringWebSession 启用 WebSession 支持,并将 Session 数据存储在 ConcurrentHashMap 中。

⚠️ 注意:必须添加 @EnableSpringWebSession 注解,否则配置不会生效。

4. Redis 会话配置

如果使用 Redis 作为会话存储,配置类如下:

@Configuration
@EnableRedisWebSession
public class RedisConfig {
 
    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory();
    }
}

⚠️ 注意:不能同时使用 @EnableRedisWebSession@EnableSpringWebSession,否则会抛出异常。

🔧 使用 Docker 快速启动 Redis

最简单的启动 Redis 的方式是使用 Docker:

$ docker stop redis
$ docker rm redis
$ docker run -d --name redis -p 6379:6379 redis:4.0.5-alpine

5. 实战使用 WebSession

接下来,我们编写一个响应式的 REST 控制器来演示如何使用 WebSession

🧪 示例 1:获取默认 Session 信息

@GetMapping("/websession")
public Mono getSession(WebSession session) {

    session.getAttributes().putIfAbsent("id", 0);
    session.getAttributes().putIfAbsent("note", "Howdy Cosmic Spheroid!");

    CustomResponse r = new CustomResponse();
    r.setId((int) session.getAttributes().get("id"));
    r.setNote((String) session.getAttributes().get("note"));

    return Mono.just(r);
}

🧪 示例 2:通过参数更新 Session

@GetMapping("/websession/test")
public Mono<CustomResponse> testWebSessionByParam(@RequestParam(value = "id") int id,
  @RequestParam(value = "note") String note, WebSession session) {

    session.getAttributes().put("id", id);
    session.getAttributes().put("note", note);

    CustomResponse r = new CustomResponse();
    r.setId((int) session.getAttributes().get("id"));
    r.setNote((String) session.getAttributes().get("note"));

    return Mono.just(r);
}

通过 session.getAttributes() 方法,我们可以像操作 Map 一样读写会话属性。

🚀 启动应用并测试

启动 Spring Boot 应用后,可以通过如下方式测试:

更新 Session 数据

$ curl -i -H "Accept: application/json" -H "Content-Type:application/json" -X GET "http://localhost:8080/websession/test?id=222&note=helloworld"

或者直接访问浏览器地址:

http://localhost:8080/websession/test?id=222&note=helloworld

查看当前 Session 数据

访问:

http://localhost:8080/websession

返回的 JSON 将包含更新后的 idnote 值:

websession one

websession three

6. 总结

本文介绍了如何在 Spring WebFlux 应用中集成 Spring Session 的响应式支持 —— WebSession。你可以选择内存或 Redis 作为 Session 存储后端,结合 WebSession 实现灵活的非阻塞会话管理。

更多细节可以查阅官方文档。

📌 本文所有代码示例均可在 GitHub 获取:点击访问


原始标题:A Guide to Spring Session Reactive Support: WebSession