MapStruct的介绍
MapStruct是一个Java注解处理器,用于生成类型安全的bean映射类。注解处理器是什么,可以参考我前段时间写的这篇博客:【实用工具】JSR-269 插入式注解处理器AbstractProcessor
您要做的就是定义一个映射器接口,该接口声明任何必需的映射方法。在编译期间,MapStruct将生成此接口的实现。此实现使用简单的Java方法调用在源对象和目标对象之间进行映射,即没有反射或类似内容。
Java实现
依赖引入
<properties>
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
<lombok.version>1.18.10</lombok.version>
</properties>
<dependencies>
<!-- ...-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<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>
</dependencies>
或者
...
<properties>
<org.mapstruct.version>1.5.2.Final</org.mapstruct.version>
</properties>
...
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source> <!-- depending on your project -->
<target>11</target> <!-- depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
功能特性
名称和类型不一致
任务类
@Data
public class AppTask {
private String name;
private String title;
private List<String> data;
private Date createDate;
private String createTime;
}
任务Vo类
@Data
public class AppTaskVo {
private String taskName;
private String title;
private String dataStr;
private String createTimeStr;
private Date createTime;
}
可以看出除了title属性一致外,其他属性要么类型不一样,要么是名称不一样。
@Mapper(uses = ListStrFormat.class)
public interface AppTaskMapper {
AppTaskMapper INSTANCES = Mappers.getMapper(AppTaskMapper.class);
@Mappings({
@Mapping(source = "name", target = "taskName"),
@Mapping(source = "data", target = "dataStr"),
@Mapping(source = "createDate", target = "createTimeStr", dateFormat = "yyyyMMdd"),
@Mapping(target = "createTime", dateFormat = "yyyyMMdd")
})
AppTaskVo toTaskVo(AppTask appTask);
}
日期格式转换可以通过dateFormat
设置,名称修改通过@Mapping
指定source
和target
。类型不一致可以通过@Mapper(uses = ListStrFormat.class)
,设置转换类。
public class ListStrFormat {
public String toStr(List<String> list) {
return list.stream().collect(Collectors.joining(","));
}
}
测试效果
public class AppTaskTest {
AppTaskMapper instances = AppTaskMapper.INSTANCES;
@Test
public void t1() {
AppTask appTask = new AppTask();
appTask.setName("123");
appTask.setTitle("abc");
appTask.setData(Arrays.asList("AA", "BB", "CC"));
appTask.setCreateDate(new Date());
appTask.setCreateTime("20230513");
AppTaskVo appTaskVo = instances.toTaskVo(appTask);
System.out.println(appTask);
System.out.println(appTaskVo);
}
}
控制台输出
AppTask(name=123, title=abc, createDate=Sun May 14 19:18:41 CST 2023, createTime=20230513, data=[AA, BB, CC])
AppTaskVo(taskName=123, title=abc, dataStr=AA,BB,CC, createTimeStr=20230514, createTime=Sat May 13 00:00:00 CST 2023)
集合转换
如果集合转换,添加方法如下
List<AppTaskVo> toTaskVoList(List<AppTask> appTasks);
多转一
如果想要多个数据源复制到一个数据实体中,也是可以做到的。
记录类
@Data
public class AppRecord {
private String name;
}
任务记录类
@Data
public class AppTaskRecordVo {
private String taskName;
private String recordName;
}
添加转换方法
@Mappings({
@Mapping(source = "appTask.name", target = "taskName"),
@Mapping(source = "record.name", target = "recordName")
})
AppTaskRecordVo toTaskRecordVo(AppTask appTask, AppRecord record);
测试效果:
public void t2() {
AppTask appTask = new AppTask();
appTask.setName("123");
appTask.setTitle("abc");
AppRecord record = new AppRecord();
record.setName("爬山");
AppTaskRecordVo appTaskRecordVo = instances.toTaskRecordVo(appTask, record);
System.out.println(appTaskRecordVo);
}
控制台输出:
AppTaskRecordVo(taskName=123, recordName=爬山)
指定更新对象
通过@MappingTarget
来指定目标类是谁(谁的属性需要被更新)。@Mapping
还是用来定义属性对应规则。
void update(AppTask appTask, @MappingTarget AppTaskVo appTaskVo);
Spring容器管理
@Mapper(componentModel = “spring”)
,表示把当前Mapper类纳入spring容器。
@Mapper(componentModel ="spring")
public interface AppTaskMapper {
}