阿里巴巴 Java 开发手册解读:DO、DTO、BO、AO、VO、Query 的区别与用法
目录
- 一、六大对象的定义(阿里规约原文)
- 二、结合案例理解
- 1. DO —— 数据库对象
- 2. AO —— 应用对象
- 3. BO —— 业务对象
- 4. DTO —— 传输对象
- 5. VO —— 视图对象
- 6. Query —— 查询对象
- 三、调用链流程
- 四、总结
在 Java 企业开发中,分层架构是最常见的模式。为了让各层职责清晰,阿里巴巴 Java 开发手册明确提出了 DO、DTO、BO、AO、VO、Query 的定义和使用规范。
很多开发者初看时觉得概念相似、容易混淆,今天我们结合手册规约和一个具体案例,来彻底搞清楚它们。
一、六大对象的定义(阿里规约原文)
- DO(Data Object,数据对象):此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
- DTO(Data Transfer Object,数据传输对象):Service 或 Manager 向外传输的对象。
- BO(Business Object,业务对象):由 Service 层输出的封装业务逻辑的对象。
- AO(Application Object,应用对象):在 Web 层与 Service 层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
- VO(View Object,显示层对象):通常是 Web 向模板渲染引擎层传输的对象。
- Query(查询对象):用于封装查询请求。注意超过 2 个参数的查询必须封装成 Query 对象,禁止使用 Map 来传输。
二、结合案例理解
我们以一个简单的 用户登录与查询 需求为例,看看这些对象在实际项目里如何应用。
1. DO —— 数据库对象
数据库表 user
:
id | username | password | role_id | |
---|---|---|---|---|
1 | Tom | 123456 | tom@xx.com | 2 |
对应的 UserDO:
@Data
public class UserDO {private Long id;private String username;private String password;private String email;private Long roleId;
}
👉 作用:DO 与数据库表字段一一对应,用于 DAO 层与数据库交互。
2. AO —— 应用对象
前端发起登录请求:
{"username": "Tom","password": "123456"
}
Controller 层接收时封装成 LoginAO:
@Data
public class LoginAO {private String username;private String password;
}
👉 作用:AO 封装 Web 层的请求参数。
3. BO —— 业务对象
Service 层校验用户时,不仅需要 username
,还需要角色信息,于是封装成 UserBO:
@Data
public class UserBO {private Long id;private String username;private String email;private List<RoleDO> roles;
}
👉 作用:BO 封装业务逻辑,通常聚合多个 DO。
4. DTO —— 传输对象
如果用户数据需要传递到 订单服务,为了避免泄露密码,我们定义 UserDTO:
@Data
public class UserDTO {private Long id;private String username;private String email;
}
👉 作用:DTO 用于系统间、层间传输,保证安全性和可控性。
5. VO —— 视图对象
后端返回前端时,前端只关心展示数据:
@Data
public class UserVO {private String username;private String email;private String roleName;
}
返回结果:
{"username": "Tom","email": "tom@xx.com","roleName": "管理员"
}
👉 作用:VO 是展示层的数据对象,满足页面渲染需求。
6. Query —— 查询对象
假设有一个接口要查询用户:
条件是 用户名 + 状态 + 最小年龄 + 最大年龄,如果直接写 4 个参数很难维护。
于是我们封装一个 UserQuery:
@Data
public class UserQuery {private String username;private Integer status;private Integer minAge;private Integer maxAge;
}
👉 作用:Query 用来封装复杂查询条件,避免使用 Map
。
三、调用链流程
一个完整的调用链可以总结为:
前端请求 → AO → Service(BO) → DAO(DO) → 数据库↓DTO(跨系统传输)↓VO(返回前端)
这样,每个对象的职责就非常清晰:
- DO:数据库层
- AO:Web 入参
- BO:业务逻辑
- DTO:跨层/跨系统传输
- VO:前端展示
- Query:查询条件
四、总结
阿里规约的核心思想是 高内聚、低耦合:
- 不要让数据库对象直接暴露到前端(DO ≠ VO)。
- 不要用 Map 来传递复杂参数(用 Query)。
- 不要在 Controller 里写业务逻辑(用 BO 封装)。