一文讲清DTO、BO、PO、VO,为什么可以不需要VO?

DTO、BO、PO、VO是什么

在讨论这些是什么的时候,建议先看看我的这篇文章:写好业务代码的经典案例 - 掘金 (juejin.cn)

在上面我的这篇文章中提到的缺乏模型抽象,无边界控制,就是正好对应的DTO BO PO VO这些模型的概念

在后端开发中,比如传统的MVC架构和现在流行的DDD架构,经常会使用到下列几种对象的概念

  • DTO (Data Transfer Object) 数据传输对象: DTO设计模式用于将数据从服务端传输到客户端,或者在不同的服务之间传递。通常,DTO包含了特定业务场景需要的数据结构,并且不包含任何业务逻辑。它简化了不同服务或模块之间的交互,使得各个层之间的耦合度降低。
  • BO (Business Object) 业务对象: BO代表了业务逻辑层中的对象,封装了与某个业务相关的数据以及针对这些数据的操作逻辑。一个BO可能由多个实体属性组成,并处理涉及多个实体的复杂业务逻辑。
  • PO (Persistent Object) 持久化对象 : PO主要用来表示数据库表的一条记录,它的属性和数据库表的字段相对应。通常在持久层(如Hibernate、JPA等ORM框架)中使用,主要用于操作数据库,如保存、更新和查询数据。
  • VO (Value Object) 值对象 : VO是视图层的对象,通常用于封装展示给用户的数据,它可以和数据库表对应,也可以根据UI界面需求进行定制。VO的主要目的是在页面展示时只携带必要的数据,从而避免把大量不必要的数据暴露给前端。

举个实际代码的例子,这里暂不给出VO,在最后的总结会讲这个VO

  • 这个就是PO
java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("sys_user")
public class User implements Serializable{
    @JsonSerialize(using = ToStringSerializer.class)
    @TableId
    private Long id;

    private String username;

    private String password;

    private String identityCard;

    private String gender;

    private String location;

    private String userImage;

    private String phoneNumber;

    private String createTime;

    private String updateTime;

    @TableLogic
    private int isDelete;
}
  • UserDTO
java 复制代码
@Data
public class UserDTO implements Serializable{
    private Long id;

    private String username;

    private String password;

    private String identityCard;

    private String gender;

    private String location;

    private String userImage;

    private String phoneNumber;
}
  • UserLoginBO、UserUpdateBO ...
java 复制代码
@Data
public class UserLoginBO implements Serializable{
    private String username;

    private String password;
}

@Data
public class UserUpdateBO implements Serializable{
    private Long id;

    private String username;

    private String password;

    private String identityCard;

    private String gender;

    private String location;

    private String userImage;

    private String phoneNumber;
}

从上面这个例子大家能看出来区别不

UserDTO是一个大的入口,它可以接收整个模块的参数

BO则是在进入Service层之前对UserDTO的数据进行过滤,并且对边界进行控制

最后在进入infra层之前转为PO

在后端开发中怎么用的

总结

为什么我们通篇没有讲关于VO的事情呢?

我个人的理解是DTO能解决的事情没有必要再加一个VO,我们可以弄一个全局配置,将DTO里面为null值的字段全都过滤掉

这样就没有说将数据传给前端的时候需要加多一个VO

给出代码示例,这样配置就可以把DTO中为null值过滤掉,不会序列化发给前端

java 复制代码
@Configuration
public class GlobalConfig extends WebMvcConfigurationSupport {

    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        converters.add(mappingJackson2HttpMessageConverter());
    }
    /**
     * 自定义mappingJackson2HttpMessageConverter
     * 目前实现:空值忽略,空字段可返回
     */
    private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return new MappingJackson2HttpMessageConverter(objectMapper);
    }
}
相关推荐
开心猴爷13 小时前
FTP 抓包分析实战,命令、被动主动模式要点、FTPS 与 SFTP 区别及真机取证流程
后端
本当迷ya13 小时前
最新2025年SpringBoot集成PowerJob分布式任务调度
后端
骈拇13 小时前
ConcurrentHashMap细节分析
后端
我是华为OD~HR~栗栗呀13 小时前
华为OD-23届考研-Java面经
java·c++·后端·python·华为od·华为·面试
shepherd11113 小时前
⏰ 一招鲜吃遍天!详解Java延时队列DelayQueue,从此延时任务不再难!
java·后端·消息队列
brzhang13 小时前
我用 Flutter 做了个小游戏,结果发现这玩意有点意思
前端·后端·架构
brzhang13 小时前
用 Vue 写原生 iOS/Android 应用,我发现这个库比 uni 要轻量且靠谱些
前端·后端·架构
这里有鱼汤13 小时前
3步用Python识别MACD背驰,避免80%追涨杀跌陷阱,建议收藏
后端·python
武子康14 小时前
大数据-125 - Flink 实时流计算中的动态逻辑更新:广播状态(Broadcast State)全解析
大数据·后端·flink
Mintopia14 小时前
🧠 Next.js 文件上传(头像 / 图片)终极指南
前端·后端·全栈