Skip to content

Ethan,没问题!在 Java 开发(尤其是像你现在研究的 Redis、微服务、RPC 通信)中,序列化是绕不开的核心。

简单来说,序列化就是把 Java 对象变成“二进制流”或“文本”,以便在网络传输或存入磁盘;反序列化则是把这些流变回 Java 对象。

我帮你从“原生”到“主流开源”梳理了一遍,你可以根据使用场景来选:


1. Java 原生序列化 (Serializable)

这是最基础的方法,类只需要实现 java.io.Serializable 接口。

  • 实现方式:使用 ObjectOutputStreamObjectInputStream
  • 优点:自带,无需额外依赖。
  • 缺点(非常致命):
    • 性能差:产生的码流非常大。
    • 安全性极低:容易受到反序列化攻击(这也是为什么现代框架都在弃用它)。
    • 不支持跨语言:只能 Java 连 Java。

2. JSON 序列化 (目前最主流)

把对象转成 JSON 字符串。这是你目前在 Redis 配置中使用的方案。

Jackson (Spring Boot 默认)

  • 特点:功能极其强大,配置灵活,生态最好。

  • 适用场景:Spring Boot 内部、Web 开发、Redis 存储。

  • 代码参考

    Java

    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(user); // 序列化
    User user = mapper.readValue(json, User.class); // 反序列化

FastJSON / FastJSON2 (阿里出品)

  • 特点:速度极快,国内公司用得非常多。

  • 注意:历史版本安全漏洞较多,建议只用最新的 FastJSON2

    java
    // 将对象转为 JSON 字符串
    String jsonString = JSON.toJSONString(user);
    // 将 JSON 字符串转回对象
    User user = JSON.parseObject(json, User.class);

3. 二进制序列化框架 (高性能首选)

如果你在做高并发、高性能的分布式系统(比如 Dubbo 或大流量 RPC),JSON 的体积就太大了,这时需要专业的二进制序列化。

Protobuf (Google 出品)

  • 特点:体积小到极致,速度极快。
  • 原理:基于 .proto 文件定义数据结构,然后自动生成代码。
  • 缺点:使用繁琐,需要预先定义结构,不能像 JSON 那样随便写。

Kryo (追求速度的 Java 专属)

  • 特点:在 Java 内部序列化中,速度几乎是最快的,体积也非常小。
  • 注意:它不跨语言,只能用于 Java 项目之间。

Hessian

  • 特点:老牌经典,由于其稳定性和良好的跨语言支持,常作为 Dubbo 等框架的默认序列化协议。

4. 总结与选择指南

为了让你更清晰,我把它们放在一起对比:

方案速度压缩体积跨语言易用性推荐场景
Java 原生极慢极大不要用
Jackson中等极高Spring Boot/Web/Redis 首选
FastJSON2极高国内业务开发
Protobuf极快极小高性能微服务、即时通讯
Kryo极快Java 高性能计算、内部缓存

💡 给 Ethan 的小建议

由于你正在学习 RedisSpring Boot 3.x,你只需要精通 Jackson 就足够应付 90% 的场景了。

  1. 对于简单的 Key-Value:直接用 StringRedisTemplate,手动把对象转成 JSON 字符串存进去。
  2. 对于复杂的对象存储:使用你在 redisTemplate 里的那种 GenericJackson2JsonRedisSerializer 配置(或者最新的 RedisSerializer.json())。

5. 手动配置的RedisTemplate和StringRedisTemplate选择

这是一个非常深刻的工程实践问题。简单直接的回答是:会用,而且在高并发或跨语言的场景下,StringRedisTemplate 反而是主角。

虽然你配置好了全自动的 RedisTemplate<String, Object>,但它们两人在项目里是**“互补”**关系,而不是“替代”关系。


5.1 核心分水岭:@class 属性

当你使用 GenericJackson2JsonRedisSerializer 配置 RedisTemplate 时,它为了实现“全自动反序列化”,会在 JSON 里塞进一个 @class 字段:

  • RedisTemplate 存的结果

    JSON

    {
      "@class": "com.hmdp.entity.Shop",
      "id": 1,
      "name": "Ethan的咖啡店",
      "expiredTime": "2026-04-05 21:00:00"
    }
  • StringRedisTemplate 存的结果(配合手动转 JSON):

    JSON

    {
      "id": 1,
      "name": "Ethan的咖啡店",
      "expiredTime": "2026-04-05 21:00:00"
    }

为什么这个差别很重要?

  1. 跨语言兼容性:如果以后你的项目引入了 Python 或 Go 写的微服务,它们读取 Redis 时看到 @class 会一脸懵逼,因为那是 Java 特有的类路径。
  2. 存储开销:在高并发场景下,成千上万个 Key 都带上长长的包名类名,会浪费不少内存空间。
  3. 耦合度:如果以后你重构了代码,把 Shop 类改了包名,旧缓存里的 @class 路径就失效了,反序列化会直接崩掉。

5.2 什么时候选谁?(避坑指南)

我们可以根据业务需求来做选择:

✅ 推荐使用 RedisTemplate<String, Object> 的场景:

  • 快速开发:内部小项目,或者不考虑跨语言,只想写代码快,不想每次都手动 toBean
  • 深度绑定 Java 的对象:比如存取复杂的 Session、权限信息等,这些数据通常只在 Java 内部流动。

✅ 推荐使用 StringRedisTemplate 的场景:

  • 高并发/大体量数据:为了节省内存,只存纯净的 JSON。
  • 简单计数/标识:如 incr 自增(点赞数)、验证码、分布式锁。
  • 跨系统共享数据:比如你要存一个数据给前端 Node.js 渲染或者给 Python 脚本分析。
  • 黑马点评/苍穹外卖等教学项目:这些项目后期通常会教你如何手动处理 JSON,以模拟真实大厂对性能和兼容性的极致要求。

5.3 黄金组合建议

在实际的生产架构中,Ethan,你可以参考这个配置比例:

  1. 80% 的情况用 StringRedisTemplate
    • 配合我们在 JacksonConfig 里注入的 objectMapper 手动转字符串。
    • 这样虽然多写一行代码,但换来了极高的兼容性透明的数据格式
  2. 20% 的情况用 RedisTemplate
    • 用于存储一些结构极其复杂、且只有当前服务自己会用的临时对象。

5.4 总结

你配置的 RedisTemplate 是**“高级自动挡”,让你开得爽;而 StringRedisTemplate“手动挡”**,让你在复杂路况(跨语言、高并发)下有更强的掌控力。

在你的 writeCache 方法里,如果你现在已经把 JacksonConfig 配好了,我建议你尝试注入 ObjectMapper 并使用 StringRedisTemplate,这样你存进 Redis 的数据会非常漂亮且纯净。

目前在你的项目中,是否有其他部门或者其他语言编写的微服务需要读取你的 Redis 数据呢?