使用 RedisTemplate 操作物件

大多數使用者可能會使用 RedisTemplate 及其對應的包 org.springframework.data.redis.core,或者其響應式變體 ReactiveRedisTemplate。實際上,由於其豐富的功能集,該模板是 Redis 模組的核心類。該模板為 Redis 互動提供了高階抽象。雖然 [Reactive]RedisConnection 提供了接受並返回二進位制值(byte 陣列)的低階方法,但該模板負責序列化和連線管理,使使用者無需處理這些細節。

RedisTemplate 類實現了 RedisOperations 介面,其響應式變體 ReactiveRedisTemplate 實現了 ReactiveRedisOperations

引用 [Reactive]RedisTemplate 例項上的操作的首選方式是透過 [Reactive]RedisOperations 介面。

此外,該模板提供了操作檢視(遵循 Redis 命令參考中的分組),這些檢視提供了豐富、泛型化的介面,用於對特定型別或特定鍵(透過 KeyBound 介面)進行操作,如下表所示

操作檢視
  • 命令式

  • 響應式

介面 描述

鍵型別操作

GeoOperations

Redis 地理空間操作,例如 GEOADDGEORADIUS 等…​

HashOperations

Redis hash 操作

HyperLogLogOperations

Redis HyperLogLog 操作,例如 PFADDPFCOUNT 等…​

ListOperations

Redis 列表操作

SetOperations

Redis set 操作

ValueOperations

Redis string(或 value)操作

ZSetOperations

Redis zset(或有序 set)操作

鍵繫結操作

BoundGeoOperations

Redis 鍵繫結地理空間操作

BoundHashOperations

Redis hash 鍵繫結操作

BoundKeyOperations

Redis 鍵繫結操作

BoundListOperations

Redis 列表鍵繫結操作

BoundSetOperations

Redis set 鍵繫結操作

BoundValueOperations

Redis string(或 value)鍵繫結操作

BoundZSetOperations

Redis zset(或有序 set)鍵繫結操作

介面 描述

鍵型別操作

ReactiveGeoOperations

Redis 地理空間操作(例如 GEOADDGEORADIUS 等)

ReactiveHashOperations

Redis hash 操作

ReactiveHyperLogLogOperations

Redis HyperLogLog 操作(例如 PFADDPFCOUNT 等)

ReactiveListOperations

Redis 列表操作

ReactiveSetOperations

Redis set 操作

ReactiveValueOperations

Redis string(或 value)操作

ReactiveZSetOperations

Redis zset(或有序 set)操作

一旦配置完成,該模板是執行緒安全的,可以在多個例項中重複使用。

RedisTemplate 對其大多數操作使用基於 Java 的序列化器。這意味著透過該模板寫入或讀取的任何物件都透過 Java 進行序列化和反序列化。

您可以更改模板上的序列化機制,Redis 模組提供了多種實現,這些實現位於 org.springframework.data.redis.serializer 包中。有關更多資訊,請參閱序列化器。您還可以將任何序列化器設定為 null,並透過將 enableDefaultSerializer 屬性設定為 false 來使用帶有原始位元組陣列的 RedisTemplate。請注意,該模板要求所有鍵非 null。但是,只要底層序列化器接受,值可以為 null。閱讀每個序列化器的 Javadoc 以獲取更多資訊。

對於需要特定模板檢視的情況,請將該檢視宣告為依賴項並注入模板。容器會自動執行轉換,從而省去了 opsFor[X] 呼叫,如下例所示

配置模板 API
  • Java 命令式

  • Java 響應式

  • XML

@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;
  }
}
@Configuration
class MyConfig {

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

  @Bean
  ReactiveRedisTemplate<String, String> ReactiveRedisTemplate(ReactiveRedisConnectionFactory connectionFactory) {
    return new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext.string());
  }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>
  <!-- redis template definition -->
  <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="redisConnectionFactory"/>
  ...

</beans>
使用 [Reactive]RedisTemplate 將項推入列表
  • 命令式

  • 響應式

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());
  }
}
public class Example {

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

  public Mono<Long> addLink(String userId, URL url) {
    return operations.opsForList().leftPush(userId, url.toExternalForm());
  }
}

字串重點的便利類

由於儲存在 Redis 中的鍵和值通常是 java.lang.String,Redis 模組為 RedisConnectionRedisTemplate 分別提供了兩個擴充套件:StringRedisConnection(及其 DefaultStringRedisConnection 實現)和 StringRedisTemplate,作為密集型字串操作的便捷一站式解決方案。除了繫結到 String 鍵外,該模板和連線在底層使用 StringRedisSerializer,這意味著儲存的鍵和值是人類可讀的(假設 Redis 和您的程式碼中使用相同的編碼)。以下列表顯示了一個示例

  • Java 命令式

  • Java 響應式

  • XML

@Configuration
class RedisConfiguration {

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

  @Bean
  StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {

    StringRedisTemplate template = new StringRedisTemplate();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
  }
}
@Configuration
class RedisConfiguration {

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

  @Bean
  ReactiveStringRedisTemplate reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) {
    return new ReactiveStringRedisTemplate<>(factory);
  }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>

  <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connection-factory-ref="redisConnectionFactory"/>

</beans>
  • 命令式

  • 響應式

public class Example {

  @Autowired
  private StringRedisTemplate redisTemplate;

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

  @Autowired
  private ReactiveStringRedisTemplate redisTemplate;

  public Mono<Long> addLink(String userId, URL url) {
    return redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
  }
}

與其他的 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");
    }
   });
}

序列化器

從框架的角度來看,儲存在 Redis 中的資料只是位元組。雖然 Redis 本身支援各種型別,但大多數情況下,這些型別指的是資料的儲存方式,而不是資料代表的含義。使用者需要決定是將資訊翻譯成字串還是任何其他物件。

在 Spring Data 中,使用者(自定義)型別與原始資料之間的轉換(反之亦然)由 Spring Data Redis 在 org.springframework.data.redis.serializer 包中處理。

該包包含兩種型別的序列化器,顧名思義,它們負責序列化過程

  • 基於 RedisSerializer 的雙向序列化器。

  • 使用 RedisElementReaderRedisElementWriter 的元素讀取器和寫入器。

這些變體之間的主要區別在於 RedisSerializer 主要序列化為 byte[],而讀取器和寫入器使用 ByteBuffer

提供了多種實現(包括本文件中已經提到的兩種)

但是,可以使用 OxmSerializer 透過 Spring OXM 支援進行物件/XML 對映,或者使用 Jackson2JsonRedisSerializerGenericJackson2JsonRedisSerializerJSON 格式儲存資料。

請注意,儲存格式不僅限於值。它可以無限制地用於鍵、值或 hash。

預設情況下,RedisCacheRedisTemplate 配置為使用 Java 原生序列化。Java 原生序列化已知會因利用漏洞庫和類注入未經驗證的位元組碼的有效載荷而導致遠端程式碼執行。惡意輸入可能導致在反序列化步驟期間在應用程式中執行不需要的程式碼。因此,不要在不受信任的環境中使用序列化。通常,我們強烈建議使用任何其他訊息格式(例如 JSON)代替。

如果您擔心 Java 序列化引起的安全漏洞,請考慮核心 JVM 級別的通用序列化過濾器機制