SpringDataRedis的序列化方式

RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,

使用默认配置的 RedisTemplate 会遇到序列化问题,根本原因在于它默认使用 JDK 序列化。这会导致两个直接的麻烦:

  1. 可读性极差:存入 Redis 的数据会变成不可读的二进制乱码,无法通过 redis-cli 等工具直观地查看和调试。
  2. 存储空间浪费:JDK 序列化会存储完整的类元信息,占用更多内存。

因此,为了获得更好的可读性和存储效率,自定义 RedisTemplate 的序列化方式就非常必要了。

自定义 RedisTemplate 配置

在项目里添加一个配置类,通常就是把 key 设为 String 序列化,value 设为 JSON 序列化。

下面是一份可以直接参考的配置模板:

java 复制代码
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 redis 的 value 值
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 启用默认类型信息,这样反序列化时能知道具体的类,否则会变成 LinkedHashMap
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // key 采用 String 的序列化方式
        template.setKeySerializer(new StringRedisSerializer());
        // value 采用 Jackson 的序列化方式
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash 的 key 也采用 String 的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        // hash 的 value 采用 Jackson 的序列化方式
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }
}

这份配置解决了前面提到的可读性问题,同时也处理了 LocalDateTime 等复杂对象的序列化,是业界比较通用的方案。

关于 Jackson 序列化器的选择

在选择具体的 JSON 序列化器时,常看到两个选项,它们的区别是这样的:

特性 Jackson2JsonRedisSerializer GenericJackson2JsonRedisSerializer
类型信息 不存储类型信息,序列化结果更简洁 自动存储类型信息(如 @class 字段)
反序列化 需要显式指定目标类型 可自动识别类型,使用更便捷
存储开销 较小 较大(需额外存储类型信息)

简单来说:

  • 如果追求存储空间效率 ,且能明确知道要反序列化的目标类型,选 Jackson2JsonRedisSerializer。
  • 如果追求使用便捷性 ,希望反序列化能自动完成,选 GenericJackson2JsonRedisSerializer。

大多数场景下,为了方便,直接用 GenericJackson2JsonRedisSerializer 就好。但需要注意,它会把数字类型(如 Long)反序列化成 Integer,取值时可能报类型转换错误,这一点需要留意。

另一种思路:StringRedisTemplate

除了自定义 RedisTemplate,还有一种更轻量的做法:使用 Spring 已经提供的 StringRedisTemplate。它的 key 和 value 都强制使用 String 序列化,你只需要在代码里手动把对象转成 JSON 字符串再存进去就行。

  • 优点:完全省去自定义配置,手动序列化让存储格式完全可控,非常节省空间。
  • 缺点:代码里需要多写一步序列化和反序列化,稍微繁琐一点。
相关推荐
小朱爱编程1237 小时前
我用 Jev 做了三个实用工具:整理标签页、分诊飞书反馈、找回 GitHub 收藏
java·开发语言·人工智能·后端·python·架构·ai编程
明月_清风8 小时前
企业买了 Codex、WorkBuddy,AI 为什么还是没落地?我用 FDE + AKA 做深度定制
人工智能·后端
喵个咪8 小时前
RushWind Admin — 用 Rust 写的企业级中后台,开源了
后端·rust·开源
喵个咪8 小时前
RushWind Admin — 契约驱动:203 条路由零手写的工程化拆解
后端·rust·开源
明月_清风8 小时前
只会 Vibe Coding 的程序员,为什么可能会被淘汰?
后端·ai编程
喵个咪9 小时前
Go 写业务,Rust 扛底盘:一套可落地的混合架构
后端·rust·go
小小张说故事9 小时前
Python logging 日志不输出?根源在 propagate 这条链上
后端·python
ZealSinger9 小时前
Go slog生产落地LevelVar与共存
开发语言·后端·golang·go
w***488210 小时前
SpringBoot整合easy-es
spring boot·后端·elasticsearch
dpharness10 小时前
踩完 dsh-ads 的四个坑,我说说虚构排名该怎么看
后端