Java对象序列化在缓存中是否需要,取决于是否跨越JVM边界:Redis等远程缓存必须序列化,Caffeine等本地缓存无需序列化;应避免JDK原生序列化,优先选用FASTJSON2或Jackson,并正确配置类型处理、敏感字段过滤与空值策略。

Java 对象序列化在缓存框架中落地,核心不是“能不能序列化”,而是“要不要序列化”“用什么方式序列化”“怎么配才安全又高效”。不同缓存层级对序列化的依赖程度差异很大,不能一刀切。
先分清缓存类型:哪些必须序列化,哪些根本不用
缓存是否需要序列化,取决于它是否跨越 JVM 边界:
- Redis、Memcached 等远程缓存:必须序列化。数据要通过网络传输、写入外部存储,JVM 内存对象无法直接传递,必须转成字节流(如 JSON 字符串、二进制 blob)。
- Caffeine、Guava Cache 等本地缓存:完全不需要序列化。它们本质是带淘汰策略的 ConcurrentHashMap,对象直接引用,零序列化开销。
- EhCache(堆外/磁盘模式):仅当启用持久化到磁盘或堆外内存时才需序列化;纯堆内使用可跳过。
选序列化方案:别再默认用 JDK 自带的了
JDK 原生序列化(ObjectOutputStream)虽简单,但存在严重问题:性能差、体积大、不兼容、有反序列化漏洞风险。生产环境应避免:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- JSON 类方案(推荐 FASTJSON2 / Jackson):可读性强,调试方便,天然支持跨语言;FASTJSON2 性能接近 Protobuf,且对泛型、LocalDateTime、枚举等支持更友好。
- Protobuf / Kryo:适合高性能、低延迟场景;但需预定义 schema 或注册类,调试成本高,不适合快速迭代业务。
- 自定义二进制(如 Hessian):已逐步被社区弃用,维护性差,不建议新项目引入。
在主流缓存框架中配置序列化
关键不是写序列化代码,而是把序列化器正确注入到缓存客户端的“值处理器”中:
-
Spring Data Redis:通过
RedisTemplate设置valueSerializer,例如用GenericJackson2JsonRedisSerializer或自定义FastJson2JsonRedisSerializer,并确保ObjectMapper注册了JavaTimeModule支持时间类型。 -
Jetcache:2.7+ 版本不再内置 JSON 序列化器,需手动配置
EncodePolicy,例如传入Fastjson2ValueEncoder实现类,并指定JSONWriter.Feature.WriteClassName控制类型信息写入策略。 -
Redisson:默认使用
JsonJacksonCodec,也可切换为FstCodec或AvroJacksonCodec;注意开启enableTypeHints避免泛型擦除导致反序列化失败。
绕不开的几个实战细节
光配对序列化器还不够,这几个点常被忽略但直接影响稳定性:
-
泛型反序列化必须显式传类型:比如缓存
Map,取值时不能只写json.parseObject(str, Map.class),而要用TypeReference或ParameterizedTypeReference显式声明结构。 -
时间类型要统一处理:LocalDateTime 默认序列化成数组([2023,10,5,14,30]),前端难解析;应在 JSON 配置中设为字符串格式("2023-10-05T14:30"),并全局注册
JavaTimeModule。 -
敏感字段要过滤:用
@JSONField(serialize = false)(FASTJSON2)或@JsonIgnore(Jackson)标记密码、token 等字段,避免意外泄露到缓存里。 -
空值和 null 处理要一致:缓存空集合、null 对象时,序列化后是否保留 key?反序列化时能否还原为
Optional.empty()或空集合?这些逻辑要在编码器/解码器中明确定义。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










