05-Java操作Redis

五、Java 操作 Redis

  • Redis 的 Java 客户端很多,官方推荐的有三种:
    • Jedis
    • Lettuce
    • Redisson
  • Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在 Spring Boot 项目中还提供了对应的 Starter,即 spring-boot-starter-data-redis

5.1、Jedis

  • Jedis 是 Redis 的 Java 版本的客户端实现

  • 相关 maven 坐标

    • <dependencies>
      <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.8.0</version>
      </dependency>
      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      </dependency>
      </dependencies>
  • 使用 Jedis 操作 Redis 的步骤

    • ①、获取连接
    • ②、执行操作
    • ③、关闭连接
  • 示例代码

    • package com.coolman;
      import org.junit.Test;
      import redis.clients.jedis.Jedis;
      public class JedisTest {
      @Test
      public void jedisTest() {
      // 1. 连接 redis
      // 创建一个 Jedis 对象连接 Redis 数据库
      Jedis jedis = new Jedis("127.0.0.1", 6379);
      // 2. 执行操作
      // 存储数据
      jedis.set("name", "coolman");
      // 获取数据
      System.out.println(jedis.get("name"));
      // 3. 关闭连接
      jedis.close();
      }
      }

5.2、Spring Data Redis

  • Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用 Spring Data Redis 来简化 Redis 操作

  • 官网

  • 相关 maven 坐标

    • <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>2.4.8</version>
      </dependency>
    • SpringBoot 也提供了对应的 starter

    • <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>
  • Spring Data Redis 中提供了一个高度封装的类:RedisTemplate,针对 Jedis 客户端中大量 api 进行了归类封装, 将同一类型操作封装为 operation 接口,具体分类如下:

    • ValueOperations:简单 K-V 操作
    • HashOperations:针对 hash 类型的数据操作
    • ListOperations:针对 list 类型的数据操作
    • SetOperations:set 类型数据操作
    • ZSetOperations:zset 类型数据操作

提前初始化一个 SpringBoot 项目,其中的配置文件信息如下

  • spring:
    redis:
    host: 127.0.0.1
    port: 6379
    # password: 有密码你才写
    database: 0 #redis 默认有 16 个数据库, 操作的数据库是哪个
    jedis:
    pool:
    max-active: 10 #最大链接数,连接池中最多有 10 个
    max-idle: 5 # 最大空闲数 , 618 你们公司业务比较繁忙,招聘 10 个人, 3 个人有活干,空闲了 7 个人
    min-idle: 1 #最小空闲数 618 到来之前,发现只有 1 个人没活干, 赶紧去招聘。
    #举个例子: 连接池初始化 3 个链接, 客户拿走 2 个链接,空闲 1 个, 达到最小的空闲数,必须马上增加
    max-wait: 1ms #连接池最大阻塞等待时间
  • 解释说明

    • spring.redis.database:指定使用 Redis 的哪个数据库,Redis 服务启动后默认有 16 个数据库,编号分别是从 0 到 15
    • 可以通过修改 Redis 配置文件来指定数据库的数量
  • 前置步骤

    • pringdata_redis 默认帮我们创建的 RedisTemplate 对象是使用 jdk 的序列号器帮我们键与值存储到 redis 中,而 jdk 的序列号器对键与值是采用二进制的方式存储的,所以我们会看到乱码的情况。如果我们需要看得懂,那么需要修改 redistemplate 使用的序列号器才行。

    • 提供配置类如下所示

    • package com.coolman.config;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.data.redis.connection.RedisConnectionFactory;
      import org.springframework.data.redis.core.RedisTemplate;
      import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
      import org.springframework.data.redis.serializer.StringRedisSerializer;
      @Configuration
      public class MyRedisAutoConfig {
      @Bean
      public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
      RedisTemplate<Object, Object> template = new RedisTemplate();
      template.setConnectionFactory(redisConnectionFactory);
      template.setKeySerializer(new StringRedisSerializer()); //key 的序列号器
      template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // 值序列号器
      return template;
      }
      }
    • 注意事项

      • 当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,但是默认的 key 序列化器为 JdkSerializationRedisSerializer,导致我们存到 Redis 中后的数据和原始数据有差别
  • 导入相关依赖

    • <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>org.coolman</groupId>
      <artifactId>Redis-Test</artifactId>
      <version>1.0-SNAPSHOT</version>
      <properties>
      <maven.compiler.source>8</maven.compiler.source>
      <maven.compiler.target>8</maven.compiler.target>
      </properties>
      <parent>
      <artifactId>spring-boot-starter-parent</artifactId>
      <groupId>org.springframework.boot</groupId>
      <version>2.5.6</version>
      </parent>
      <dependencies>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      </dependency>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>
      <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.8.0</version>
      </dependency>
      <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.11.1</version>
      </dependency>
      <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.11.1</version>
      </dependency>
      <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.11.1</version>
      </dependency>
      </dependencies>
      <build>
      <plugins>
      <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <version>2.4.5</version>
      </plugin>
      </plugins>
      </build>
      </project>
  • 提供测试类

    • package com.coolman;
      import org.junit.jupiter.api.Test;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.data.redis.core.RedisTemplate;
      public class SpringDataRedisTest {
      @Autowired
      private RedisTemplate<String, String > redisTemplate;
      }

5.3.1、操作字符串类型数据

  • 测试代码

    • @Test
      public void stringTest() {
      // 1. 获取操作字符串类型的对象
      ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
      // 2. 执行操作字符串命令
      // 存储
      valueOperations.set("name", "嘿嘿 Boy");
      // 获取
      System.out.println(valueOperations.get("name"));
      // 设置过期时间(一分钟)
      valueOperations.set("age", "18", 1, TimeUnit.MINUTES);
      // 如果不存在 key 则添加,否则不添加
      valueOperations.setIfAbsent("name", "嘿嘿 NewBoy");
      System.out.println(valueOperations.get("name"));
      }
  • 输出结果

5.3.2、操作哈希类型数据

  • 测试代码

    • @Test
      public void hashTest() {
      //1. 获取 hash 类型客户端
      HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
      // 2. 执行 hash 操作命令
      // 存储
      hashOperations.put("coolman", "age", "18");
      hashOperations.put("coolman", "name", "you konw what i mean");
      hashOperations.put("coolman", "sex", "superBoy");
      // 取
      System.out.println(hashOperations.get("coolman", "name"));
      // 获取所有 hash_key
      Set<Object> hashSet = hashOperations.keys("coolman");
      System.out.println("所有的 hash_key 为:");
      hashSet.forEach(System.out::println);
      // 获取所有的 value
      List<Object> values = hashOperations.values("coolman");
      System.out.println("所有的 value 为:");
      values.forEach(System.out::println);
      }
  • 输出结果

5.3.3、操作列表类型数据

  • 测试代码

    • @Test
      public void listTest() {
      // 1. 获取 list 类型客户端
      ListOperations<String, String> listOperations = redisTemplate.opsForList();
      // 2. 执行 list 操作命令
      listOperations.leftPushAll("list", "s1", "s2", "s3");
      // 3. 获取所有元素
      System.out.println(listOperations.range("list", 0, -1));
      // 4. 获取元素个数
      System.out.println(listOperations.size("list"));
      }
  • 输出结果

5.3.4、操作集合类型数据

  • 测试代码

    • @Test
      public void setTest() {
      // 1. 获取 set 集合客户端
      SetOperations<String, String> setOperations = redisTemplate.opsForSet();
      // 2. 执行 set 操作命令
      // 存储
      setOperations.add("wife_set", "林志玲", "刘亦菲", "莫妮卡", "dream_wife");
      // 获取
      Set<String> wifeSet = setOperations.members("wife_set");
      wifeSet.forEach(System.out::println);
      // 删除
      setOperations.remove("wife_set", "林志玲");
      System.out.println("删除后内容如下所示:");
      Set<String> wifeSetDel = setOperations.members("wife_set");
      wifeSetDel.forEach(System.out::println);
      }
  • 输出结果

5.3.5、操作有序集合类型数据

  • 测试代码

    • @Test
      public void orderSetTest() {
      // 1. 获取有序集合类型客户端
      ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
      // 2. 执行操作
      // 添加
      zSetOperations.add("wife_z_set", "林志玲", 60);
      zSetOperations.add("wife_z_set", "刘亦菲", 98);
      zSetOperations.add("wife_z_set", "莫妮卡", 97);
      zSetOperations.add("wife_z_set", "dream_wife", 100);
      // 获取
      Set<String> wifeZSet = zSetOperations.range("wife_z_set", 0, -1);
      System.out.println("-------------------------------");
      wifeZSet.forEach(System.out::println);
      // 修改
      zSetOperations.incrementScore("wife_z_set", "刘亦菲", 100);
      System.out.println("-------------------------------");
      zSetOperations.range("wife_z_set", 0, -1).forEach(System.out::println);
      }
  • 输出结果

5.3.6、通用操作

  • 测试代码

    • @Test
      public void commonTest() {
      // 1. 获取所有键
      System.out.println(redisTemplate.keys("*"));
      // 2. 判断有无该键
      System.out.println("redisTemplate.hasKey(\"wife_set\") =" + redisTemplate.hasKey("wife_set"));
      System.out.println("redisTemplate.hasKey(\"wife\") =" + redisTemplate.hasKey("wife"));
      // 3. 获取键的类型
      System.out.println(redisTemplate.type("wife_z_set"));
      // 4. 删除键
      redisTemplate.delete("wife_z_set");
      System.out.println(redisTemplate.keys("*"));
      }
  • 输出结果