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 字符串再存进去就行。

  • 优点:完全省去自定义配置,手动序列化让存储格式完全可控,非常节省空间。
  • 缺点:代码里需要多写一步序列化和反序列化,稍微繁琐一点。
相关推荐
YHL1 小时前
🚀 NestJS 后端开发实战:从设计模式到 CRUD 全栈
后端
晚安日记wanna1 小时前
接口幂等性怎么保证
后端·面试
风中的小熊生气1 小时前
Spring Boot 面试知识(一):从启动流程到 AOP 与事务失效
spring boot·后端·面试
神秘的猪头1 小时前
Gin 项目为什么要分 Handler、Service、Repository?顺便讲透接口、依赖注入与指针
后端·go
程序员cxuan1 小时前
DeepSeek V4.1 Flash 正式发布!
人工智能·后端·程序员
特立独行的猫A1 小时前
AtomMQTT Broker — 用 Rust 实现的轻量级高性能 MQTT 消息代理
前端·后端·架构
the局外人1 小时前
学习 FastAPI 的 Day 3:企业级目录与数据库迁移
后端·python·fastapi
mldong1 小时前
AI Agent 不能自己签字:用 Python 工作流引擎给 AI 加一道人类审批闸门
后端·python·agent
她的男孩1 小时前
多租户隔离怎么落地?拆完这1600行Starter源码,我把5个坑全踩明白了
java·后端·架构