MapStruct是一个Java注解解释器,用于生成类型安全的Bean映射类。在使用时只需要定义一个映射器接口。在接口中声明所需要的映射方法,MapStruct会在编译期为我们生成此接口的实现类。

使用

依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--mapstruct核心-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>

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

插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-processor</artifactId>
<version>${mapstruct-plus.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${mapstruct-plus.lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>

定义接口形式用法

1.准备实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Data  
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Student implements Serializable {

private static final long serialVersionUID = 1L;

private Long id;

private String name;

private Integer age;

private String createBy;

private Date createTime;

}

@Data
public class StudentVO implements Serializable {

private static final long serialVersionUID = 1L;

private Long id;

private String name;

private Integer years;

private String createBy;

private Date createTime;

}

2.转换接口

1
2
3
4
5
6
7
8
9
10
11
@Mapper(imports = {DateUtils.class})  
public interface StudentConvert {

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

@Mappings({
@Mapping(target = "createTime", expression = "java(DateUtils.getNowDate())"),
@Mapping(source = "age", target = "years"),
})
StudentVO convertStudent(Student student);
}

3.工具类

1
2
3
4
5
6
7
8
public class DateUtils {  

public static Date getNowDate()
{
return new Date();
}

}

5.自动生成的实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Generated(  
value = "org.mapstruct.ap.MappingProcessor",
date = "2025-01-06T13:39:36+0800",
comments = "version: 1.5.5.Final, compiler: javac, environment: Java 1.8.0_181 (Oracle Corporation)"
)
public class StudentConvertImpl implements StudentConvert {

@Override
public StudentVO convertStudent(Student student) {
if ( student == null ) {
return null;
}

StudentVO studentVO = new StudentVO();

studentVO.setYears( student.getAge() );
studentVO.setId( student.getId() );
studentVO.setName( student.getName() );
studentVO.setCreateBy( student.getCreateBy() );

studentVO.setCreateTime( DateUtils.getNowDate() );

return studentVO;
}
}

5.输出测试

1
2
3
4
5
6
7
public static void main(String[] args) {
Student student = Student.builder().id(1024L).age(25).createBy("xihai").name("悦彬先生").build();
StudentVO studentVO = StudentConvert.INSTANCE.convertStudent(student);
System.out.println(studentVO);
}

// 输出内容为:StudentVO(id=1024, name=悦彬先生, years=25, createBy=xihai, createTime=Mon Jan 06 14:18:00 CST 2025)

注解形式用法

1.准备实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@Data  
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(value = "设备信息")
public class DeviceInfo implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 主键id
*/ private Long id;

/**
* 设备sn码
*/
private String deviceSn;
/**
* 设备名称
*/
private String deviceName;

/**
* 设备类型
*/
private String deviceType;

/**
* 设备型号
*/
private String deviceModel;

/**
* 设备图片
*/
private String devicePic;

/**
* 设备厂商
*/
private String manufacturer;

/**
* 固件版本
*/
private String firmwareVersion;
/**
* 状态(停用0,启用1)
*/ private Integer status;

/**
* 父设备id
*/ private Long parent;

public void alarm(String name) {
System.out.println("方法被调用:" + name);
}

}

@Data
@AutoMapper(target = DeviceInfo.class)
public class DeviceListVO {

@ApiModelProperty(value = "设备ID")
private Long id;

@ApiModelProperty(value = "设备sn码")
private String deviceSn;

@ApiModelProperty(value = "设备名称")
private String deviceName;

@ApiModelProperty(value = "设备类型")
private String deviceType;

@ApiModelProperty(value = "设备型号")
private String deviceModel;

@ApiModelProperty(value = "固件版本")
private String firmwareVersion;

@ApiModelProperty(value = "状态(停用0,启用1)")
private Integer status;

}

2.转换工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@NoArgsConstructor(access = AccessLevel.PRIVATE)  
public class MapstructUtils {

private static final Converter CONVERTER = (Converter)SpringUtils.getBean(Converter.class);

/**
* 将 T 类型对象,转换为 desc 类型的对象并返回
*
* @param source 数据来源实体
* @param desc 描述对象 转换后的对象
* @return desc
*/ public static <T, V> V convert(T source, Class<V> desc) {
if (ObjectUtil.isNull(source)) {
return null;
}
if (ObjectUtil.isNull(desc)) {
return null;
}
return CONVERTER.convert(source, desc);
}

/**
* 将 T 类型对象,按照配置的映射字段规则,给 desc 类型的对象赋值并返回 desc 对象
*
* @param source 数据来源实体
* @param desc 转换后的对象
* @return desc
*/ public static <T, V> V convert(T source, V desc) {
if (ObjectUtil.isNull(source)) {
return null;
}
if (ObjectUtil.isNull(desc)) {
return null;
}
return CONVERTER.convert(source, desc);
}

/**
* 将 T 类型的集合,转换为 desc 类型的集合并返回
*
* @param sourceList 数据来源实体列表
* @param desc 描述对象 转换后的对象
* @return desc
*/ public static <T, V> List<V> convert(List<T> sourceList, Class<V> desc) {
if (ObjectUtil.isNull(sourceList)) {
return null;
}
if (CollUtil.isEmpty(sourceList)) {
return CollUtil.newArrayList();
}
return CONVERTER.convert(sourceList, desc);
}

/**
* 将 Map 转换为 beanClass 类型的集合并返回
*
* @param map 数据来源
* @param beanClass bean类
* @return bean对象
*/
public static <T> T convert(Map<String, Object> map, Class<T> beanClass) {
if (MapUtil.isEmpty(map)) {
return null;
}
if (ObjectUtil.isNull(beanClass)) {
return null;
}
return CONVERTER.convert(map, beanClass);
}

}

3.进行转换

1
2
3
4
5
6
7
8
9
10
11
@RestController  
public class MapStructController {

@GetMapping("/test")
public void test() {
DeviceInfo deviceInfo = new DeviceInfo(111L,"1f7a3af7-6b06-410b-a283-d8fc24e1acbb", "M30T-1", "M30T", "M30T", "url", "XIHAI", "1.0.0", 1, null);
DeviceListVO vo = MapstructUtils.convert(deviceInfo, DeviceListVO.class);
System.out.println(vo);
}

}