蔡昊 - 如何高效而优雅的进行对象转换

简介: 简介随着分层结构和DDD设计思想的普及,我们在后端开发过程中,会使用到VO/DO/DTO等等各种类型的模型对象,对象的转换工作也随着变得越来越多。而这种工作技术含量不高,却容易过多的出现在编码里,处理不当也会出现各种问题,那么如何更加高效而优雅的进行类型转换呢?且花几分钟了解下笔者接下来要讲的一款Java代码生成器MapStruct——创建实现Java Bean之间转换的扩展映射器!

MapStruct的优点

首先,我们了解下常见的转换对象方法:

// 1. getter+setter 这种方式会产生大量无意义工作和重复代码
// 2. BeanUtils      
这种方式适用处理简单结构的转换,遇到字段名称不对应等情况,仍需要额外的处理
BeanUtils.copyProperties(Object source,Object target)

MapStruct特点

•            简单、自动化

•            编译时生成映射,确保运行时性能

•            只需要创建接口,大大减少样板代码的编码工作

MapStruct的使用

1. 引包与配置

<properties>                
   <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
</properties>

<dependency>
   <groupId>org.mapstruct</groupId>
   <artifactId>mapstruct</artifactId>
   <version>${org.mapstruct.version}</version>
</dependency>
<dependency>
   <groupId>org.mapstruct</groupId>
   <artifactId>mapstruct-processor</artifactId>
   <version>${org.mapstruct.version}</version>
</dependency>

*最新maven版本:https://mvnrepository.com/artifact/org.mapstruct/mapstruct

2. 编码及基本使用

先看下需要转换的两个类,这里简化模型,仅仅以VODO做为案例:

@Data
publicclass UserVO{
   privateLong id;
   privateString userName;
   privateString email;
   privateInteger gender;
}

@Data
@TableName(value ="User")
publicclass User implementsSerializable{
   privatestaticfinallong serialVersionUID =1L;

   @TableId(type = IdType.AUTO)
   privateLong id;
   privateString name;
   privateString email;
   privateString createdDate;
   privateString updatedDate;
   privateInteger gender;
}

第一步:下面是新建一个转换类的接口:

/**
* UserTransfer
*
* @author CaiHao
*@since 2022/3/1011:42
*/
//
标记为映射接口,@Mapper允许接口mapstruct-processor在编译期启动
@Mapper
publicinterface UserTransfer {

   UserTransfer INSTANCE = Mappers.getMapper(UserTransfer.class);

   //
映射名称不同的字段
   @Mapping(source ="userName", target ="name")
   //
声明转换方法
   User toDo(UserVO vo);

   @Mapping(source ="name", target ="userName")
   UserVO toVo(User user);

   // list
转换
   List<User>toDo(List<UserVO> voList);

   List<UserVO>toVo(List<User> doList);
}

第二步:如何使用

// 方式一:通过INSTANCE实现访问
User user = UserTransfer.INSTANCE.toDo(tom);

或使用@Mapper(componentModel = "spring")

// 方式二:注入UserTransfer userTransfer;
User user = userTransfer.toDo(tom);

3. 拓展应用

情况一:变量为实体(嵌套bean

@Data
@Builder
@AllArgsConstructor
publicclass EmployeeVO {
   privateLong id;
   privateString empName;
   privateString gender;

   private Contact contact;
}

@Data
publicclass Contact {
   privateString address;
   privateString phone;
   privateString email;
}

@Data
@Builder
publicclass UserVO {
   privateLong id;
   privateString userName;
   privateString email;
   privateInteger gender;
   privateString address;
   privateString phone;
}

@Mapper
publicinterface UserTransfer {
   UserTransfer INSTANCE = Mappers.getMapper(UserTransfer.class);
   /**
    * UserVO
转换成EmployeeVO
    *
    * @param userVO userVO
    *@return EmployeeVO EmployeeVO
    */
   @Mapping(source ="userName", target ="empName")
   @Mapping(source ="email", target ="contact.email")
   @Mapping(source ="address", target ="contact.address")
   @Mapping(source ="phone", target ="contact.phone")
   EmployeeVO toEmployeeVO(UserVO userVO);
}

EmployeeVO employeeVO = UserTransfer.INSTANCE.toEmployeeVO(tom);

情况二: 类型转换、映射合成

publicclass User{    
   privateString updatedDate;
   privateInteger gender;
}

publicclass UserVO {
   privateDate gmtCreate;
   privateString gender;
}

@Mappings({
@Mapping(target ="gender", expression="java(java.lang.String.valueOf(user.getGender()))"),
@Mapping(source ="createdDate", target ="gmtCreate", dateFormat ="yyyy-MM-dd HH:mm")
})
UserVO toVo(User user);

mapstruct的应用场景广泛,如转换、处理第三方服务结果集,同时配合Lombok注解,可以发挥出更好的效果。

*关于更多高级属性和方法,可以查看官方文档

相关文章
|
应用服务中间件 nginx
利用nginx+fancyindex美化目录索引
利用nginx+fancyindex美化目录索引 1.下载第三方插件
1301 0
利用nginx+fancyindex美化目录索引
|
Web App开发 Cloud Native Docker
删除容器报错:Error response from daemon: conflict: unable to delete
云原生日益普及的现在,docker容器化成为现有很多服务的改进方向,docker凭借更高效的利用系统资源、更快速的启动时间、一致的运行环境、持续支付和部署、更轻松的迁移、更轻松的维护和拓展等优势,迅速走红。但是,很多容器部署后在回收时,都会遇到各种各样的问题,比如今天讨论的删除镜像的问题,有时候删除操作会莫名其妙的报错。
1358 1
|
8月前
|
存储 编解码 人工智能
阿里云视频点播VOD收费标准:存储费用、流量价格、转码费用及视频加速价格整理
阿里云视频点播VOD按存储、转码、流量及加速等计费,支持资源包与按量付费。含新客9.9元套餐,涵盖流量、转码、存储等多种优惠,详情见官方页面。
|
人工智能 关系型数据库 分布式数据库
客户说|哔哩哔哩基于阿里云PolarDB与千问大模型构建全域内容洞察新框架
哔哩哔哩联合阿里云 PolarDB for AI,构建“大模型+小模型”协同的全域内容洞察体系,基于去标识化公开互动数据,实现视频、评论等内容的结构化分析,精准识别品牌、类目、用户反馈属性,助力营销效果量化与策略优化。
|
Arthas 监控 Java
Arthas logger(查看 logger 信息,更新 logger level)
Arthas logger(查看 logger 信息,更新 logger level)
516 6
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
606 6
|
数据安全/隐私保护 容器 API
利用临时用户名和密码登录容器镜像仓库
利用临时用户名和密码登录容器镜像仓库
3999 136
|
存储 运维 监控
【网络安全】安全等级保护测评培训试题集
【网络安全】安全等级保护测评培训试题集
3434 0

热门文章

最新文章