DTO(数据传输对象)

一、DTO是什么

DTO (Data Transfer Object,数据传输对象)是 Java 后端开发中常见的设计模式之一。它的作用是在不同的层之间传输数据 ,特别是在网络或应用层之间进行数据交换时,提供一种简单的数据载体。DTO 本质上是一个不包含业务逻辑的纯数据对象 ,用于打包数据,便于在系统的不同部分传递。

二、DTO 的主要作用

  1. 减少数据暴露:DTO 可以精简从后端返回给前端的数据。例如,数据库实体类中可能有许多字段,但前端只需要其中的几个字段。通过使用 DTO,可以避免将所有数据(包括敏感数据)都暴露给外部。
  2. 数据封装与解耦:DTO 可以将内部数据结构(如数据库实体类)与外部 API 或视图的表示形式分离。这样即使内部数据结构发生了变化,DTO 也可以保持不变,降低耦合。
  3. 提高传输效率:在大型应用中,实体类可能包含大量字段,传输整个实体类可能会浪费带宽和资源。DTO 可以只传输必要的数据,减少不必要的网络开销。
  4. 数据格式的适配:不同层之间的数据格式可能不同,比如数据库实体类与前端要求的数据结构不同。DTO 可以适配不同层的数据格式,使得数据传输更加方便。
  5. 保持安全性:DTO 允许你控制哪些数据被暴露给外部,避免直接暴露数据库实体,从而提升安全性。

三、DTO的使用

1. DTO 的定义

DTO 通常是一个简单的 POJO(Plain Old Java Object) ,它包含需要传输的数据字段以及相应的 getter 和 setter 方法。它不包含任何业务逻辑,只负责数据的传输。

示例 :假设我们有一个 UserDTO 类,用于传输用户的部分信息。

java 复制代码
public class UserDTO {
    private String name;
    private String email;

    // 构造函数
    public UserDTO(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getter 和 Setter 方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

2. 控制层中处理服务层数据传输与前端请求的数据管理

控制层(Controller 层)是应用程序中的关键组件,负责处理前端发起的 HTTP 请求,并调用服务层执行相关的业务逻辑。控制层的主要任务是接收前端传递的数据,将其封装为 DTO(数据传输对象)后传递给服务层。同时,控制层还负责将服务层返回的 DTO 数据传递给前端。通过这种方式,控制层可以确保前端和后端之间的数据交换安全、高效。

以下两种功能的实现都在控制层。

处理来自服务层的数据传输

控制层经常需要将服务层返回的数据发送给前端。为了防止将数据库实体类直接暴露给前端,控制层使用 DTO 作为传输对象。这种方法能够精简返回的数据内容,并避免泄露敏感信息,例如用户的密码、角色等。控制层从服务层获取到 UserDTO,并将其作为响应返回给前端。

处理来自前端的数据传输

控制层不仅负责返回服务层的数据,还需要处理来自前端的输入数据。前端通常通过 HTTP 请求将数据(如 JSON 格式的用户信息)发送到后端。控制层接收这些数据,将其封装为 DTO,然后将 DTO 传递给服务层处理。这种做法确保前端提交的数据格式符合系统预期,并简化了服务层的数据处理。

示例代码

java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    // GET 请求:通过 ID 获取用户信息,并返回 DTO
    @GetMapping("/{id}")
    public UserDTO getUserById(@PathVariable Long id) {
        // 调用服务层,获取用户的 DTO
        UserDTO userDTO = userService.getUserById(id);
        return userDTO;  // 将 DTO 返回给前端
    }

    // POST 请求:接收来自前端的用户数据,创建新用户
    @PostMapping
    public ResponseEntity<String> createUser(@RequestBody UserDTO userDTO) {
        // 调用服务层,将前端传递的 DTO 传递给服务层进行处理
        userService.createUser(userDTO);
        return ResponseEntity.ok("User created successfully");  // 返回响应消息
    }
}

详细解释

  • @GetMapping("/{id}") 方法

    • 功能:这个方法接收 HTTP GET 请求,用于获取指定 ID 的用户信息。
    • 步骤 :控制层调用 userService.getUserById(id) 方法,该方法返回的是 UserDTO 对象。控制层不需要知道服务层是如何处理数据库实体的,它只接收 DTO 并将其返回给前端。
    • 作用:通过这种方式,控制层只暴露必要的用户数据(如用户名和邮箱),而不会暴露数据库中的其他敏感数据。
  • @PostMapping 方法

    • 功能 :这个方法接收 HTTP POST 请求,用于创建新用户。前端发送的用户数据被自动封装为 UserDTO 对象,并传递给服务层处理。
    • 步骤 :控制层接收到前端传递的 UserDTO,并将其传递给服务层的 createUser(userDTO) 方法。服务层负责将 DTO 转换为实体对象并保存到数据库中。
    • 作用:控制层不直接操作数据库,而是通过服务层进行业务逻辑的处理。DTO 仅用于传输数据,确保输入数据的格式和内容符合预期。

3. 服务层中的数据库实体与持久层的数据转换与管理

服务层(Service 层 )位于控制层和持久化层(Repository 层)之间。它负责应用程序的业务逻辑处理,并在数据库实体类和 DTO 之间进行数据转换。服务层从持久化层(如数据库)获取数据,并将其转换为 DTO 返回给控制层。同样地,服务层也会将控制层传递的 DTO 转换为实体类,并通过持久化层保存到数据库中。

以下两种功能的实现都在服务层。

将数据库实体类转换为 DTO 并返回给控制层

服务层负责从数据库中获取实体类,并将其转换为 DTO 对象,传递给控制层。服务层处理了所有的业务逻辑和数据转换,控制层不需要关心数据库的具体实现。这确保了控制层只接收到必要的数据,同时避免数据库细节暴露给前端。

将 DTO 转换为实体类并持久化到数据库

在接收控制层传递的 DTO 之后,服务层负责将 DTO 转换为实体类,并通过持久化层(Repository 层)保存到数据库中。服务层可以对 DTO 进行必要的验证和业务处理,然后将其转换为持久化实体类,以确保数据能够正确存储。

示例代码

java 复制代码
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    // 将 User 实体转换为 DTO 并返回给控制层
    public UserDTO getUserById(Long id) {
        // 从数据库中获取用户实体类
        User user = userRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("User not found"));
        
        // 将实体类转换为 DTO
        UserDTO userDTO = new UserDTO(user.getName(), user.getEmail());
        return userDTO;  // 返回 DTO 给控制层
    }

    // 接收 DTO 并将其转换为实体类进行保存
    public void createUser(UserDTO userDTO) {
        // 创建实体类并从 DTO 获取数据
        User user = new User();
        user.setName(userDTO.getName());
        user.setEmail(userDTO.getEmail());
        
        // 保存实体类到数据库
        userRepository.save(user);
    }
}

详细解释

  • getUserById(Long id) 方法

    • 功能 :从数据库中获取指定 ID 的 User 实体类,并将其转换为 UserDTO 对象返回给控制层。
    • 步骤
      1. 服务层调用 userRepository.findById(id) 方法,从数据库中获取用户的实体类对象。
      2. 一旦获取到 User 实体对象,服务层将其转换为 UserDTO 对象。转换过程中,服务层会提取实体类中的必要字段(如用户名和邮箱),并将这些字段封装到 DTO 中。
      3. 最后,服务层将 DTO 返回给控制层。
    • 作用:服务层承担了将数据库实体类转换为 DTO 的任务,确保控制层只接收到必要的数据,保护数据库结构的完整性。
  • createUser(UserDTO userDTO) 方法

    • 功能 :服务层接收来自控制层的 UserDTO,将其转换为 User 实体类并保存到数据库中。
    • 步骤
      1. 服务层通过 UserDTO 创建一个新的 User 实体类对象。DTO 中的字段(如 nameemail)被复制到实体类中。
      2. 实体类对象准备好后,服务层通过 userRepository.save(user) 方法将实体类持久化到数据库中。
    • 作用:服务层负责将 DTO 转换为实体类,并将数据保存到数据库中。这种方式将数据的持久化逻辑与控制层分离,增强了代码的模块化和可维护性。
  • 控制层处理服务层数据传输与前端请求的数据管理

    • 控制层通过 DTO 传输数据,确保前端只接收必要的信息,同时避免将敏感数据暴露。
    • 控制层接收前端的请求数据,通过 DTO 将其传递给服务层处理,确保输入数据的格式和内容符合预期。
  • 服务层中的数据库实体与持久层的数据转换与管理

    • 服务层负责将数据库实体类转换为 DTO,并将其返回给控制层。这种转换确保控制层只接收到需要的数据,提升数据安全性。
    • 服务层将从控制层接收的 DTO 转换为实体类,并通过持久化层保存到数据库中,保证前端提交的数据能够正确存储。
相关推荐
代码代码快快显灵1 小时前
java之异常处理
java·开发语言
茶馆大橘1 小时前
Spring Validation —— 参数校验框架
java·后端·学习·spring
阿望要努力上研究生3 小时前
若依项目搭建(黑马经验)
java·redis·node.js·maven·管理系统
一只脑洞君3 小时前
Kubernetes(K8s)的简介
java·容器·kubernetes
zygswo3 小时前
程序猿成长之路之设计模式篇——设计模式简介
java·设计模式
除了代码啥也不会4 小时前
springboot项目发送邮件
java·spring boot·spring
无敌の星仔5 小时前
一个月学会Java 第7天 字符串与键盘输入
java·开发语言·python
GGBondlctrl5 小时前
【JavaEE初阶】多线程案列之定时器的使用和内部原码模拟
java·开发语言·定时器·timer的使用·定时器代码模拟
多多*5 小时前
OJ在线评测系统 微服务高级 Gateway网关接口路由和聚合文档 引入knife4j库集中查看管理并且调试网关项目
java·运维·微服务·云原生·容器·架构·gateway