第五章:Redis 的 Java 客户端

第五章:Redis 的 Java 客户端


📺 对应集数:p016p023(第1522集)

第五章:Redis 的 Java 客户端

5.1 三大 Java 客户端对比

客户端 特点 适用场景
Jedis 方法名 = Redis 命令名,学习成本低;线程不安全,需用连接池 简单使用,快速上手
Lettuce 基于 Netty,支持同步/异步/响应式编程;线程安全;Spring 默认使用 Spring 生态,响应式编程
Redisson 基于 Redis 实现分布式工具类(分布式锁、Map、队列等) 分布式环境下的工具需求

5.2 Jedis 快速入门

引入依赖
xml 复制代码
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.7.0</version>
    <scope>test</scope>
</dependency>
基本使用(4 步)
java 复制代码
public class JedisTest {

    private Jedis jedis;

    @BeforeEach
    void setUp() {
        // 第1步:建立连接
        jedis = new Jedis("192.168.150.101", 6379);
        // 设置密码
        jedis.auth("123321");
        // 选择数据库
        jedis.select(0);
    }

    @Test
    void testString() {
        // 第2步:操作数据(方法名 = 命令名)
        jedis.set("name", "虎哥");
        String result = jedis.get("name");
        System.out.println("result = " + result);
    }

    @Test
    void testHash() {
        jedis.hset("user:1", "name", "Jack");
        jedis.hset("user:1", "age", "21");
        Map<String, String> map = jedis.hgetAll("user:1");
        System.out.println(map);
    }

    @AfterEach
    void tearDown() {
        // 第3步:释放资源
        if (jedis != null) {
            jedis.close();
        }
    }
}
Jedis 连接池
java 复制代码
public class JedisConnectionFactory {

    private static final JedisPool jedisPool;

    static {
        // 配置连接池
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(8);           // 最大连接数
        config.setMaxIdle(8);            // 最大空闲连接
        config.setMinIdle(0);            // 最小空闲连接
        config.setMaxWaitMillis(1000);   // 等待时长(毫秒)

        // 创建连接池
        jedisPool = new JedisPool(config, "192.168.150.101", 6379, 1000, "123321");
    }

    // 获取 Jedis 对象
    public static Jedis getJedis() {
        return jedisPool.getResource();
    }
}

// 使用方式
@Test
void testPool() {
    Jedis jedis = JedisConnectionFactory.getJedis();
    jedis.set("name", "虎哥");
    System.out.println(jedis.get("name"));
    jedis.close();  // 底层不会真的关闭,而是归还到连接池
}

5.3 Spring Data Redis

简介
  • Spring Data 是 Spring 中数据操作的统一模块
  • Spring Data Redis 对 Jedis 和 Lettuce 进行了整合
  • 提供 RedisTemplate 作为统一的操作 API
  • 支持自动序列化/反序列化(JDK、JSON 等)
  • 支持 Redis 的发布订阅、哨兵、集群等高级功能
RedisTemplate 的设计
java 复制代码
// RedisTemplate 提供了分组操作 API
RedisTemplate.opsForValue()   // → String 类型操作
RedisTemplate.opsForHash()    // → Hash 类型操作
RedisTemplate.opsForList()    // → List 类型操作
RedisTemplate.opsForSet()     // → Set 类型操作
RedisTemplate.opsForZSet()    // → SortedSet 类型操作
快速入门

引入依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

配置文件(application.yml):

yaml 复制代码
spring:
  redis:
    host: 192.168.150.101
    port: 6379
    password: 123321
    database: 0
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 1000ms

注入使用:

java 复制代码
@SpringBootTest
class RedisTemplateTest {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Test
    void testString() {
        // 获取 Value 操作对象
        redisTemplate.opsForValue().set("name", "虎哥");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println(name);
    }
}

5.4 RedisTemplate 的序列化问题

默认序列化的问题

RedisTemplate 默认使用 JDK 序列化(JdkSerializationRedisSerializer),会导致:

  1. 可读性差:数据在 Redis 中变成二进制乱码
  2. 内存占用大:包含额外的类信息
方案一:自定义 RedisTemplate(自动 JSON 序列化)
java 复制代码
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // Key 和 HashKey 使用 String 序列化
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);

        // Value 和 HashValue 使用 JSON 序列化
        GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
        template.setValueSerializer(jsonSerializer);
        template.setHashValueSerializer(jsonSerializer);

        return template;
    }
}

优点 :自动序列化/反序列化,代码简洁
缺点:JSON 中会携带 Java 类型信息(@class 字段),占用额外空间

方案二:使用 StringRedisTemplate(手动 JSON 序列化)⭐推荐
java 复制代码
@SpringBootTest
class StringRedisTemplateTest {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // JSON 工具
    private static final ObjectMapper mapper = new ObjectMapper();

    @Test
    void testSaveUser() throws JsonProcessingException {
        // 创建对象
        User user = new User("虎哥", 21);
        // 手动序列化为 JSON 字符串
        String json = mapper.writeValueAsString(user);
        // 存入 Redis
        stringRedisTemplate.opsForValue().set("user:200", json);
    }

    @Test
    void testGetUser() throws JsonProcessingException {
        // 从 Redis 获取 JSON 字符串
        String json = stringRedisTemplate.opsForValue().get("user:200");
        // 手动反序列化为对象
        User user = mapper.readValue(json, User.class);
        System.out.println(user);
    }
}

优点 :Redis 中数据简洁干净,节省存储空间
缺点:需要手动序列化/反序列化(可封装工具类)

两种序列化方案对比
对比项 自定义 RedisTemplate StringRedisTemplate
序列化方式 自动 JSON 序列化 需手动 JSON 序列化
Redis 中存储 JSON + 类型信息 纯 JSON
代码复杂度 配置简单 需手动处理序列化
内存占用 较大(含 @class) 较小(纯数据)
推荐程度 ⭐⭐⭐ ⭐⭐⭐⭐

5.5 RedisTemplate 操作 Hash 类型

java 复制代码
@SpringBootTest
class HashTest {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void testHash() {
        // 添加单个字段(HSET → put)
        stringRedisTemplate.opsForHash().put("user:400", "name", "虎哥");
        stringRedisTemplate.opsForHash().put("user:400", "age", "21");

        // 获取单个字段(HGET → get)
        Object name = stringRedisTemplate.opsForHash().get("user:400", "name");
        System.out.println(name);

        // 获取所有键值对(HGETALL → entries)
        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:400");
        System.out.println(entries);

        // 获取所有 key(HKEYS → keys)
        Set<Object> keys = stringRedisTemplate.opsForHash().keys("user:400");
        System.out.println(keys);

        // 获取所有 value(HVALS → values)
        List<Object> values = stringRedisTemplate.opsForHash().values("user:400");
        System.out.println(values);
    }
}

注意 :Spring Data Redis 的方法名不同于 Redis 命令名,更接近 Java 编程习惯(如 put 对应 HSET)。


相关推荐
程序员阿伦2 小时前
谢飞机面Java大厂:音视频场景下的Spring Boot + Kafka + Redis实战三连问
spring boot·redis·kafka·java面试·音视频架构·微服务容错
毕设源码-钟学长2 小时前
【开题答辩全过程】以 基于Springboot的在线考试系统为例,包含答辩的问题和答案
java·spring boot·后端
数据皮皮侠2 小时前
1095 《中国城市统计年鉴》面板数据整理
大数据·数据库·人工智能·算法·制造
星如雨グッ!(๑•̀ㅂ•́)و✧2 小时前
Webflux onErrorStop使用
java
java1234_小锋2 小时前
Java高频面试题:RocketMQ有哪些使用场景?
java·zookeeper·java-zookeeper
wellc2 小时前
SpringCloud系列教程:微服务的未来(十四)网关登录校验、自定义过滤器GlobalFilter、GatawayFilter
java·spring cloud·微服务
dovens2 小时前
SpringBoot 集成 Activiti 7 工作流引擎
java·spring boot·后端
sinat_255487812 小时前
JSON·学习笔记
java·开发语言·笔记·算法
Bat U2 小时前
MySQL数据库|CRUD
数据库·mysql