1. 简介
在本教程中,我们将学习如何使用 Spring Data 提供的 ReactiveRedisTemplate
来配置并实现 Redis 的基本操作。
我们会介绍 ReactiveRedisTemplate
的常见用法,比如如何在 Redis 中存储和读取对象,并且会讲解如何通过 ReactiveRedisConnection
执行 Redis 命令。
如果你还不太熟悉 Redis 的基础操作,可以先阅读我们之前的 Spring Data Redis 入门指南。
2. 依赖配置
要使用 ReactiveRedisTemplate
,首先需要添加 Spring Boot 的 Redis 响应式模块依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
3. 连接配置
接着,我们需要建立与 Redis 服务器的连接。如果你的 Redis 服务器运行在 localhost:6379
,那就不需要额外配置。
但如果 Redis 是远程部署的,或者使用了非默认端口,可以通过 LettuceConnectionFactory
来指定主机名和端口号:
@Bean
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
4. 列表操作(List Operations)
Redis 的 List 是按插入顺序排序的字符串列表,支持从左边或右边进行插入(push)和弹出(pop)操作。
4.1. String 模板配置
要操作 List 类型的数据,我们需要使用 ReactiveStringRedisTemplate
来获取 RedisListOperations
实例:
@Autowired
private ReactiveStringRedisTemplate redisTemplate;
private ReactiveListOperations<String, String> reactiveListOps;
@Before
public void setup() {
reactiveListOps = redisTemplate.opsForList();
}
4.2. LPUSH 和 LPOP 操作
有了 ReactiveListOperations
实例后,我们可以通过 leftPushAll
方法将多个元素从左边推入名为 demo_list
的列表中:
@Test
public void givenListAndValues_whenLeftPushAndLeftPop_thenLeftPushAndLeftPop() {
Mono<Long> lPush = reactiveListOps.leftPushAll(LIST_NAME, "first", "second")
.log("Pushed");
StepVerifier.create(lPush)
.expectNext(2L)
.verifyComplete();
Mono<String> lPop = reactiveListOps.leftPop(LIST_NAME)
.log("Popped");
StepVerifier.create(lPop)
.expectNext("second")
.verifyComplete();
}
⚠️ 注意:在测试响应式组件时,可以使用 StepVerifier
来等待操作完成。
5. 值操作(Value Operations)
除了字符串,我们也可以存储自定义对象。下面以 Employee
类为例,演示如何在 Redis 中存储和读取 POJO:
public class Employee implements Serializable {
private String id;
private String name;
private String department;
// ... getters and setters
// ... hashCode and equals
}
5.1. 自定义模板配置
为了支持 Employee
对象的序列化,我们需要创建一个 ReactiveRedisTemplate
实例,key 使用字符串,value 使用 Employee
类型:
@Bean
public ReactiveRedisTemplate<String, Employee> reactiveRedisTemplate(
ReactiveRedisConnectionFactory factory) {
StringRedisSerializer keySerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Employee> valueSerializer =
new Jackson2JsonRedisSerializer<>(Employee.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, Employee> builder =
RedisSerializationContext.newSerializationContext(keySerializer);
RedisSerializationContext<String, Employee> context =
builder.value(valueSerializer).build();
return new ReactiveRedisTemplate<>(factory, context);
}
我们使用 Jackson 库对 Employee
对象进行 JSON 序列化,key 使用 StringRedisSerializer
处理。
然后,创建 ReactiveValueOperations
实例:
@Autowired
private ReactiveRedisTemplate<String, Employee> redisTemplate;
private ReactiveValueOperations<String, Employee> reactiveValueOps;
@Before
public void setup() {
reactiveValueOps = redisTemplate.opsForValue();
}
5.2. 存储与读取操作
使用 ReactiveValueOperations
存储一个 Employee
实例:
@Test
public void givenEmployee_whenSet_thenSet() {
Mono<Boolean> result = reactiveValueOps.set("123",
new Employee("123", "Bill", "Accounts"));
StepVerifier.create(result)
.expectNext(true)
.verifyComplete();
}
再从 Redis 中取出这个对象:
@Test
public void givenEmployeeId_whenGet_thenReturnsEmployee() {
Mono<Employee> fetchedEmployee = reactiveValueOps.get("123");
StepVerifier.create(fetchedEmployee)
.expectNext(new Employee("123", "Bill", "Accounts"))
.verifyComplete();
}
5.3. 设置过期时间
我们经常需要为缓存数据设置过期时间,这可以通过 set
方法的重载版本来实现:
@Test
public void givenEmployee_whenSetWithExpiry_thenSetsWithExpiryTime()
throws InterruptedException {
Mono<Boolean> result = reactiveValueOps.set("129",
new Employee("129", "John", "Programming"),
Duration.ofSeconds(1));
StepVerifier.create(result)
.expectNext(true)
.verifyComplete();
Thread.sleep(2000L);
Mono<Employee> fetchedEmployee = reactiveValueOps.get("129");
StepVerifier.create(fetchedEmployee)
.expectNextCount(0L)
.verifyComplete();
}
⚠️ 这个测试通过 Thread.sleep
等待键过期,模拟缓存失效的场景。
6. Redis 命令接口
Redis 命令是指客户端可以向 Redis 服务器发送的指令,例如 LPUSH、LPOP 等。
Spring Data Redis 提供了两种方式操作 Redis:
- Operations API:更高层次的抽象,封装了常用操作。
- Commands API:更底层的命令接口,允许直接调用 Redis 原始命令。
6.1. 获取命令接口
通过 ReactiveRedisConnectionFactory
获取 ReactiveKeyCommands
和 ReactiveStringCommands
实例:
@Bean
public ReactiveKeyCommands keyCommands(ReactiveRedisConnectionFactory
reactiveRedisConnectionFactory) {
return reactiveRedisConnectionFactory.getReactiveConnection().keyCommands();
}
@Bean
public ReactiveStringCommands stringCommands(ReactiveRedisConnectionFactory
reactiveRedisConnectionFactory) {
return reactiveRedisConnectionFactory.getReactiveConnection().stringCommands();
}
6.2. SET 与 GET 命令示例
使用 ReactiveStringCommands
可以批量执行 SET 命令,然后通过 ReactiveKeyCommands
获取匹配的 key:
@Test
public void givenFluxOfKeys_whenPerformOperations_thenPerformOperations() {
Flux<SetCommand> keys = Flux.just("key1", "key2", "key3", "key4");
.map(String::getBytes)
.map(ByteBuffer::wrap)
.map(key -> SetCommand.set(key).value(key));
StepVerifier.create(stringCommands.set(keys))
.expectNextCount(4L)
.verifyComplete();
Mono<Long> keyCount = keyCommands.keys(ByteBuffer.wrap("key*".getBytes()))
.flatMapMany(Flux::fromIterable)
.count();
StepVerifier.create(keyCount)
.expectNext(4L)
.verifyComplete();
}
⚠️ 注意:Commands API 是低层接口,使用的是字节流(ByteBuffer
)而不是对象,更贴近 Redis 原生行为。
7. 总结
本教程介绍了 Spring Data Redis 的响应式模板 ReactiveRedisTemplate
的基本使用方法,包括列表操作、对象存储、过期时间设置以及底层命令接口的使用。
完整的示例代码可以在 GitHub 上获取。