Spring Data Redis 从入门到实战:简化 Redis 操作全解析

一、学习目标

  • 掌握 Spring Data Redis 核心使用方式
  • 学会使用 Spring Data Redis 缓存首页内容(实战场景)

二、Spring Data Redis 核心介绍

2.1 Spring Data 整体介绍

Spring Data 是一款用于简化数据库访问的开源框架,核心目标是让数据访问更便捷、高效,包含多个子项目:

  • Spring Data JDBC:对 JDBC 的 Spring Data 存储库支持
  • Spring Data JPA:对 JPA 的 Spring Data 存储库支持
  • Spring Data MongoDB:对 MongoDB 的基于 Spring 对象文档的存储库支持
  • Spring Data Redis:从 Spring 应用程序轻松配置和访问 Redis

2.2 Spring Data Redis 核心优势

Spring Data Redis 是 Spring Data 旗下模块,专门用于简化 Redis 操作,针对 Jedis 提供了核心能力:

  1. 高度封装的RedisTemplate类,覆盖 Redis 五大数据结构操作:

    java

    复制代码
    redisTemplate.opsForValue():操作字符串
    redisTemplate.opsForHash():操作hash
    redisTemplate.opsForList():操作list
    redisTemplate.opsForSet():操作set
    redisTemplate.opsForZSet():操作zset
  2. SpringBoot2.x 后默认采用 Lettuce 客户端(基于 Netty 的异步非阻塞 IO),高并发场景下效率优于 Jedis

  3. 内置多种序列化器,适配不同数据存储场景:

序列化器 说明
JdkSerializationRedisSerializer POJO 对象存取,基于 JDK 序列化机制,存储字节序列,最常用
StringRedisSerializer 键 / 值为字符串场景,轻量级、高效,基于指定字符集编码解码
GenericJackson2JsonRedisSerializer POJO 与 JSON 互转,存储 JSON 格式,可读性高,无乱码问题

三、Spring Data Redis 实战使用

3.1 工程搭建

(1)创建工程
(2)POM 依赖配置

xml

复制代码
<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <groupId>com.hg</groupId>
    <artifactId>springdata_redis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 编码配置 -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <!-- JDK版本 -->
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>

    <dependencies>
        <!-- SpringBoot Web启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring Data Redis启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- 测试启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
</project>
(3)application.yml 配置

yaml

复制代码
spring:
  redis:
    cluster:
      nodes:
        - 192.168.204.131:7001
        - 192.168.204.131:7002
        - 192.168.204.131:7003
        - 192.168.204.131:7004
        - 192.168.204.131:7005
        - 192.168.204.131:7006
    jedis:
      pool:
        max-active: 20 # 连接池最大连接数
        max-idle: 10   # 连接池最大空闲连接
        min-idle: 5    # 连接池最小空闲连接
(4)核心配置类

java

复制代码
package com.hg.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.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis整合配置类
 */
@Configuration
public class RedisConfig {

    /**
     * 创建RedisTemplate:用于执行Redis操作的核心模板
     */
    @Bean
    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory)    {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        return template;
    }
}
(5)启动类

运行

复制代码
package com.hg;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}
}

3.2 实体类准备

java

复制代码
package com.hg.pojo;

import java.io.Serializable;

public class User implements Serializable {
	
	private Integer id;
	private String name;
	private Integer age;
	
	// getter/setter 方法
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
}

3.3 基础操作测试

java

复制代码
package com.hg.test;

import com.hg.App;
import com.hg.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {App.class})
public class RedisTest {

    // 默认key-value序列化器:JdkSerializationRedisSerializer
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 1、StringRedisSerializer:字符串类型数据操作
     */
    @Test
    public void testSetStr(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.opsForValue().set("str", "张三丰");
    }

    @Test
    public void testGetStr(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        String str = (String) redisTemplate.opsForValue().get("str");
        System.out.println(str);
    }

    /**
     * 2、JdkSerializationRedisSerializer:POJO对象序列化(字节序列)
     */
    @Test
    public void testSetPojo(){
        User user = new User();
        user.setId(1);
        user.setName("张三丰");
        user.setAge(140);

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.opsForValue().set("user", user);
    }

    @Test
    public void testGetPojo(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        User user = (User) redisTemplate.opsForValue().get("user");
        System.out.println(user);
    }

    /**
     * 3、GenericJackson2JsonRedisSerializer:POJO转JSON存储(无乱码)
     */
    @Test
    public void testSetPojo2(){
        User user = new User();
        user.setId(1);
        user.setName("张三丰");
        user.setAge(140);

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.opsForValue().set("user2", user);
    }

    @Test
    public void testGetPojo2(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        User user2 = (User) redisTemplate.opsForValue().get("user2");
        System.out.println(user2);
    }

    /**
     * 4、GenericJackson2JsonRedisSerializer处理字符串
     */
    @Test
    public void testSetStr2(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.opsForValue().set("str2", "张三丰");
    }

    @Test
    public void testGetStr2(){
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        String str2 = (String) redisTemplate.opsForValue().get("str2");
        System.out.println(str2);
    }

    /**
     * 5、默认序列化器操作POJO
     */
    @Test
    public void testSetPojo3(){
        User user = new User();
        user.setId(1);
        user.setName("张三丰");
        user.setAge(140);

        redisTemplate.opsForValue().set("user3", user);
    }

    @Test
    public void testGetPojo3(){
        User user3 = (User) redisTemplate.opsForValue().get("user3");
        System.out.println(user3);
    }
}

3.4 问题优化:设置通用序列化器

问题:每次存取 POJO 都要重复设置序列化器,开发效率低。

解决方案:在配置类中统一设置序列化器:

java

复制代码
package com.hg.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 RedisConfig {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(factory);

        // 全局序列化器配置
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        
        return redisTemplate;
    }
}

3.5 进阶优化:封装 RedisClient(贴近原生命令)

问题:RedisTemplate 封装的 API 与 Redis 原生命令不一致,使用成本高。

解决方案:封装通用 RedisClient 工具类:

java

复制代码
package com.hg.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * RedisTemplate 封装工具类(贴近原生命令)
 */
@Component
public class RedisClient {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 指定缓存失效时间
     * @param key 键
     * @param time 时间(秒)
     * @return 是否成功
     */
    public boolean expire(String key,long time){
        try {
            if(time>0){
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key获取过期时间
     * @param key 键(非空)
     * @return 过期时间(秒),0代表永久有效
     */
    public long ttl(String key){
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true=存在,false=不存在
     */
    public Boolean exists(String key){
        return redisTemplate.hasKey(key);
    }

    //============================String=============================
    /**
     * 普通缓存获取
     * @param key 键
     * @return 值
     */
    public Object get(String key){
        return key==null?null:redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     * @param key 键
     * @param value 值
     * @return true=成功,false=失败
     */
    public boolean set(String key,Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @param key 键(可传多个)
     */
    public Boolean del(String key){
       return redisTemplate.delete(key);
    }

    /**
     * 递增
     * @param key 键
     * @param delta 递增因子(>0)
     * @return 递增后的值
     */
    public long incr(String key, long delta){
        if(delta<0){
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     * @param key 键
     * @param delta 递减因子(>0)
     * @return 递减后的值
     */
    public long decr(String key, long delta){
        if(delta<0){
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().decrement(key, -delta);
    }

    //================================Hash=================================
    /**
     * Hash获取指定字段值
     * @param key 键(非空)
     * @param item 字段(非空)
     * @return 值
     */
    public Object hget(String key,String item){
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * Hash放入指定字段值
     * @param key 键
     * @param item 字段
     * @param value 值
     * @return true=成功,false=失败
     */
    public boolean hset(String key,String item,Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除Hash中指定字段
     * @param key 键(非空)
     * @param item 字段(可传多个,非空)
     */
    public void hdel(String key, Object... item){
        redisTemplate.opsForHash().delete(key,item);
    }

    //============================Set=============================
    /**
     * 根据key获取Set所有值
     * @param key 键
     * @return Set集合
     */
    public Set<Object> smembers(String key){
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Set添加值
     * @param key 键
     * @param values 值(可传多个)
     * @return 成功添加个数
     */
    public long sadd(String key, Object...values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * Set移除指定值
     * @param key 键
     * @param values 值(可传多个)
     * @return 移除个数
     */
    public long srem(String key, Object ...values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    //===============================List=================================
    /**
     * 获取List缓存内容
     * @param key 键
     * @param start 开始索引
     * @param end 结束索引(0到-1代表所有)
     * @return List集合
     */
    public List<Object> lrange(String key, long start, long end){
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * List右侧添加元素
     * @param key 键
     * @param value 值
     * @return true=成功,false=失败
     */
    public boolean rpush(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * List批量添加元素
     * @param key 键
     * @param value 值列表
     * @return true=成功,false=失败
     */
    public boolean lpush(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * List移除指定值
     * @param key 键
     * @param count 移除个数
     * @param value 值
     * @return 移除个数
     */
    public long lrem(String key,long count,Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}

四、总结

  1. Spring Data Redis 核心是RedisTemplate,封装了 Redis 五大数据结构的操作,简化了 Redis 客户端的使用
  2. 序列化器选择:字符串用StringRedisSerializer,POJO 推荐用GenericJackson2JsonRedisSerializer(无乱码、可读性高)
  3. 通过配置类统一设置序列化器,避免重复编码;封装 RedisClient 可让 API 更贴近 Redis 原生命令,降低使用成本
  4. SpringBoot2.x 后默认使用 Lettuce 客户端,高并发场景下性能更优,可结合连接池进一步优化 Redis 操作效率
相关推荐
zzginfo2 小时前
javascript 类定义常见注意事项
开发语言·前端·javascript
SomeB1oody2 小时前
【Python深度学习】1.1. 多层感知器MLP(人工神经网络)介绍
开发语言·人工智能·python·深度学习·机器学习
希望永不加班2 小时前
SpringBoot 多数据源配置(读写分离基础)
java·spring boot·后端·spring
天下无贼!2 小时前
【功能实现】基于Vue3+TS实现大文件分片上传
开发语言·javascript·node.js·vue·html5
程序员小寒2 小时前
JavaScript设计模式(九):工厂模式实现与应用
开发语言·前端·javascript·设计模式
派大星酷2 小时前
线程池-----Executors
java·开发语言
小碗羊肉2 小时前
【从零开始学Java | 第二十八篇】可变参数
java·开发语言
Java成神之路-2 小时前
Spring AOP 核心进阶:切入点表达式 + 通知类型 + 环绕通知避坑指南(Spring系列8)
java·后端·spring
weitingfu2 小时前
Excel VBA 入门到精通(二):变量、数据类型与运算符
java·大数据·开发语言·学习·microsoft·excel·vba