跳到主要内容

通过 RedisTemplate 操作对象

DeepSeek V3 中英对照 RedisTemplate Working with Objects through RedisTemplate

大多数用户可能会使用 RedisTemplate 及其对应的包 org.springframework.data.redis.core,或者其响应式变体 ReactiveRedisTemplate。实际上,模板是 Redis 模块的核心类,因为它提供了丰富的功能集。该模板为 Redis 交互提供了高级抽象。虽然 [Reactive]RedisConnection 提供了接受和返回二进制值(byte 数组)的低级方法,但模板负责序列化和连接管理,使用户无需处理这些细节。

RedisTemplate 类实现了 RedisOperations 接口,而其响应式变体 ReactiveRedisTemplate 则实现了 ReactiveRedisOperations 接口。

备注

[Reactive]RedisTemplate 实例上引用操作的首选方式是通过 [Reactive]RedisOperations 接口。

此外,该模板提供了操作视图(遵循 Redis 命令 参考 的分组),为针对特定类型或特定键的操作提供了丰富的通用化接口(通过 KeyBound 接口),如下表所述:

操作视图

接口描述
键类型操作
GeoOperationsRedis 地理空间操作,例如 GEOADD, GEORADIUS,…​
HashOperationsRedis 哈希操作
HyperLogLogOperationsRedis HyperLogLog 操作,例如 PFADD, PFCOUNT,…​
ListOperationsRedis 列表操作
SetOperationsRedis 集合操作
ValueOperationsRedis 字符串(或值)操作
ZSetOperationsRedis 有序集合(或 zset)操作
键绑定操作
BoundGeoOperationsRedis 键绑定地理空间操作
BoundHashOperationsRedis 哈希键绑定操作
BoundKeyOperationsRedis 键绑定操作
BoundListOperationsRedis 列表键绑定操作
BoundSetOperationsRedis 集合键绑定操作
BoundValueOperationsRedis 字符串(或值)键绑定操作
BoundZSetOperationsRedis 有序集合(或 zset)键绑定操作

一旦配置完成,模板是线程安全的,并且可以在多个实例中重复使用。

RedisTemplate 在大多数操作中使用基于 Java 的序列化器。这意味着通过模板写入或读取的任何对象都会通过 Java 进行序列化和反序列化。

你可以在模板上更改序列化机制,Redis 模块提供了多种实现,这些实现位于 org.springframework.data.redis.serializer 包中。有关更多信息,请参阅序列化器。你还可以将任何一个序列化器设置为 null,并通过将 enableDefaultSerializer 属性设置为 false 来使用原始字节数组的 RedisTemplate。请注意,模板要求所有键都不能为 null。然而,只要底层的序列化器允许,值可以为 null。有关更多信息,请阅读每个序列化器的 Javadoc。

对于需要特定模板视图的情况,可以将视图声明为依赖项并注入模板。容器会自动执行转换,从而消除 opsFor[X] 调用,如下例所示:

@Configuration
class MyConfig {

@Bean
LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}

@Bean
RedisTemplate<String, String> redisTemplate(RedisConnectionFactory connectionFactory) {

RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
return template;
}
}
java
public class Example {

// inject the actual operations
@Autowired
private RedisOperations<String, String> operations;

// inject the template as ListOperations
@Resource(name="redisTemplate")
private ListOperations<String, String> listOps;

public void addLink(String userId, URL url) {
listOps.leftPush(userId, url.toExternalForm());
}
}
java

专注于字符串的便捷类 {#redis:string}

由于在 Redis 中存储的键和值通常是 java.lang.String 类型,Redis 模块提供了对 RedisConnectionRedisTemplate 的两个扩展,分别是 StringRedisConnection(及其 DefaultStringRedisConnection 实现)和 StringRedisTemplate,作为密集型字符串操作的便捷一站式解决方案。除了绑定到 String 类型的键之外,该模板和连接在底层使用了 StringRedisSerializer,这意味着存储的键和值是人类可读的(假设 Redis 和你的代码使用了相同的编码)。以下清单展示了一个示例:

@Configuration
class RedisConfiguration {

@Bean
LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}

@Bean
StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {

StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
java
public class Example {

@Autowired
private StringRedisTemplate redisTemplate;

public void addLink(String userId, URL url) {
redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
}
}
java

与其他 Spring 模板一样,RedisTemplateStringRedisTemplate 允许你通过 RedisCallback 接口直接与 Redis 进行交互。这一特性为你提供了完全的控制权,因为它直接与 RedisConnection 进行通信。需要注意的是,当使用 StringRedisTemplate 时,回调接收的是一个 StringRedisConnection 的实例。以下示例展示了如何使用 RedisCallback 接口:

public void useCallback() {

redisOperations.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
Long size = connection.dbSize();
// Can cast to StringRedisConnection if using a StringRedisTemplate
((StringRedisConnection)connection).set("key", "value");
}
});
}
java

序列化器 {#redis:serializer}

从框架的角度来看,Redis 中存储的数据只是字节。虽然 Redis 本身支持多种类型,但在大多数情况下,这些类型指的是数据的存储方式,而不是它所代表的内容。由用户决定是否将这些信息转换为字符串或其他对象。

在 Spring Data 中,用户(自定义)类型与原始数据之间的转换(以及反之)由 Spring Data Redis 中的 org.springframework.data.redis.serializer 包处理。

这个包包含两种类型的序列化器,顾名思义,它们负责处理序列化过程:

  • 基于 RedisSerializer 的双向序列化器。

  • 使用 RedisElementReaderRedisElementWriter 的元素读写器。

这些变体的主要区别在于,RedisSerializer 主要将数据序列化为 byte[],而 reader 和 writer 使用 ByteBuffer

有多种实现方式可供选择(包括本文档中已经提到的两种):

然而,可以通过 Spring 的 OXM 支持使用 OxmSerializer 进行对象/XML 映射,或者使用 Jackson2JsonRedisSerializerGenericJackson2JsonRedisSerializerJSON 格式存储数据。

请注意,存储格式不仅限于值。它可以不受任何限制地用于键、值或哈希。

注意

默认情况下,RedisCacheRedisTemplate 配置为使用 Java 原生序列化。Java 原生序列化以允许通过利用易受攻击的库和类注入未经验证的字节码的负载来运行远程代码而闻名。在反序列化步骤中,被操纵的输入可能导致在应用程序中运行不需要的代码。因此,不要在不受信任的环境中使用序列化。一般来说,我们强烈建议使用其他任何消息格式(如 JSON)代替。

如果您担心由于 Java 序列化导致的安全漏洞,请考虑在核心 JVM 级别使用通用序列化过滤机制: