SpringBoot连接Redis
- SpringBoot连接Redis的方式
- [RedisTemplate 与 StringRedisTemplate](#RedisTemplate 与 StringRedisTemplate)
- [自定义 RedisTemplate](#自定义 RedisTemplate)
SpringBoot连接Redis的方式
引入依赖,在 pom.xml 中添加:
xml
<dependencies>
<!-- SpringBoot 整合 Redis 核心依赖 -->
<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>
<!-- SpringBoot 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
-
spring-boot-starter-data-redis 是 Spring Boot 官方提供的 Redis 整合启动器,可自动完成 Redis 相关的核心配置,开箱即用。
自动引入的关键组件:引入 Lettuce 客户端,自动配置开发中操作 Redis 的核心模板类 RedisTemplate 和 StringRedisTemplate,自动创建 RedisConnectionFactory(Redis 连接的核心工厂类),默认提供 JDK 序列化器。
需要注意的是 Lettuce 的连接实例是线程安全的,多个线程可以共享同一个连接,无需为每个线程创建新连接,早期的 Jedis 客户端连接是线程不安全的,必须通过连接池为每个线程分配独立连接,否则会出现并发问题。
-
commons-pool2 连接池依赖,为 Redis 客户端提供连接池支持,是实现 Redis 连接复用的核心依赖。
Redis 连接的创建与销毁开销很大,如果每次操作都新建连接,会严重影响性能,连接池可以提前创建一批连接,复用这些连接,大幅提升 Redis 操作的吞吐量。
-
spring-boot-starter-test 是 Spring Boot 官方提供的通用测试依赖,提供 Spring Boot 单元测试与集成测试所需的全套核心组件,可用于测试 Redis、数据库、接口等所有 Spring Boot 组件的逻辑正确性。
自动引入的核心测试组件:Java 测试框架 JUnit、Spring 整合测试核心 Spring Test(Spring TestContext)、AssertJ 断言工具(简化测试结果校验)、Mockito 模拟工具(模拟外部依赖,降低测试环境依赖)。
在 application.yml 中配置连接信息:
yml
spring:
redis:
# 基础连接信息
host: 101.201.155.5 # Redis服务端IP
port: 6379 # Redis端口
password: "" # Redis密码,无密码则留空
database: 0 # 连接的Redis数据库编号,默认0号库
timeout: 10000 # 连接超时时间,单位毫秒(默认10秒)
# ==================== 以下根据客户端类型二选一配置 ====================
# 【选项1】使用Lettuce客户端(SpringBoot默认,推荐)
lettuce:
pool:
max-active: 8 # 连接池最大连接数(默认8)
max-idle: 8 # 连接池最大空闲连接数(默认8)
min-idle: 0 # 连接池最小空闲连接数(默认0)
max-wait: -1ms # 连接池最大等待时间,-1表示无限制(默认)
# 【选项2】使用Jedis客户端(需先排除Lettuce依赖,再引入Jedis依赖)
# jedis:
# pool:
# max-active: 8
# max-idle: 8
# min-idle: 0
# max-wait: -1ms
连接测试
java
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.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testSetAndGet() {
String key = "test:key";
String value = "Hello Redis";
// 写入
redisTemplate.opsForValue().set(key, value);
// 2. 读取
Object result = redisTemplate.opsForValue().get(key);
System.out.println("读取结果: " + result);
// 3. 断言
assertEquals(value, result);
}
}

RedisTemplate 与 StringRedisTemplate
RedisTemplate
- 序列化规则
默认采用 JdkSerializationRedisSerializer(JDK 原生对象序列化器),不仅将对象的数据内容转换为字节数组,还会附加 Java 对象的元信息(如类全限定名、序列化版本号、类型标识等),其中 \xac\xed\x00\x05 是 JDK 序列化字节流的固定前缀,用于标识 JDK 序列化格式;
需要注意的是被序列化的 Java 对象必须实现 java.io.Serializable 接口,否则会抛出 NotSerializableException 异常;
序列化范围:默认对 Key、Value、HashKey、HashValue 均采用该序列化器。 - 乱码现象
在 redis-cli、Redis Desktop Manager 等客户端查看数据时出现的乱码,是解析规则不匹配造成的。
Redis 客户端默认按 UTF-8 字符串规则解析字节流,但 JDK 序列化的字节流包含非 UTF-8 编码的前缀、元信息字节,这些字节无法被 UTF-8 正常解析,从而显示为乱码符号。Key 和 Value 都会出现该现象,并且与数据是否为中文无关。 - 适用场景
需要直接存储与读取完整 Java 实体对象,且无需在 Redis 客户端直接查看数据的场景;
不推荐直接使用默认的 JDK 序列化器(可读性差、序列化体积大、版本兼容风险高),生产环境建议替换为 JSON 序列化器,既支持对象序列化,又能在客户端以 JSON 格式可读。
StringRedisTemplate
- 序列化规则
作为 RedisTemplate<String, String> 的子类,默认全维度采用 StringRedisSerializer(UTF-8 字符串序列化器),仅处理字符串类型数据,将 Java 字符串直接按 UTF-8 字符集转换为纯字节数组,无任何额外前缀和元信息;反序列化时,将字节数组按 UTF-8 直接转回字符串;
序列化范围:Key、Value、HashKey、HashValue 均采用该序列化器(全维度字符串序列化)。 - 无乱码特性
序列化与反序列化规则与 Redis 原生客户端(redis-cli)、第三方可视化工具(如 Redis Desktop Manager)的默认解析规则(UTF-8)完全一致;与 Redis 原生命令(如 incr、keys、expire)完全兼容,可直接通过命令行操作 StringRedisTemplate 存储的 Key/Value。 - 适用场景
将 Java 对象先序列化为 JSON 字符串,再存储为字符串;
存储令牌(token)、验证码、用户会话信息、配置项等纯字符串数据;
分布式锁、计数器(incr/decr)、过期缓存控制等依赖 Redis 原生命令的场景;
StringRedisTemplate 可读性强、兼容原生命令、无序列化额外开销,是生产环境的首选模板类。
但若直接给 StringRedisTemplate 传 User 对象,编译阶段就会报错,因为 StringRedisTemplate 的 opsForValue().set() 方法要求第二个参数是 String 类型,编译不通过。

要 StringRedisTemplate 能处理 User 对象,必须要先把 Object 转成 String 格式,读取时再把 String 转回 Object,如下所示:
java
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
private final ObjectMapper objectMapper = new ObjectMapper();
@Test
public void testSaveUserRight() throws JsonProcessingException {
// 创建 User 对象(Object 类型)
User user = new User(1L, "张三", 25);
// 手动把 User 对象转为 JSON 字符串
String userJson = objectMapper.writeValueAsString(user);
// 把 JSON 字符串传给 StringRedisTemplate
stringRedisTemplate.opsForValue().set("user:1", userJson);
// 读取时先取 JSON 字符串再手动转回 User 对象
String savedUserJson = stringRedisTemplate.opsForValue().get("user:1");
User savedUser = objectMapper.readValue(savedUserJson, User.class);
System.out.println(savedUser.getName());
}
}
java
public class User {
private Long id;
private String name;
private Integer age;
public User() {
}
public User(Long id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long 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;
}
}
Jackson 反序列化 JSON 为 Java 对象的核心逻辑是:先创建一个空的 User 对象(需要依赖无参构造器),再通过 setter 方法把 JSON 里的字段值赋值给空对象的属性。

使用 RedisTemplate 直接存储与取出 Object 类型数据
java
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.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testSaveUserWrong() {
// 创建待存储的 User 对象
User user = new User(1L, "张三", 25);
// 存入 Redis
String redisKey = "user:1";
redisTemplate.opsForValue().set(redisKey, user);
System.out.println("User 对象已存入 Redis,Key = " + redisKey);
// 从 Redis 取出对象(需强制类型转换为 User)
User savedUser = (User) redisTemplate.opsForValue().get(redisKey);
System.out.println("从 Redis 取出 User 对象:" + savedUser);
}
}

自定义 RedisTemplate
使用 RedisTemplate 直接存储与取出 Object 类型数据,但 RedisTemplate 会在 redis-cli、Redis Desktop Manager 等客户端查看数据时会出现乱码问题,下面进行编写自定义 RedisTemplate 可以避免这个问题,如下所示:
java
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<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 1. 创建 RedisTemplate 实例
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 2. 绑定 Redis 连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 3. 配置序列化器(解决乱码,同时支持 Java 对象序列化)
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // 键序列化器
GenericJackson2JsonRedisSerializer jacksonRedisSerializer = new GenericJackson2JsonRedisSerializer(); // 值序列化器
// 4. 设置全局序列化规则
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(jacksonRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jacksonRedisSerializer);
// 5. 初始化 RedisTemplate
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
自定义 RedisTemplate 是字符串序列化(Key/HashKey)与 JSON 序列化(Value/HashValue)的组合:
Key/HashKey 采用 StringRedisSerializer 按 UTF-8 规则明文序列化,Redis 中 Key/HashKey 均为纯字符串,无任何乱码;Value/HashValue 采用 GenericJackson2JsonRedisSerializer 序列化为标准 JSON 字符串,既解决了原生 RedisTemplate 因 JDK 二进制序列化导致的乱码问题,又保留了直接存储与读取 Java Object 的能力(无需手动转换 JSON 字符串)。