Java中的 VO,BO,DO 对象命名问题小结

 更新时间:2024年01月24日 11:38:12   作者:_江屿_  
本文讲解VO,BO,DO 的作用以及如何使用,分析了如何消除三者之间重复的代码,同样结合现实生活中领导配秘书来类比讲解,对Java  VO  对象命名相关知识感兴趣的朋友一起看看吧

最近,有小伙伴反馈:很困惑代码里用什么对象来传输数据,是共用一个对象还是每层各用一个对象,对于数据对象又该如何命名,种种困惑导致代码结构很混乱。针对该问题,今天就一起来聊聊这个看似简单,其实很多人都在误用的代码分层以及对象命名问题。

说起代码分层,那就不得不提起 MVC模式,相信很多程序员的编程启蒙阶段都有它的陪伴。

1. 什么是MVC?

MVC是后端业务开发最常见,使用频率最高的一种编程模式,因此,本文将结合 Java语言对 MVC做简要的介绍:

M:Mode,数据层,负责和数据库交互;

V:View,视图层,负责显示数据给用户,并向用户呈现信息;

C:Controller,逻辑层,负责处理用户的输入和相应操作;

早期,在 Java语言中,JSP(Java Server Page) 是 View视图的最好体现,有过 JSP经历的开发人员一定深深体会到了它的辛酸,随着互联网的快速发展,这种前端页面在后端代码中去编写显然满足不了市场的需求,随之而来的是前后端分离,基于前后端分离的场景,MVC模式与 Java常见的代码分层的对应关系可以如下图所示:

上图 Controller-Service-Repository 三层架构模型是前后端分离场景下 MVC最经典体现,目前,绝大多数的公司都是直接或者间接使用这个模型。尽管不同公司,代码架构略有差异,但万变不离穷,掌握了MVC三层架构就能轻松的去使用其他模型。

2. 公共对象贯穿MVC

讲完了 MVC模型,接下来的问题是:Controller-Service-Repository 各层之间通过什么对象传输数据呢?

你是否写过这样的代码?一个公共的对象,贯穿整个MVC,如下图, User对象从Controller层接收用户参数,一直到Repository 层,最终存储到 DB中。

上图是很多中初级程序员最容易出现的代码,一个类对象将参数从最顶层传到最底层,然后又将最底层的 DB数据输出到最顶层,简单粗暴,这样会产生什么问题呢?

  • 安全性:用户的入参可以直传到DB,存在SQL注入到风险,DB出来的数据直接到达View层,这样某些敏感数据可能会泄漏,比如注册功能,可能把密码暴露。
  • 使用困恼:对于接收入参的对象,一般是需要什么数据,定义什么参数,假如把一个大而全的对象直接暴露给用户,这样对接的用户对于入参传值就会很困惑。
  • 耦合性:如果各层都依赖于相同的数据对象,更改一个层次的数据结构可能会影响其他层次,系统耦合性太强。

这里只列举了 3个比较常见的问题,那么有什么好的方式可以解决这个问题呢?

最常用的方法是:使用VO,BO,DO对各层进行数据传输。

3. VO,BO,DO

VO:View Object,视图对象,用于 Controller层的数据对象;

BO:Business Object,业务对象,用于 Service层的数据对象;

DO:Domain Object,数据对象,用于 Repository层的数据对象,也可以叫做 Entity;

VO,BO,DO本质上是对数据类对象起一个规范的名字,比如:UserVO,UserBO,UserDO,它就和 xxxController,xxxService,xxxRepository 一样,见名知意,让人看见名字就知道它的职责。

为了更好的说明 VO,BO,DO,我们以一个生活中的实例“领导配秘书“来进行讲解。如下图:

当各层共用一个数据对象时,类比 董事长,CEO,总经理共用一个秘书,我们一起来分析上面提到的 3个常见问题:

  • 安全性:共用秘书,董事长的秘密会不会暴露给CEO和总经理呢?安全吗?
  • 耦合性:一个秘书要干 3个人的事情,每个领导的事情不一样,怎么解耦?
  • 使用困惑:当员工要反映问题时,秘书该反映到哪一层领导呢?

因此,闻道有先后,术业有专攻,专业的事就得干专业的人来干。董事长,CEO,总经理共用一个秘书显然不合理,必须配备自己的专职秘书;同理,Controller层,Service层,Repository层共用一个数据类对象也是不合理的,必须配备特定的类对象,对比图如下:

通过上图中每层领导配备专职秘书的实例,是不是能很好的理解 VO,BO,DO的作用:各层对象只负责自己本层的数据,划清边界,清晰职责。

因此,MVC,代码分层以及各层数据对象的对应关系可以描述成下图:

需要注意:因为 VO,BO,DO 需要定义属性来传递数据,因此难免会带来一个问题:三者出现重复的代码。这个问题合理吗?需要如何处理呢?

4. 消除重复代码

首先我们来分析三者出现重复的代码是否合理?

比如,用户注册功能,我们会在 UserVO,UserBO,UserDO中都定义相同的字段 username, password,如下图:

尽管三个类中都包含了相同的字段和getter和setter方法,但是因为他们的语义不一样,职责也不一样,所以这种重复是合理的。

有没有好的办法来消除这种重复呢?

有,将相同的属性抽到公共的类中,通过继承获得,如下图:

上图,我们抽取了一个父类 BaseUser来存放共用的字段,这样就可以达到代码复用,然后在每个子类对象中去定义特定的属性。既然类对象之间需要传输数据,那么该如何相互转换呢?

5. 对象相互转换

在实际开发中,我们一般会定义 Converter 类来负责对象之间的拷贝,如下图:

方法一:手动set

该方式缺点:需要手动编写 set方法,代码量比较多;优点:一个类对象更换了字段名,赋值会报错,能及时发现。

方法二:使用Apache的BeanUtils等工具进行拷贝

该方式优点:使用三方类包装的方式,简单易用;缺点:像BeanUtils工具,只会拷贝相同的属性,当一个类对象换了字段名,不会报错,不能及时发现。

两种方式各有优缺点,实际开发中都会用到,具体选择哪一种需要技术团队内部讨论决定。

6. 总结

  • 本文讲解了 MVC模式以及Java与之对应的代码分层;
  • 本文讲解了在代码各层共用一个类对象传输数据的优缺点,并且结合现实生活中领导配秘书来类比讲解;
  • 本文讲解VO,BO,DO 的作用以及如何使用,分析了如何消除三者之间重复的代码,同样结合现实生活中领导配秘书来类比讲解;
  • MVC 是代码分层的精髓,尽管很多公司不一定严格遵守MVC,但是万变不离其宗,掌握了精髓,才能轻松玩转其他的分层风格;

到此这篇关于Java中的 VO,BO,DO 对象命名问题的文章就介绍到这了,更多相关Java VO 对象命名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mybatis执行SQL时多了一个limit的问题及解决方法

    Mybatis执行SQL时多了一个limit的问题及解决方法

    这篇文章主要介绍了Mybatis执行SQL时多了一个limit的问题及解决方法,Mybatis拦截器方法识别到配置中参数supportMethodsArguments 为ture时会分页处理,本文结合示例代码给大家讲解的非常详细,需要的朋友可以参考下
    2022-10-10
  • SpringBoot继承LogStash实现日志收集的方法示例

    SpringBoot继承LogStash实现日志收集的方法示例

    这篇文章主要介绍了SpringBoot继承LogStash实现日志收集的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • java实现TCP socket和UDP socket的实例

    java实现TCP socket和UDP socket的实例

    这篇文章主要介绍了本文主要介绍了java实现TCP socket和UDP socket的实例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • SpringMVC将请求和响应的数据转换为JSON格式的几种方式

    SpringMVC将请求和响应的数据转换为JSON格式的几种方式

    这篇文章主要给大家介绍饿了SpringMVC将请求和响应的数据转换为JSON格式的几种方式,文中通过代码示例和图文结合给大家介绍的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2023-11-11
  • 使用Netty快速实现一个群聊功能的示例详解

    使用Netty快速实现一个群聊功能的示例详解

    这篇文章主要为大家详细介绍了如何利用 Netty 框架开发一个 WebSocket 服务端,从而实现一个简单的在线聊天功能,感兴趣的小伙伴可以了解下
    2023-11-11
  • Jasypt的StandardPBEByteEncryptor使用源码解析

    Jasypt的StandardPBEByteEncryptor使用源码解析

    这篇文章主要介绍了Jasypt的StandardPBEByteEncryptor使用源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • SpringBoot使用前缀树实现敏感词过滤示例

    SpringBoot使用前缀树实现敏感词过滤示例

    最近项目用到了敏感词过滤,本文主要就来介绍一下SpringBoot使用前缀树实现敏感词过滤示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • 利用Java如何实现将二维数组转化为链式储存

    利用Java如何实现将二维数组转化为链式储存

    链式结构不要求逻辑上相邻的节点在物理位置上也相邻,节点间的逻辑关系是由附加的指针字段表示的,通常借助于程序设计中的指针结构来实现,这篇文章主要给大家介绍了关于利用Java如何实现将二维数组转化为链式储存的相关资料,需要的朋友可以参考下
    2021-12-12
  • Java编程实现直接插入排序代码示例

    Java编程实现直接插入排序代码示例

    这篇文章主要介绍了Java编程实现直接插入排序代码示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • JAVA使用SimpleDateFormat类表示时间代码实例

    JAVA使用SimpleDateFormat类表示时间代码实例

    这篇文章主要介绍了JAVA使用SimpleDateFormat类表示时间代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04

最新评论