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

  • 优点:完全省去自定义配置,手动序列化让存储格式完全可控,非常节省空间。
  • 缺点:代码里需要多写一步序列化和反序列化,稍微繁琐一点。
相关推荐
程序员海军5 小时前
用了两年多 GPT,我最近开始换模型了,还折腾了个求职避坑 Agent
前端·人工智能·后端
码士集团小青5 小时前
SpringBoot 集成缓存性能之王 Caffeine
spring boot·后端·缓存
excel7 小时前
IndexNow:让搜索引擎更快发现网站更新的主动通知协议
前端·后端·架构
Json____7 小时前
用 FastAPI + Vue3 打造一套完整的在线考试系统:从组卷到阅卷的业务闭环实践
后端·node.js·fastapi·it学习·wwwoop.com
小灰灰搞电子8 小时前
Rust+Slint 实现FTP客户端调试助手源码分享
开发语言·后端·rust
专业程序开发源9 小时前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
卷无止境9 小时前
面向arm64桌面客户端开发全景:语言、框架与生态
后端·python
IT_陈寒10 小时前
JavaScript的闭包陷阱,这个坑我躺了三天才爬出来
前端·人工智能·后端
用户83562907805110 小时前
如何使用 Python 对 Excel 数据进行分组和分级显示
后端·python
vx_Biye_Design10 小时前
django房屋租赁推荐系统78455-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·课程设计·express