1. DTO 产生背景
传统编程模式中,我们都是通过前台请求数据,发送到业务处理 service 层,然后由调用 dao 层返回 POJO 实体类 / 部分字段,然而这种原始的请求方式带来的缺点较多:
- 如果 Hacker 通过前端的 JSON 对象解析出你的表结构,然后就可结合表结构和请求命令模拟发送请求窃取你的个人信息或者造成数据库表结构的泄露;
- 后台处理僵硬:如果前台索要的信息不止局限于该 POJO 实体类,还有其他额外信息需要注入,这时候后台处理起来就比较麻烦了;
- 多次请求耗费一定的网络资源,减缓效率;
- 前后台耦合。
DTO 应运而生,数据传输对象 DTO (Data Transfer Object) 就是将数据封装成 JavaBean,听起来好像和以前习惯封装的 POJO 类无异,其中却有着些许差异,即按需阻止 DTO 对象,页面需要的字段才进行组织,避免传输整个表的字段。
2. DTO 优点
- 避免暴露数据库表结构
- 后台处理相对灵活
- 前后台解耦:有了 DTO,就可以让 DTO 类对接前端显示界面,实体类 POJO 则与数据库对接,这样前端更改就无需修改后端实体类了,同样后端增加业务逻辑也不会改变 DTO 类。
3. 设计方式
- 根据前端显示需求建立 DTO 类
- 根据数据库表建立 POJO 实体类
- 创建数据传输工具类(从 from 类将属性赋值到 to 类)
在这个类中,可以通过反射获取 DTO 类和实体类的方法,然后遍历查找 from 对象 getter
方法的返回值和 to 对象 setter
方法参数相同的方法,回调 from 类的 get
方法获取属性值,然后将此属性值通过回调函数赋值给 to 对象。
4. 应用场景
主要用于远程调用等需要大量传输对象的地方,比如一张表有 20 个字段,那么对应的 POJO 就有 20 个属性;但是前端界面只要显示 10 个字段,客户端用 Web Service 来获取数据,就没有必要把整个 POJO 对象都传递到客户端。
这时我们可以用只含这 10 个属性的 DTO 来传递结果到客户端即可,这样也不会暴露服务端表结构,然后 DTO 到达前端页面时,就被转换为 VO。
⭐前端界面 => VO => DTO => DO => 数据库。
5. 分层领域模型规约
- DO( Data Object): 与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
- DTO( Data Transfer Object): 数据传输对象,Service 或 Manager 向外传输的对象。
- BO( Business Object): 业务对象,由 Service 层输出的封装业务逻辑的对象。
- AO( Application Object): 应用对象,在 Web 层与 Service 层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
- VO( View Object): 显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
- POJO( Plain Ordinary Java Object): POJO 专指只有
setter/getter/toString
的简单类,包括 DO/DTO/BO/VO 等。 - Query: 数据查询对象,各层接收上层的查询请求。 注意超过 2 个参数的查询封装,禁止使用 Map 类来传输。
各类模型在三层架构应用中的位置⭐
- 用户发出请求(可能是填写表单),表单的数据在展示层被匹配为 VO。
- 展示层把 VO 转换为服务层对应方法所要求的 DTO,传送给服务层。
- 服务层首先根据 DTO 的数据构造(或重建)一个 DO,调用 DO 的业务方法完成具体业务。
- 服务层把 DO 转换为持久层对应的 PO(可以使用 ORM 工具,也可以不用),调用持久层的持久化方法,把 PO 传递给它,完成持久化操作。
- 对于一个逆向操作,如读取数据,也是用类似的方式转换和传递,略。
6. 领域模型命名规约:
- 数据对象:
xxxDO
,xxx 即为数据表名。 - 数据传输对象:
xxxDTO
,xxx 为业务领域相关的名称。 - 展示对象:
xxxVO
,xxx 一般为网页名称。 - POJO 是 DO/DTO/BO/VO 的统称,禁止命名成
xxxPOJO
。
希望本文对你有所帮助🧠
欢迎在评论区留下你的看法🌊,我们一起讨论与分享🔥