项目中的BO、DTO、VO、PO如何区分以及规范的使用

我们在日常开发中经常会看到各种的以‘O’结尾的类,那么这些类代表什么含义呢,我们如何规范的使用这些类呢?今天我们就来聊一聊这个话题。

1、区分BO、DTO、VO、PO

我们现在一般都是前后端分离的模式开发项目,后端接收到请求后做业务处理和操作数据库,如下的流程:

(1)用户发起请求后前端通过DTO类将请求的参数传给后端

(2)后端在controller层接收到前端的DTO类的请求参数后,如果此时业务比较简单,也就没有必要再整一个BO类对象接收业务数据了;如果我们的业务比较复杂,需要多个字段来存储业务数据,此时可以创建一个新的BO对象来接收业务数据。

(3)数据库对象的实体类我们一般是使用PO/DO来表示,我们将请求的BO/DTO映射成数据的PO/DO,最后拿业务数据操作数据库

(4)业务处理完成之后,我们将前端需要的数据封装到VO类对象中并响应给前端。

2、BO、DTO、VO、PO相互映射工具

在我们规范的使用BO、DTO、VO、PO的时候就会出现类之间的转换问题,最原始的办法就是创建接收对象,然后手动的把数据set到接收对象中。原始方法不仅给我们带来巨大的代码工作量,而且在字段较多的情况下容易出现字段set数据赋值错误的问题,原本19点下班直接就干到20点下班。下面介绍几种对象映射的方案。

(1)Spring框架中的BeanUtils工具

Spring自带的BeanUtils操作类可以简化Java Bean对象之间的属性拷贝和赋值操作,进而减少开发人员在属性复制和赋值时的工作量和代码量,提高开发效率。常见的方法如下所示:

BeanUtils.copyProperties(destination, source),可以将一个Bean对象的属性值复制到另一个Bean对象中。

BeanUtils.copyProperties(Object dest, Object source, String… ignoreProperties): 复制属性时忽略指定的属性。

BeanUtils.copyProperties(Object dest, Object source, Class<?> editable): 仅复制目标类中定义的属性。

BeanUtils的属性拷贝功能通常依赖于getter和setter方法;在拷贝属性时目标对象的属性名必须与源对象的属性名匹配; BeanUtils 可能会忽略掉一些复杂的类型或需要特殊处理的属性。

(2)MapStruct插件

Spring的Beanutils工具只能同类型的属性映射,但是当遇到被映射的属性数据类型被修改或者被映射的字段名被修改,则会导致无法映射。此时我们可以使用 M apS t r uct 插件来解决这个问题。

引入 M apS t r uct的依赖

<dependency> 
        <groupId>org.mapstruct</groupId> 
        <!-- jdk8以下就使用mapstruct --> 
        <artifactId>mapstruct-jdk8</artifactId> 
        <version>1.2.0.Final</version> 
    </dependency> 

    <dependency> 
        <groupId>org.mapstruct</groupId> 
        <artifactId>mapstruct-processor</artifactId> 
        <version>1.2.0.Final</version> 
    </dependency>

转换的对象类型属性一致的时候,M apS t r u ct的使用:

@Mapper 
public interface UserCovertBasic { 
  //接口中声明了一个成员变量INSTANCE,是让客户端可以访问 Mapper接口的实现 
  UserCovertBasic INSTANCE = Mappers.getMapper(UsercovertBasic.class); 
  UserVO toConvertVO1(User source); 
  User fromConvertEntity1(UserVO1 userVO1); 

}

在@Mapper注解中添加(componentModel = "spring"),是为了告诉MapStruct在生成映射器实现类时,我们希望它能支持通过Spring的依赖注入来创建,此时就可以不用添加INSTANCE,可以简化为:

@Mapper(componentModel ="spring") 
public interface UserCovertBasic { 
  UserVO toConvertVO1(User source); 
  User fromConvertEntity1(UserVO1 userVO1); 

}

转换的对象类型不一致的时候,M apS t r u ct的使用:

@Mapper(componentModel ="spring") 
public interface UserCovertBasic { 
//手动的指定字段映射 
@Mappings({ 
  @Mapping(source ="id",target = "userId"), 
  @Mapping(source ="name",target = "userName") 
}) 
Userv04 toConvertvo(User source); 
}

M apS t r u ct的功能非常的强大,有兴趣的朋友可以自己再去了解一下,这就不做过多的介绍了。

除了上面介绍的两种工具外还有其他优秀的映射工具,如Dozer、Orika等工具。

9