当前位置: 首页 > news >正文

后端开发 DTO-Entity-VO 转换模式详解

目录

🧩 一、数据流走向(总览)

⚙️ 二、DTO → Entity:在业务层中完成

⚙️ 三、Entity → VO:返回时的转换

🧠 四、关键点总结

✨ 五、推荐实践(让代码更干净)

1. 使用工具类简化拷贝

2. 把转换逻辑封装成“转换器类”

✅ 六、一句话总结


在现代 Spring Boot Web 开发中,为了实现前后端分离、保证数据安全和明确分层,我们通常会使用三种类型的 Java 对象来处理数据:DTO、Entity 和 VO。

这个模式的核心思想是:在不同的应用层之间,使用专门的对象进行数据传输。

🧩 一、数据流走向(总览)

下面是-个标准 Web 请求的数据流转过程:

前端 JSON 请求体↓
DTO(数据传输对象)     ← 【控制器层 Controller】(用于接收输入)↓
Entity(实体对象)      ← 【业务层 Service】(转换为 Entity,用于保存到数据库)↓
数据库↓
Entity(实体对象)      ← 【业务层 Service】(从数据库取出)↓
VO(视图对象)        ← 【控制器层 Controller/Service】(转换为 VO,用于封装返回前端)↓
前端 JSON 响应体

⚙️ 二、DTO → Entity:在业务层中完成

DTO (Data Transfer Object):数据传输对象。它的唯一职责是接收前端传来的数据

当 Controller 接收到前端的 JSON 请求时,Spring MVC 会自动将其封装为 DTO 对象。

// Controller
@PostMapping("/register")
public ApiResponse<Long> register(@Valid @RequestBody UserRegisterRequest dto) {// 此时,dto 对象就是前端传来的 JSON 数据// 然后我们把 dto 传给业务层Long userId = userService.register(dto);return ApiResponse.success("注册成功", userId);
}

Entity (实体):数据库实体对象。它严格对应数据库中的表结构

这一步转换发生在 Service (业务) 层。Service 层负责核心业务逻辑,它接收 DTO,然后将其转换为 Entity,并补充业务所需的其他字段(比如默认权限、初始积分、加密密码等)。

// ServiceImpl
public Long register(UserRegisterRequest dto) {// 1. 手动将 DTO 字段拷贝给 EntityUser user = new User();user.setUsername(dto.getUsername());// 业务逻辑:密码需要加密user.setPassword(passwordEncoder.encode(dto.getPassword()));// 业务逻辑:昵称默认为用户名user.setNickname(StringUtils.hasText(dto.getNickname()) ? dto.getNickname() : dto.getUsername());user.setPhone(dto.getPhone());user.setEmail(dto.getEmail());// 2. 也可以用工具类来简化拷贝// BeanUtils.copyProperties(dto, user);// (注意:使用工具类后,仍需手动处理密码加密等特殊逻辑)// 3. 补充前端不传的业务字段user.setRole("user");user.setStatus(1);user.setCreditScore(100);// 4. 通过 MyBatis-Plus 将 Entity 存入数据库save(user);return user.getId();
}

这一步的作用

  1. 把前端的请求参数(DTO)转换成数据库对应的实体对象(Entity)。

  2. 在转换过程中执行业务逻辑(如加密、设置默认值)。

⚙️ 三、Entity → VO:返回时的转换

VO (View Object):视图对象。它专门用于封装后端需要返回给前端的数据

我们通常不会直接把 Entity 返回给前端,因为 Entity 里可能包含敏感字段(比如 passwordsalt)或者前端不需要的字段(比如 is_deletedupdate_time)。

VO 的作用就是只挑选前端需要的字段。

示例:

// 专门用于前端展示的 UserVO
public class UserVO {private Long id;private String username;private String nickname;private String avatar;private String email;
}

转换可以在 Service 层完成,也可以在 Controller 层完成(推荐在 Service 层)。

// ServiceImpl 中...
// 假设我们从数据库查到了 user (Entity)
User user = getById(userId);// 1. 转换为 VO
UserVO vo = new UserVO();
vo.setId(user.getId());
vo.setUsername(user.getUsername());
vo.setNickname(user.getNickname());
vo.setAvatar(user.getAvatar());
vo.setEmail(user.getEmail());// 2. 或者同样用工具类
// BeanUtils.copyProperties(user, vo);// 3. 在 Controller 返回 VO
return ApiResponse.success("查询成功", vo);

前端最终拿到的 JSON 就会非常干净:

{"success": true,"message": "查询成功","data": {"id": 1001,"username": "tom","nickname": "Tom","avatar": "avatar/default.png","email": "tom@demo.com"}
}

🧠 四、关键点总结

转换方向

发生位置

意义

DTO → Entity

Service

把前端请求数据转换为数据库对象(用于保存

Entity → VO

ServiceController

把数据库对象转换为前端可展示的数据(用于返回

✨ 五、推荐实践(让代码更干净)

1. 使用工具类简化拷贝

手动 setget 非常繁琐且容易出错。

  • Spring 自带: BeanUtils.copyProperties(source, target);

  • 常用增强库:

    • MapStruct(推荐):在编译时自动生成类型安全的转换代码,性能极高。

    • ModelMapper:在运行时通过反射自动映射,非常灵活但性能略慢。

2. 把转换逻辑封装成“转换器类”

当转换逻辑变多时,可以创建一个专门的 Convert 类(或接口),让 Service 层保持干净。

public class UserConvert {// 使用 MapStruct 的示例// @Mapper(componentModel = "spring")// public interface UserConvert {//     UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);//     User toEntity(UserRegisterRequest dto);//     UserVO toVO(User user);// }// 手动封装的示例public static User toEntity(UserRegisterRequest dto) {User user = new User();BeanUtils.copyProperties(dto, user);// ... 其他特殊处理return user;}public static UserVO toVO(User user) {UserVO vo = new UserVO();BeanUtils.copyProperties(user, vo);return vo;}
}

然后你的 Service 代码就可以简化为:

// ServiceImpl
User user = UserConvert.toEntity(request);
// ... 处理加密等 ...
save(user);
return UserConvert.toVO(user);

✅ 六、一句话总结

环节

作用

代码位置

DTO

接收前端输入

Controller 入参

Entity

持久化到数据库

Service + Mapper

VO

返回前端展示

Controller 出参

DTO→Entity

在 Service 中转换

业务逻辑处理时

Entity→VO

在 Service 或 Controller 中转换

返回结果时

http://www.dtcms.com/a/554593.html

相关文章:

  • 做私人网站 违法设计制作生态瓶教学设计
  • snipaste免费版下载安装使用教程(附安装包)
  • 【openGauss】带有out参数的存储过程及自定义函数的重载测试
  • MATLAB高效算法实战技术文章大纲
  • 上海网站建设技术指导公司杭州知名的互联网公司
  • 从域名到网站网站建设报价单表格模板
  • 高效静电测试门禁通道闸成为静电的防线 蒙冬智能
  • 主流PD协议DRP芯片技术解析与核心优势
  • USB PD协议中的DRP技术:双向供电与数据传输的革新者
  • 局网站建设管理整改情况广西桂林
  • 从火情定位到隐患排查:三光吊舱助力救援模拟全流程
  • element-ui 2.x 及 vxe-table 2.x 使用 css 定制主题
  • 如何提高网站在搜索引擎中的排名如何建立网站视频教程
  • 广州网站建设网页设计百度地图排名可以优化吗
  • 网站做多久梧州网站设计制作服务至上
  • 凉山州住房和城乡建设厅网站王烨老师
  • Metrics Server 完整配置安装手册
  • 中小型企业建设网站六安政务中心网站
  • reactnative下拉选择
  • 操作系统基础·3 进程线程模型
  • CTFHub XSS通关2:存储型
  • 递归专题3 - 回溯算法十大类型
  • python全栈-数据分析软件tableau的使用
  • 交流电里的电子咋流动?不是往前跑,而是来回 “晃”
  • 做网站写代码怎么样免费网站建设基础步骤
  • 网站.cc域名网站常见结构有那些
  • 网上做兼职老师的正规网站搭建网站的步骤有哪些
  • python进阶教程10:面向对象、super()和元类
  • 大同建设银行保安招聘网站商品展示的网站源码
  • 中交建设集团 网站win10系统可以做网站搭建