MapStruct使用
在一个项目的不同模块或不同需求中,经常需要一个数据模型的一部分,需要进行对象与对象之间的互相转换。
最为简单直接的就是使用getter,setter方法进行转换,或者使用自定义Beans.copyProperties等实现。
前者编写麻烦,后者使用反射的方式导致性能消耗较大
MapStruct是一个属性映射工具、框架。通过生成这些繁琐的代码来节省时间。
- GitHub: mapstruct/mapstruct
依赖
以SpringBoot+Lombok+MapStruct为例,其余场景见 GitHub示例代码
...
<properties>
<org.mapstruct.version>1.5.2.Final</org.mapstruct.version>
<org.projectlombok.version>1.18.20</org.projectlombok.version>
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
</properties>
...
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<!-- lombok dependencies should not end up on classpath -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
<build>
<plugins>
<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>
<!-- MapStruct 注解处理器 -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<!-- Lombok 注解处理器 -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<!-- MapStruct 和 Lombok 注解绑定处理器 -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
...
使用
创建pojo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Boy {
private String name;
private Integer age;
private String school;
private String blog;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Man {
private String name;
private Integer age;
private String work;
private String blogName;
private String blogUrl;
}
- 公共属性:name,age
- Boy独有属性:school
- Man独有属性:work
- 不同名属性:blog / blogName
- 自定义转换:blogUrl
创建映射器
配置
属性
-
mapstruct.suppressGeneratorTimestamp- 禁止在生成的映射器中创建时间戳
- 默认
false
-
mapstruct.supppressGeneratorVersionInfoComment- 禁止在生成的映射器中创建属性
- 默认为
false
-
mapstruct.defaultComponentModel- 基于生成映射器的组件模型的名称,支持
default,cdi,spring,jsr30 - 默认
default,使用spring可以使用@Autowired方式注入
- 基于生成映射器的组件模型的名称,支持
-
mapstruct.unmappedTargetPolicy- 在未使用source值填充映射方法的target属性的情况下要应用的默认报告策略,支持
ERROR(映射代码生成失败)、WARN(构建时引起警告)、IGNORE(忽略)- 默认为
WARN,如Warning:(36, 24) java: Unmapped target property: .....
- 默认为
- 在未使用source值填充映射方法的target属性的情况下要应用的默认报告策略,支持
配置方式一:注解配置
@Mapper(componentModel="spring", ....)
配置方式二:pom配置
<build>
<plugins>
<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>
<compilerArgs>
<compilerArg>
-Amapstruct.suppressGeneratorTimestamp=true
</compilerArg>
<compilerArg>
-Amapstruct.suppressGeneratorVersionInfoComment=true
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
映射器实现
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public Interface ObjectConvertor(){
@Mapping(source = "blogName", target = "blog")
@Mapping(source = "blogName", target = "blogUrl", qualifiedByName = "blogUrl")
Man boy2Man(Boy boy);
@Named("blogUrl")
default String blogUrl(String blog){
return "https://"+blog;
}
}
属性的默认转换是按照属性名进行转换
List等对象需要先有其中元素对象的转换方法。
自定义的转换方式采用
qualifiedName和@Named()实现
@Mapping的source可以是传入的参数,如@Mapping(source=“boy”, ...)对于多个不同名属性,可以在
@Mapping外包一层@Mappings,或多个@Mapping叠加@Mappings({ @Mapping(source = "blogName", target = "blog"), ... })由于生成的代码直接为
.class文件,如果是对pojo的属性做出调整,重新运行时不会再重新生成,导致类型转换出错,需要ReBuild。
使用
@Autowired
ObjectConvertor objectConvertor;
public void objConvert() {
Boy boy = new Boy("zang", 18, "zjut", "zang.gold");
System.out.println(boy);
Man man = objectConvertor.boy2Student(boy);
System.out.println("After convert: ");
System.out.println(man);
}
~$: Boy(name=zang, age=18, school=zjut, blog=zang.gold)
~$: After convert:
~$: Man(name=zang, age=18, work=null, blogName=zang.gold)

浙公网安备 33010602011771号