场景通常,在后端项目开发中,因为会有项目分层的设计,例如MVC架构,以及最近很火热的DDD架构中,会在不同的层级,有对应的DO,BO,VO,DTO等各种各样的POJO类,而我们在层级之间进行调用的数据传递时,通常要进行对象属性之间的映射 。对于一些简单的对象,可能会直接使用get,set方法完成,或者使用BeanUtils工具类来完成属性之间的映射 。
这些代码往往是枯燥、无聊的,并且在不同的业务处理类中可能需要重复地对两个对象进行互相转换 。导致代码里充斥着大量的get,set转换,如果使用BeanUtils,可能会因为字段名称不一致,导致在运行时才能发现问题 。
那有没有什么方案能解决这个问题呢?
答案就是使用MapStruct,可以优雅地解决上面的这些问题 。
MapStruct是一种代码生成器组件,它遵循约定优于配置的原则,可以让我们的Bean对象之间的转换变得更简单 。
为什么要使用MapStruct?如前文中描述,在多层应用设计中,需要在不同的对象模型之间进行转换,属性映射,手动编写这些代码不仅繁琐,而且很容易出错,MapStruct的目的是让这项工作变得简单,自动化 。
相比其他的映射框架,比如BeanUtils,或者Json序列化反序列化等方式,MapStruct能在编译时就生成映射,确保程序运行性能,并且能在编译时就发现错误 。
MapStruct怎么用?MapStruct本质上是一个注解处理器,可以直接在Maven或Gradle等编译工具中集成 。
以Maven为例,我们需要先在依赖中添加MapStruct依赖,并将mapstruct-processor配置在maven插件中 。
<properties><org.mapstruct.version>1.4.2.Final</org.mapstruct.version></properties><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${org.mapstruct.version}</version></dependency><plugin><groupId>org.Apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><annotationProcessorPaths><path><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${org.mapstruct.version}</version></path></annotationProcessorPaths></configuration></plugin>
接下来,便可以在代码中使用MapStruct 。
同名字段映射比如,我们现在有一个功能是要从持久层查询学生对象Student,然后将它转换为StudentDTO传递给业务层 。这里我们需要在Student对象和StudentDTO对象之间进行转换 。
Student.JAVA
@Datapublic class Student{ private int no; private String name;}
StudentDTO.java
@Datapublic class StudentDTO { private int no; private String name;}
针对这种对象之间的转换,我们需要创建一个MApper类进行映射 。
@Mapper(componentModel = "spring")public interface StudentMapper {StudentDTO toDto(Student student);}
【使用MapStruct,让Bean对象之间转换更简单】@Mapper :是MapStruct的注解,用于创建和生成映射的实现 。
componentModel = "spring":该属性的含义是将StudentMapper的实例作为Spring的Bean对象,放在Spring容器中,这样就可以在其他业务代码中方便的注入 。
因为Student和StudentDTO的属性名相同,所以我们不需要任何其他代码显式映射 。
不同名字段映射假如DTO和PO之间的字段名称不同,应该如何处理呢?
Student.java
@Datapublic class Student{private int no;private String name;private String gender;}
StudentDTO.java
@Datapublic class StudentDTO {private int no;private String name;private String sex;}
如上代码所示,在Student和StudentDTO中,性别字段的名称不一致 。要实现这种情况的映射,只需要添加如下的@Mapping注解 。
@Mapper(componentModel = "spring")public interface StudentMapper {@Mapping(source = "gender", target = "sex")StudentDTO toDto(Student student);}
自定义对象属性映射假如每个学生有自己的地址信息Address,那么该如何处理呢?
源对象类
@Datapublic class Student{private int no;private String name;private String gender;private Address address;}@Datapublic class Address{private String city;private String province;}
目标对象类
@Datapublic class StudentDTO{private int no;private String name;private String sex;private AddressDTO address;}@Datapublic class AddressDTO{private String city;private String province;}
这种要对内部对象进行映射,我们需要对内部对象也创建一个Mapper,然后将内部对象的Mapper导入到StudentMapper中 。
推荐阅读
- 写不出文章怎么办?学会这个模板让你下笔如有神
- 金融装订机的分类及使用注意事项
- 凤庆红茶的功效与作用,红茶的口感和功效
- 面膜|面膜哪个牌子好?连明星都爱用的面膜排行榜 用一次就让你入坑
- 西洋参的功效和作用
- 如何设置Mac终端使用快捷键切换标签页?
- MyBatis 使用数组作为参数,这里藏着一个大坑
- 让你的旧打印机变身WIFI打印机
- 9 个你可能从未使用过的很棒的 CSS 属性
- 只需关闭一个设置,解除电脑网速和内存的限制,让电脑丝滑顺畅