RedisTemplate默认使用JdkSerializationRedisSerializer序列化value,导致数据不可读、体积大、跨语言不兼容且反序列化易失败;推荐改用Jackson2JsonRedisSerializer并配置ObjectMapper启用DefaultTyping和JavaTimeModule,同时需显式设置hashKey/hashValue序列化器,或选用StringRedisTemplate手动JSON编解码。

RedisTemplate 默认用 JdkSerializationRedisSerializer 序列化 value,存进去是一串不可读的二进制,反序列化还容易报 ClassNotFoundException 或 InvalidClassException。想存 User、Order 这类对象,必须换掉默认序列化器。
为什么不能直接用默认的 JdkSerializationRedisSerializer
它要求所有对象实现 Serializable,且类名、字段、serialVersionUID 一改就反序列化失败;序列化后体积大、不可读、跨语言完全不兼容。比如存一个简单 User 对象,Redis CLI 里看到的是类似 aced000573720019636f6d2e6578616d706c652e55736572... 的乱码。
GenericJackson2JsonRedisSerializer 是最稳妥的入门选择
它把对象转成 JSON 字符串再存,人类可读、跨语言友好、字段增删基本不影响反序列化(只要不删必需字段)。但要注意三点:
-
GenericJackson2JsonRedisSerializer已被标记为@Deprecated(Spring Data Redis 3.2+),应改用Jackson2JsonRedisSerializer - 必须配置
ObjectMapper启用DefaultTyping.NON_FINAL,否则反序列化时无法还原具体类型,会变成LinkedHashMap - 时间类型(
LocalDateTime等)需手动注册JavaTimeModule,否则抛JsonMappingException
示例关键代码:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
StringRedisSerializer stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
om.registerModule(new JavaTimeModule());
jsonSerializer.setObjectMapper(om);
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
template.afterPropertiesSet();
return template;
}
哈希结构(HASH)要单独配 hashKey 和 hashValue 序列化器
redisTemplate.opsForHash().put("user:1001", "profile", profileObj) 这种操作,key 是字符串(如 "profile"),value 是对象(如 Profile)。如果只设了 setValueSerializer,hashValue 仍走默认 JDK 序列化——结果就是哈希表里 value 又变乱码。
- 必须显式调用
template.setHashKeySerializer(...)和template.setHashValueSerializer(...) - 推荐统一用
StringRedisSerializer处理 hash key(毕竟一般用字符串作 field 名),用 JSON 序列化器处理 hash value - 别漏掉
template.afterPropertiesSet(),否则配置不生效
生产环境建议用 StringRedisTemplate + 手动 JSON 转换
如果你只存业务对象、不依赖 RedisTemplate 的泛型操作,StringRedisTemplate 更轻量、更可控:
- 它默认所有 key/value 都是
String,天然避免序列化陷阱 - 用
ObjectMapper.writeValueAsString(obj)存,ObjectMapper.readValue(str, User.class)取,逻辑清晰、调试方便 - 能精确控制每个字段的序列化行为(比如忽略 null、格式化日期),而不用全局配置
ObjectMapper
真正难的不是选哪种序列化器,而是保证反序列化时 classpath 里有对应类、且版本兼容——JSON 至少让你一眼看出存的是什么,出问题时不用猜字节流里藏了啥。

















