在 Java 开发中,DTO
(Data Transfer Object)和 VO
(Value Object)类通常会实现 Serializable
接口,即“序列化”。之所以这样做,有以下几个主要原因:
一、为了支持网络传输
在分布式系统、微服务架构或前后端交互中,DTO/VO
往往需要通过网络在不同服务之间传输。Java 的序列化机制可以将对象转为二进制流,从而支持网络传输。
例如:
public class UserDTO implements Serializable {
private String name;
private int age;
// getter/setter...
}
这样,UserDTO
就可以被序列化后发送给远程服务,或者通过 HTTP 传递给前端。
二、为了支持持久化存储
有时我们会将对象持久化到磁盘(如缓存、日志、数据库中的 BLOB 字段等),也需要先将对象序列化。如果 DTO/VO 不支持序列化,将无法直接存储对象。
三、为了与一些框架兼容
很多 Java 框架在内部使用了对象序列化机制,比如:
Spring:某些缓存(如使用
RedisTemplate
)可能默认会序列化对象;Dubbo / gRPC:传输参数时可能要求参数对象实现
Serializable
;Java RMI(远程方法调用):传输的对象必须可序列化。
四、防止运行时异常
即使你当前没有明确用到序列化,但某些中间件、缓存组件或远程调用框架在底层可能会自动尝试序列化,如果对象没有实现 Serializable
,运行时会抛出 java.io.NotSerializableException
异常。
总结:
原因 | 描述 |
---|---|
网络传输 | 跨服务/模块传输对象数据 |
持久化存储 | 支持将对象保存到文件、缓存、数据库中 |
框架兼容性 | 与 Spring、Redis、Dubbo 等框架协作 |
运行时安全 | 避免未序列化对象导致的运行时异常 |
因此,给 DTO 和 VO 类实现 Serializable
是一种良好的开发规范,即使当前用不上,也能提升代码的健壮性与扩展性。
二、Spring controller 返回的数据
你这个问题问得非常好,关键在于:Spring 项目中返回的是 JSON 而不是字节流,但这其实也是“序列化”的一种形式,只不过不是 Java 默认的二进制序列化。下面我来详细解释:
✅ 你看到的情况:
在 Spring 的 Controller 中,我们常写:
@GetMapping("/user")
public BaseResponse<UserVO> getUser() {
return new BaseResponse<>(...);
}
浏览器或前端收到的是 JSON 格式,比如:
{
"code": 0,
"msg": "success",
"data": {
"id": 123,
"name": "张三"
}
}
所以你会想:我返回的是对象啊,不是序列化后的字节流呀?
✅ 实际发生了什么(背后机制)
Spring Boot 的 Web 模块使用的是 HTTP 协议,默认的数据传输格式是 JSON,而不是 Java 原生的序列化。
当你返回一个 Java 对象时(比如
BaseResponse<UserVO>
),Spring 会通过
HttpMessageConverter
(通常是MappingJackson2HttpMessageConverter
)自动把 Java 对象转为 JSON 字符串,最终写入 HTTP 响应体中。
➡️ 这个过程其实就是**“对象序列化为 JSON”的过程,使用的是 Jackson(或 Gson、FastJSON 等)这种 JSON 序列化框架,而不是 Java 的 ObjectOutputStream
的二进制序列化机制**。
🟡 那为什么还要实现 Serializable
接口?
在 Web Controller 场景下,Serializable
并不是必须的!但有以下几种情况你还是可能需要它:
对象可能被缓存(比如存 Redis、放本地磁盘)
服务间远程调用(如 Dubbo)使用了 Java 序列化或其他需要对象能被序列化的协议
为了统一规范(即使现在用不上)
某些测试、调试、快照需求
✅ 总结一句话:
Spring Controller 返回对象时的“序列化”是由 Spring 自动完成的,默认是把对象 转换为 JSON 字符串(即 JSON 序列化),而不是 Java 原生的二进制序列化。
你写的 BaseResponse<>
虽然没有手动调用 Serializable
,但被 Spring 自动通过 Jackson
等库转换为 JSON,这种也是一种“序列化”,只不过形式不同(JSON vs Java 二进制)。
如你继续深入,还可以看下:
@RestController
和@ResponseBody
的作用;HttpMessageConverter
接口;MappingJackson2HttpMessageConverter
的源码或配置。