mapstruct-plus是基于mapstruct开发的Java Bean转换工具,相比mapstruct节省了编写接口的步骤,完全基于注解自动生成对应的接口和实现,我这里简单的演示在spring boot项目中使用。

引入Maven依赖

1
2
3
4
5
<dependency>  
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
<version>1.2.2</version>
</dependency>

由于我需要转换的Bean采用了lombok,而mapstruct根据注解生成转换接口与实体类、lombok生成getset等方法都是在编译期完成的,所以要保证lombok的处理走在mapstruct之前,这里需要在Maven中设置一下:

lombok 1.18.16 之前:
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
<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.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>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
lombok 1.18.16 及以后:
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
<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.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>0.2.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

实体

在User或UserDto一方类上加上@AutoMapper注解即可,target的值为另一方类,我这里放在UserDto类上:

1
2
3
4
5
6
7
8
@Data  
public class User {

private String username;
private int age;
private boolean young;

}
1
2
3
4
5
6
7
8
9
@AutoMapper(target = User.class)  
@Data
public class UserDto {

private String username;
private int age;
private boolean young;

}

测试

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
@SpringBootTest  
class SpringDemoApplicationTests {

@Resource
private Converter converter;

@Test
void mapStruct(){
User user = new User();
user.setUsername("jack");
user.setAge(23);
user.setYoung(false);

// user转userDto
UserDto userDto = converter.convert(user, UserDto.class);
System.out.println(userDto);

assert user.getUsername().equals(userDto.getUsername());
assert user.getAge() == userDto.getAge();
assert user.isYoung() == userDto.isYoung();

// userDto转user
User newUser = converter.convert(userDto, User.class);

System.out.println(newUser);

assert user.getUsername().equals(newUser.getUsername());
assert user.getAge() == newUser.getAge();
assert user.isYoung() == newUser.isYoung();
}
}

结果

image.png

扩展

在spring中使用,需要在每个使用的类中注入Converter对象,过于麻烦,最好是使用工具类进行操作最为方便:

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
import io.github.linpeilie.Converter;  
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
* @author 刘靖
*/
@Component
public class MapStructUtil {

private static Converter converter = null;

@Resource
public void setConverter(Converter converter) {
MapStructUtil.converter = converter;
}

public static <S, T> T convert(S source, Class<T> targetType){
return converter.convert(source, targetType);
}

public static <S, T> T convert(S source, T target) {
return converter.convert(source, target);
}

public static <S, T> List<T> convert(List<S> source, Class<T> targetType) {
return converter.convert(source, targetType);
}

public static <T> T convert(Map<String, Object> map, Class<T> target) {
return converter.convert(map, target);
}

}
使用
1
UserDto userDto = MapStructUtil.convert(user, UserDto.class);