惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
Google DeepMind News
Google DeepMind News
博客园 - 【当耐特】
量子位
博客园 - 司徒正美
爱范儿
爱范儿
Hugging Face - Blog
Hugging Face - Blog
博客园 - 聂微东
Jina AI
Jina AI
J
Java Code Geeks
腾讯CDC
大猫的无限游戏
大猫的无限游戏
V
Visual Studio Blog
I
InfoQ
D
Docker
Recent Announcements
Recent Announcements
MongoDB | Blog
MongoDB | Blog
博客园 - Franky
宝玉的分享
宝玉的分享
G
Google Developers Blog
GbyAI
GbyAI
Y
Y Combinator Blog
有赞技术团队
有赞技术团队
H
Help Net Security

Lanke

Google 账号地区是日本,ChatGPT 订阅为什么还是美元? 在 Flutter 项目里折腾苹果的液态玻璃效果 从“宅斗庶女”看极端女权 一期一会 关于梦 用 Vercel AI Gateway 给博客做一个 AI 摘要服务 Claude 搜索网页报错:Unable to verify if domain is safe to fetch 的解决方法 Flutter输入面板布局优化:键盘、表情面板与@联想的丝滑切换 再谈语言和思维 还有人记得 在2026年拥有自己的博客 为 Astro 博客添加 llms.txt 使用 LLM Wiki 作为 Hermes Agent 的记忆系统 使用Obsidian 作为 Hermes Agent 的记忆数据库 流畅的下滑关闭页面 遇到的一起生产事故 好看的鼠标样式 拖了很久的更新,还是来了 Linux · 常用日志查询命令 面试 · Java面试二 面试 · Java面试一 如何实现验证码及校验 在电脑上共存MySQL 三道前端题 「随便来点」失语症 一些碰到的面试问题 关于博客主题的自问自答 重装电脑后恢复MySQL数据 如何畅玩旮旯game之软件篇--串流 欢迎来到实力至上主义教室
Entity、DTO和VO
Lanke · 2025-05-30 · via Lanke

最近在写一个新的项目,因为打算做的正式点,不能像之前那样只是个自娱自乐的玩具,所以安全性这方面就需要注意一下。

Entity 实体类

对应数据库表的领域模型,包含完整的业务属性和关系。简单来说,它与数据库表的属性一一对应,包括这些属性的 get 和 set 方法都在其中定义。

综上,它的核心特点就是数据持久化

我之前为了省事,都是直接通过 entity 来操作数据库的,那么这就带来了一个问题,使用 entity 会将数据库中所有的字段一并返回给前端,那如果我要实现修改用户信息,这样在前后端之间进行数据交换的操作时,就会很容易暴露 entity 类,进而导致密码等重要参数的暴露。

为了解决这种安全性问题,那我们就要借助 DTO 和 VO 来对 Entity 进行解耦,只返回所需的字段。

DTO 和 VO 的区别主要是:DTO 用于数据交换,VO 用于展示数据

DTO

DTO 是一种用于在不同层次(如前端与后端、服务层与数据访问层)之间传输数据的对象,通常包含简单的字段和 getter/setter 方法,不包含业务逻辑。这里的业务逻辑指的是与业务规则、流程直接相关的代码,即数据的校验、处理。

DTO 的核心职责是数据传输。在 DTO 中可以将 Entity 类中的我们想操作的字段单独拿出来,防止其他字段的泄露。比如我想实现一个展示用户信息的接口,那为了避免密码这种重要字段的泄露,我们就可以在 DTO 中单独将用户信息的部分进行定义。

java

public class UserDTO {
    private Long id;
    private String username;
    private String email;
}

当然,虽然原则上 DTO 只能进行数据传输,但实际上现在还有很多的注解,可以帮助我们进行数据的校验,比如 @NotNull

VO

VO 是一种专门为前端视图展示设计的数据对象,它将后端的业务数据转换为前端易于处理的格式。VO 通常包含从多个领域模型或 DTO 组合而来的数据,不包含业务逻辑。

VO 的核心特点是视图展示。虽然它不能用于数据传输,但是在展示数据这方面更加友好。

java

public class UserVO {
    @Schema(description = "用户ID")
    private Long id;

    @Schema(description = "用户名")
    private String username;

    @Schema(description = "昵称")
    private String nickname;

    @Schema(description = "手机号")
    private String phone;

    @Schema(description = "邮箱")
    private String email;

    @Schema(description = "简介")
    private String introduction;

    @Schema(description = "头像URL")
    private String avatarUrl;

    @Schema(description = "角色:ADMIN(管理员),USER(普通用户)")
    private String role;

    @Schema(description = "状态:0-禁用,1-启用")
    private Integer status;

    @Schema(description = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createdAt;

    @Schema(description = "最后活跃时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime lastActiveAt;
}

实践

在实践中,我是将 DTO 和 VO 组合起来使用的,就比如说上面的,我先用 DTO 获取前端的传来的字段,再根据此字段数据进行处理,将结果以定义好的 UserVO 返回。

文章标题:Entity、DTO和VO

文章作者:Lanke

文章链接:https://blog.blueke.top/posts/894321[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。