在Spring Boot微服务使用ListOperations操作Redis List列表

记录:402

场景:在Spring Boot微服务使用RedisTemplate的ListOperations操作Redis List列表。

版本:JDK 1.8,Spring Boot 2.6.3,redis-6.2.5

1.微服务中Redis配置信息

1.1在application.yml中Redis配置信息

spring:
  redis:
    host: 192.168.19.203
    port: 28001
    password: 12345678
    timeout: 50000

1.2加载简要逻辑

Spring Boot微服务在启动时,自动注解机制会读取application.yml的注入到RedisProperties对象。在Spring环境中就能取到Redis相关配置信息了。

类全称:org.springframework.boot.autoconfigure.data.redis.RedisProperties

1.3在pom.xml添加依赖

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

2.配置RedisTemplate

2.1配置RedisTemplate

@Configuration
public class RedisConfig {
  @Bean("redisTemplate")
  public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
      // 1.创建RedisTemplate对象
      RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
      // 2.加载Redis配置
      redisTemplate.setConnectionFactory(lettuceConnectionFactory);
      // 3.配置key序列化
      RedisSerializer<?> stringRedisSerializer = new StringRedisSerializer();
      redisTemplate.setKeySerializer(stringRedisSerializer);
      redisTemplate.setHashKeySerializer(stringRedisSerializer);
      // 4.配置Value序列化
      Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
      ObjectMapper objMapper = new ObjectMapper();
      objMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
      objMapper.activateDefaultTyping(objMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
      jackson2JsonRedisSerializer.setObjectMapper(objMapper);
      redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
      redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
      // 5.初始化RedisTemplate
      redisTemplate.afterPropertiesSet();
      return redisTemplate;
  }
  @Bean
  public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
    return redisTemplate.opsForList();
  }
}

2.2解析

在配置RedisTemplate后,在Spring环境中,可以@Autowired自动注入方式注入操作Redis对象。比如:RedisTemplate、ListOperations。

3.使用ListOperations操作Redis List列表

3.1简要说明

使用ListOperationsRedis List列表,常用操作:增、查、删、设置超时等。

3.2操作示例

@RestController
@RequestMapping("/hub/example/load")
@Slf4j
public class LoadController {
  @Autowired
  private RedisTemplate redisTemplate;
  @Autowired
  private ListOperations listOperations;
  /**
   * 操作List,使用ListOperations
   * 对应写命令: LPUSH 队列名称 值
   * 对应读命令: LPOP 队列名称
   * 对应写命令: RPUSH 队列名称 值
   * 对应读命令: RPOP 队列名称
   */
  @GetMapping("/listOperations")
  public Object loadData03() {
    log.info("ListOperations操作开始...");
    // 1.增
    listOperations.leftPush("CityInfo:Hangzhou03", "杭州");
    listOperations.rightPush("CityInfo:Hangzhou03", "苏州");
    // 2.查,查出队列指定范围元素,不会删除队列里面数据,(0,-1)查出全部元素
    listOperations.leftPush("CityInfo:Hangzhou03", "杭州");
    listOperations.leftPush("CityInfo:Hangzhou03", "苏州");
    List cityList = redisTemplate.boundListOps("CityInfo:Hangzhou03").range(0, -1);
    cityList.forEach((value)->{
        System.out.println("value="+value);
    });
    // 3.取,逐个取出队列元素(取出一个元素后,队列就没有这个元素了)
    Object city01 = listOperations.leftPop("CityInfo:Hangzhou03");
    Object city02 = listOperations.rightPop("CityInfo:Hangzhou03");
    log.info("city01=" + city01 + ",city02=" + city02);
    // 4.删
    listOperations.leftPush("CityInfo:Hangzhou03", "杭州");
    listOperations.leftPush("CityInfo:Hangzhou03", "苏州");
    redisTemplate.delete("CityInfo:Hangzhou03");
    // 5.设置超时
    listOperations.leftPush("CityInfo:Hangzhou03", "上海");
    redisTemplate.boundValueOps("CityInfo:Hangzhou03").expire(5, TimeUnit.MINUTES);
    redisTemplate.expire("CityInfo:Hangzhou03", 10, TimeUnit.MINUTES);
    // 6.查询List的元素个数
    Long size =listOperations.size("CityInfo:Hangzhou03");
    System.out.println("查询List的元素个数,size="+size);
    log.info("ListOperations操作结束...");
    return "执行成功";
  }
}

3.3测试验证

使用Postman测试。

请求RUL:http://127.0.0.1:18205/hub-205-redis/hub/example/load/listOperations

4.ListOperations接口

4.1接口

ListOperations是一个接口,默认实现类是DefaultListOperations。

接口:org.springframework.data.redis.core.ListOperations。

实现类:org.springframework.data.redis.core.DefaultListOperations。

4.2接口源码

在源码中,查看接口具体方法,可以快速了解该接口具备功能,以便在生产中能根据实际场景对号入座找到合适方法解决实际问题。

public interface ListOperations<K, V> {
  @Nullable
  List<V> range(K key, long start, long end);
  void trim(K key, long start, long end);
  @Nullable
  Long size(K key);
  @Nullable
  Long leftPush(K key, V value);
  @Nullable
  Long leftPushAll(K key, V... values);
  @Nullable
  Long leftPushAll(K key, Collection<V> values);
  @Nullable
  Long leftPushIfPresent(K key, V value);
  @Nullable
  Long leftPush(K key, V pivot, V value);
  @Nullable
  Long rightPush(K key, V value);
  @Nullable
  Long rightPushAll(K key, V... values);
  @Nullable
  Long rightPushAll(K key, Collection<V> values);
  @Nullable
  Long rightPushIfPresent(K key, V value);
  @Nullable
  Long rightPush(K key, V pivot, V value);
  @Nullable
  default V move(ListOperations.MoveFrom<K> from, ListOperations.MoveTo<K> to) {
      Assert.notNull(from, "Move from must not be null");
      Assert.notNull(to, "Move to must not be null");
      return this.move(from.key, from.direction, to.key, to.direction);
  }
  @Nullable
  V move(K sourceKey, Direction from, K destinationKey, Direction to);
  @Nullable
  default V move(ListOperations.MoveFrom<K> from, ListOperations.MoveTo<K> to, Duration timeout) {
      Assert.notNull(from, "Move from must not be null");
      Assert.notNull(to, "Move to must not be null");
      Assert.notNull(timeout, "Timeout must not be null");
      Assert.isTrue(!timeout.isNegative(), "Timeout must not be negative");
      return this.move(from.key, from.direction, to.key, to.direction, TimeoutUtils.toMillis(timeout.toMillis(), TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
  }
  @Nullable
  default V move(K sourceKey, Direction from, K destinationKey, Direction to, Duration timeout) {
      Assert.notNull(timeout, "Timeout must not be null");
      Assert.isTrue(!timeout.isNegative(), "Timeout must not be negative");
      return this.move(sourceKey, from, destinationKey, to, TimeoutUtils.toMillis(timeout.toMillis(), TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
  }
  @Nullable
  V move(K sourceKey, Direction from, K destinationKey, Direction to, long timeout, TimeUnit unit);
  void set(K key, long index, V value);
  @Nullable
  Long remove(K key, long count, Object value);
  @Nullable
  V index(K key, long index);
  Long indexOf(K key, V value);
  Long lastIndexOf(K key, V value);
  @Nullable
  V leftPop(K key);
  @Nullable
  List<V> leftPop(K key, long count);
  @Nullable
  V leftPop(K key, long timeout, TimeUnit unit);
  @Nullable
  default V leftPop(K key, Duration timeout) {
      Assert.notNull(timeout, "Timeout must not be null");
      Assert.isTrue(!timeout.isNegative(), "Timeout must not be negative");
      return this.leftPop(key, TimeoutUtils.toSeconds(timeout), TimeUnit.SECONDS);
  }
  @Nullable
  V rightPop(K key);
  @Nullable
  List<V> rightPop(K key, long count);
  @Nullable
  V rightPop(K key, long timeout, TimeUnit unit);
  @Nullable
  default V rightPop(K key, Duration timeout) {
      Assert.notNull(timeout, "Timeout must not be null");
      Assert.isTrue(!timeout.isNegative(), "Timeout must not be negative");
      return this.rightPop(key, TimeoutUtils.toSeconds(timeout), TimeUnit.SECONDS);
  }
  @Nullable
  V rightPopAndLeftPush(K sourceKey, K destinationKey);
  @Nullable
  V rightPopAndLeftPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit);
  @Nullable
  default V rightPopAndLeftPush(K sourceKey, K destinationKey, Duration timeout) {
      Assert.notNull(timeout, "Timeout must not be null");
      Assert.isTrue(!timeout.isNegative(), "Timeout must not be negative");
      return this.rightPopAndLeftPush(sourceKey, destinationKey, TimeoutUtils.toSeconds(timeout), TimeUnit.SECONDS);
  }
  RedisOperations<K, V> getOperations();
  public static class MoveTo<K> {
      final K key;
      final Direction direction;
      MoveTo(K key, Direction direction) {
          this.key = key;
          this.direction = direction;
      }
      public static <K> ListOperations.MoveTo<K> toHead(K key) {
          return new ListOperations.MoveTo(key, Direction.first());
      }
      public static <K> ListOperations.MoveTo<K> toTail(K key) {
          return new ListOperations.MoveTo(key, Direction.last());
      }
  }
  public static class MoveFrom<K> {
      final K key;
      final Direction direction;
      MoveFrom(K key, Direction direction) {
          this.key = key;
          this.direction = direction;
      }
      public static <K> ListOperations.MoveFrom<K> fromHead(K key) {
          return new ListOperations.MoveFrom(key, Direction.first());
      }
      public static <K> ListOperations.MoveFrom<K> fromTail(K key) {
          return new ListOperations.MoveFrom(key, Direction.last());
      }
  }
}

以上,感谢。

2023年4月12日

猜你喜欢

转载自blog.csdn.net/zhangbeizhen18/article/details/130119502