DTO(数据传输对象)与Model类的区别解析及示例需求
Model类与DTO的区别及示例
先明确核心差异:
- Model:是业务实体类,不仅包含数据字段,还封装了和该实体相关的业务逻辑,直接服务于业务规则;
- DTO(数据传输对象):仅作为数据传输的容器,只有数据字段和基础的读写方法,完全不包含业务逻辑,用于在不同系统/层级间传递数据。
示例1:Model类(以用户业务为例)
import java.time.LocalDate; import java.time.Period; import org.mindrot.jbcrypt.BCrypt; public class UserModel { // 与用户业务相关的核心数据字段 private Long id; private String username; private String encryptedPassword; // 存储加密后的密码,属于业务敏感数据 private LocalDate birthDate; // 构造方法:初始化业务实体 public UserModel(Long id, String username, String encryptedPassword, LocalDate birthDate) { this.id = id; this.username = username; this.encryptedPassword = encryptedPassword; this.birthDate = birthDate; } // 业务逻辑方法:计算用户当前年龄(和业务规则绑定) public int calculateAge() { return Period.between(this.birthDate, LocalDate.now()).getYears(); } // 业务逻辑方法:验证用户输入的密码是否正确(业务规则实现) public boolean verifyPassword(String rawPassword) { return BCrypt.checkpw(rawPassword, this.encryptedPassword); } // 仅暴露业务允许访问的字段的getter public Long getId() { return id; } public String getUsername() { return username; } public int getAge() { return calculateAge(); } }
这个UserModel是业务层直接操作的对象,核心是承载业务逻辑:比如计算年龄、验证密码都是和用户业务强相关的规则,而非单纯存储数据。
示例2:DTO类(数据传输用)
场景1:前端注册用户时的请求DTO
import java.time.LocalDate; public class UserRegisterDTO { // 仅包含前端注册时需要提交的数据字段 private String username; private String rawPassword; // 前端传入的明文密码,仅用于传输 private String email; private LocalDate birthDate; // 空构造、全参构造:用于框架序列化/反序列化数据 public UserRegisterDTO() {} public UserRegisterDTO(String username, String rawPassword, String email, LocalDate birthDate) { this.username = username; this.rawPassword = rawPassword; this.email = email; this.birthDate = birthDate; } // 所有字段的getter/setter:仅用于读写传输的数据 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getRawPassword() { return rawPassword; } public void setRawPassword(String rawPassword) { this.rawPassword = rawPassword; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public LocalDate getBirthDate() { return birthDate; } public void setBirthDate(LocalDate birthDate) { this.birthDate = birthDate; } }
场景2:后端返回给前端的用户信息DTO
public class UserResponseDTO { // 仅包含前端需要展示的字段,隐藏敏感数据(比如加密密码) private String username; private int age; private String email; public UserResponseDTO(String username, int age, String email) { this.username = username; this.age = age; this.email = email; } // 仅提供前端需要的字段的getter public String getUsername() { return username; } public int getAge() { return age; } public String getEmail() { return email; } }
这两个DTO类没有任何业务逻辑,仅负责在前后端之间传递数据:
UserRegisterDTO用来接收前端的注册请求数据,之后业务层会把它转换成UserModel(比如对明文密码加密后存储);UserResponseDTO则是把UserModel处理后的结果,抽取出前端需要的字段返回,避免暴露敏感数据(比如加密密码)。
总结差异
| 维度 | Model类 | DTO类 |
|---|---|---|
| 核心定位 | 业务实体,承载业务逻辑 | 数据传输容器,仅传数据 |
| 逻辑包含 | 有业务逻辑方法(计算、校验等) | 无任何业务逻辑,仅get/set |
| 使用场景 | 业务层内部处理业务逻辑时使用 | 跨层/跨系统传递数据时使用 |
| 字段范围 | 包含业务所需的全部字段(含敏感字段) | 仅包含传输所需的必要字段 |
内容的提问来源于stack exchange,提问作者Dhanush S
相关产品推荐
相关产品推荐

