🌟 引言
在 Spring Boot 项目中操作 Redis,我们最常用的两个类就是:
StringRedisTemplate
RedisTemplate
但你是否遇到过这些问题?
- 为什么我存进去的对象在 Redis 里是乱码?
- 为什么
SpringUtil.getBean(RedisTemplate.class)
报错"找到两个 Bean"? - 到底该用哪个?它们有什么区别?
本文将带你彻底搞懂这两个类的 核心区别、适用场景 ,并解释那个让人头疼的 getBean
报错原因!
一、核心区别:一句话总结
类型 | StringRedisTemplate |
RedisTemplate |
---|---|---|
用途 | 专门操作字符串 | 通用模板,可操作对象 |
Key/Value 序列化 | StringRedisSerializer (UTF-8) |
JdkSerializationRedisSerializer (二进制) |
Redis 中是否可读 | ✅ 是(明文) | ❌ 否(乱码) |
是否支持 Java 对象 | ❌ 不推荐 | ✅ 是(需自定义序列化) |
✅ 简单说:
StringRedisTemplate
:存字符串,明文可读,推荐日常使用。RedisTemplate
:存对象,但默认是乱码,需优化。
二、序列化方式详解
1. StringRedisTemplate
:明文存储
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 存储
stringRedisTemplate.opsForValue().set("user:name", "张三");
✅ 在 Redis 中查看:
"user:name" -> "张三"
👉 明文可读,调试方便!
2. RedisTemplate
:默认乱码
@Autowired
private RedisTemplate redisTemplate;
User user = new User(1, "张三");
redisTemplate.opsForValue().set("user:1", user);
❌ 在 Redis 中查看:
"\xac\xed\x00\x05t\x00\x08user:1" -> "\xac\xed\x00\x05sr\x00..."
👉 全是乱码!因为使用了 JDK 序列化。
✅ 如何让 RedisTemplate
也存明文?
自定义配置,使用 JSON 序列化:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// Key 用 String 序列化
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
// Value 用 JSON 序列化(推荐!)
Jackson2JsonRedisSerializer<Object> serializer =
new Jackson2JsonRedisSerializer<>(Object.class);
template.setValueSerializer(serializer);
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
这样存进去的就是 JSON 字符串了:
"user:1" -> {"id":1,"name":"张三"}
✅ 可读!✅ 易调试!
三、SpringUtil.getBean(RedisTemplate.class)
为什么报错?
你可能写过这样的工具类:
public class SpringUtil {
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
}
然后调用:
RedisTemplate template = SpringUtil.getBean(RedisTemplate.class);
结果报错:
No qualifying bean of type 'RedisTemplate' available:
expected single matching bean but found 2
❓ 为什么会找到两个 Bean?
因为:
- 你自定义了一个
RedisTemplate
Bean(比如叫redisTemplate
) - 你还有一个
StringRedisTemplate
Bean(名字是stringRedisTemplate
)
而 StringRedisTemplate
的源码是:
public class StringRedisTemplate extends RedisTemplate<String, String>
👉 它 继承自 RedisTemplate
!
所以当你用:
getBean(RedisTemplate.class)
Spring 会查找所有 类型为 RedisTemplate
或其子类 的 Bean,于是找到了:
redisTemplate
(你自定义的)stringRedisTemplate
(StringRedisTemplate
实例)
❌ 找到两个,Spring 不知道选哪个,于是报错!
✅ 正确获取方式(推荐)
方案 1:通过名称获取(最安全)
// 获取自定义 RedisTemplate
RedisTemplate template = (RedisTemplate) SpringUtil.getBean("redisTemplate");
// 获取 StringRedisTemplate
StringRedisTemplate strTemplate = (StringRedisTemplate) SpringUtil.getBean("stringRedisTemplate");
方案 2:直接用 StringRedisTemplate.class
(唯一)
// ✅ 这个可以唯一匹配,不会冲突
StringRedisTemplate template = SpringUtil.getBean(StringRedisTemplate.class);
方案 3:使用 @Qualifier
注解
@Autowired
@Qualifier("redisTemplate") // 明确指定
private RedisTemplate redisTemplate;
四、什么时候用哪个?(适用场景)
场景 | 推荐使用 |
---|---|
存字符串、数字、JSON 字符串 | ✅ StringRedisTemplate |
存简单键值对(如 token、配置) | ✅ StringRedisTemplate |
存 Java 对象且希望可读 | ✅ RedisTemplate + JSON 序列化 |
防止缓存穿透(存空值) | ✅ StringRedisTemplate (可存 "" 或 "null" ) |
多数据源、复杂场景 | ✅ 自定义多个 RedisTemplate ,用名称区分 |
✅ 最佳实践建议
- ✅ 90% 场景下,优先使用
StringRedisTemplate
- ✅ 把对象转成 JSON 字符串再存:
JSON.toJSONString(user)
- ✅ 避免使用
getBean(RedisTemplate.class)
,改用名称或StringRedisTemplate.class
- ✅ 如果要用
RedisTemplate
,务必配置 JSON 序列化
💬 结语
StringRedisTemplate
和 RedisTemplate
看似相似,实则大有不同。理解它们的 序列化机制 和 继承关系,能帮你避免很多"Redis 乱码"、"getBean 找到多个"等经典坑。
📌 记住:
- 想简单?用
StringRedisTemplate
- 想存对象?用
RedisTemplate
+ JSON 序列化- 想安全?用
getBean("beanName")
或getBean(StringRedisTemplate.class)
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发!也欢迎在评论区分享你的 Redis 使用经验 👇