Spring Boot 中 StringRedisTemplate 与 RedisTemplate 的区别与使用陷阱(附 getBean 为何报错

🌟 引言

在 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?

因为:

  1. 你自定义了一个 RedisTemplate Bean(比如叫 redisTemplate
  2. 你还有一个 StringRedisTemplate Bean(名字是 stringRedisTemplate

StringRedisTemplate 的源码是:

复制代码
public class StringRedisTemplate extends RedisTemplate<String, String>

👉 它 继承自 RedisTemplate

所以当你用:

复制代码
getBean(RedisTemplate.class)

Spring 会查找所有 类型为 RedisTemplate 或其子类 的 Bean,于是找到了:

  • redisTemplate(你自定义的)
  • stringRedisTemplateStringRedisTemplate 实例)

❌ 找到两个,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,用名称区分

✅ 最佳实践建议

  1. 90% 场景下,优先使用 StringRedisTemplate
  2. ✅ 把对象转成 JSON 字符串再存:JSON.toJSONString(user)
  3. ✅ 避免使用 getBean(RedisTemplate.class),改用名称或 StringRedisTemplate.class
  4. ✅ 如果要用 RedisTemplate,务必配置 JSON 序列化

💬 结语

StringRedisTemplateRedisTemplate 看似相似,实则大有不同。理解它们的 序列化机制继承关系,能帮你避免很多"Redis 乱码"、"getBean 找到多个"等经典坑。

📌 记住

  • 想简单?用 StringRedisTemplate
  • 想存对象?用 RedisTemplate + JSON 序列化
  • 想安全?用 getBean("beanName")getBean(StringRedisTemplate.class)

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发!也欢迎在评论区分享你的 Redis 使用经验 👇

相关推荐
Leslie_Lei2 小时前
【Eclipse】eclipse打开git拉取的项目
java·git·eclipse
AD钙奶-lalala2 小时前
RabbitMQ的核心使用示例
java·rabbitmq·java-rabbitmq
心之伊始3 小时前
Spring Cloud Gateway:构建智能API网关的终极指南
java·spring
a587693 小时前
Spring Cloud Gateway:下一代API网关的深度解析与实战指南
java·分布式·网关
华仔啊3 小时前
依赖注入用@Autowired、@Resource还是构造器?3分钟搞清Spring官方到底推荐谁
java·后端
Sally璐璐3 小时前
Go组合式继承:灵活替代方案
开发语言·后端·golang
码熔burning3 小时前
从 new 到 GC:一个Java对象的内存分配之旅
java·开发语言·jvm
Jooou3 小时前
并发:如何设计线程安全的类
java·并发
考虑考虑3 小时前
图片翻转
java·后端·java ee