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

简介: 简介随着分层结构和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.下载第三方插件
1276 0
利用nginx+fancyindex美化目录索引
|
4月前
|
SQL Oracle 关系型数据库
Oracle数据库学习知识点(一)
教程来源 https://app-ah8jla8z2m81.appmiaoda.com 系统梳理Oracle数据库核心知识,涵盖安装配置、体系结构、SQL基础、PL/SQL编程等关键内容,兼顾初学者入门与DBA/开发者进阶需求,助力构建完整技术体系。
|
7月前
|
监控 数据可视化 物联网
告别进度失控与成本超支!追踪复杂工程的高效工具选型指南
复杂工程管理面临进度、资源、成本与协同难题,传统工具难以为继。本文系统解析超大型基建、EPC、BIM施工等场景的精准工具选型:从轻量协同到企业级管控,覆盖Primavera、BIM5D、SAP等方案,并提炼多级计划、4D模拟、EVM等核心能力,提供四步落地策略与快速选型口诀,助力实现项目全过程数字化闭环管理。(238字)
|
人工智能 关系型数据库 分布式数据库
客户说|哔哩哔哩基于阿里云PolarDB与千问大模型构建全域内容洞察新框架
哔哩哔哩联合阿里云 PolarDB for AI,构建“大模型+小模型”协同的全域内容洞察体系,基于去标识化公开互动数据,实现视频、评论等内容的结构化分析,精准识别品牌、类目、用户反馈属性,助力营销效果量化与策略优化。
|
7月前
|
运维 关系型数据库 Linux
Linux 高效学习指南:从入门到运维的科学路径
本文介绍Linux运维学习的科学路径,主张“场景驱动”替代死记硬背。涵盖四大阶段:一周掌握核心命令,两周理解系统原理与故障排查,两周实战部署LNMP服务,长期进阶自动化运维。强调动手实操、问题驱动与循序渐进,提供各阶段目标、任务与资源推荐,助你高效构建完整知识体系,成为实战型运维人才。
|
缓存 人工智能 算法
lru算法设计与实现
本文详细介绍了LRU(Least Recently Used,最近最少使用)缓存淘汰策略的原理与实现。LRU的核心思想是:越近被访问的数据,未来被再次访问的可能性越大。文章通过Java语言实现了一个支持O(1)时间复杂度操作的LRU缓存
491 0
|
存储 边缘计算 开发工具
云计算技术:从基础到实践
【10月更文挑战第4天】云计算技术:从基础到实践
|
SQL Java 关系型数据库
Mybatis保姆级丝滑教程(一文搞懂系列)(1)
Mybatis保姆级丝滑教程(一文搞懂系列)
1428 0
|
数据安全/隐私保护 容器 API
利用临时用户名和密码登录容器镜像仓库
利用临时用户名和密码登录容器镜像仓库
3959 136
|
存储 运维 监控
【网络安全】安全等级保护测评培训试题集
【网络安全】安全等级保护测评培训试题集
3364 0