优先选 JSON 序列化,因 JDK 原生序列化导致 redis-cli 不可读、跨语言不兼容、反序列化脆弱;推荐 GenericJackson2JsonRedisSerializer(泛型友好)或 Jackson2JsonRedisSerializer(单类型高性能);key 和 hashKey 必须用 StringRedisSerializer,value 依场景选 JSON 序列化器,并务必调用 afterPropertiesSet()。

优先选 JSON,除非你确定只在纯 Java 环境里用、不调试、不跨服务、不看 redis-cli 里的数据。
为什么 JDK 原生序列化在 Spring Boot 3 里基本不该用
JDK 原生序列化(JdkSerializationRedisSerializer)默认绑定在 RedisTemplate 上,但它把对象转成二进制字节流,直接导致:
- redis-cli 里看到的是乱码或不可读符号,比如
sr com.example.User... - 中文字段显示为
\u5f20\u4e09或更糟的???,不是编码问题,是根本没走 UTF-8 文本路径 - 反序列化时必须类路径完全一致,升级类字段或改包名就
InvalidClassException - 其他语言(如 Python 脚本查缓存、Node.js 做灰度)完全无法解析
它唯一优势是序列化后体积略小——但现代 Redis 内存成本远低于调试和协作成本。
GenericJackson2JsonRedisSerializer 和 Jackson2JsonRedisSerializer 怎么选
两者都基于 Jackson,但关键差异在类型信息处理:
-
GenericJackson2JsonRedisSerializer会自动在 JSON 里加@class字段,比如{"@class":"com.example.User","name":"张三"},反序列化时能还原具体类型,适合泛型场景(如Map<string object></string>),但 JSON 体积稍大、有安全风险(需配置DefaultTyping.NON_FINAL) -
Jackson2JsonRedisSerializer初始化时必须传入具体类型,如new Jackson2JsonRedisSerializer(User.class),不带@class,更干净、更快,但只能存固定类型;若存Object又不指定类型,反序列化会变成LinkedHashMap
多数业务场景建议用 GenericJackson2JsonRedisSerializer,尤其涉及多实体混存或 DTO 泛化返回时。如果明确只存一种类型(如全为 User),且对性能极度敏感,可选后者。
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
StringRedisSerializer 什么时候够用
别被名字误导:StringRedisSerializer 不只是“字符串专用”,它是 UTF-8 明文序列化器,适用于所有能转成字符串的内容:
- 键(key)必须用它——
template.setKeySerializer(new StringRedisSerializer())是硬性要求,否则中文 key 一定乱码 - 值(value)如果本身就是字符串(如 token、JSON 字符串、HTML 片段),直接用它最轻量、无反射开销、无 Jackson 依赖
- 但如果你把一个
User对象直接塞给StringRedisSerializer,会调用toString(),结果通常是com.example.User@1a2b3c,不是你想要的
所以常见组合是:StringRedisSerializer 管 key 和 hashKey,GenericJackson2JsonRedisSerializer 管 value 和 hashValue。
容易被忽略的两个坑
即使选了 JSON 序列化,以下两点不配,照样乱码或反序列化失败:
- 没显式设置
template.setHashKeySerializer(new StringRedisSerializer())——HASH结构的 field 名称(如 user:1001 的name字段)也会走默认序列化,中文 field 名就变乱码 - 没调用
template.afterPropertiesSet()—— Spring Boot 3 中部分自动配置依赖该方法触发初始化,漏掉会导致序列化器未生效,仍走 JDK 默认
真正起作用的最小配置块,就这几句,少一个都可能白配:
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet(); // 别漏!
return template;
}

















