Macula Boot Starter MapStruct
概览
开发JAVA应用程序时会进行逻辑分层,各层之间为了解耦,通常会定义不同的对象进行数据传递(如XXXVO、XXXDTO、XXXPO、XXXBO)。当在不同层之间进行数据传递时,需要将这些对象进行相互转换。通常有两种处理方式:一是直接使用Setter和Getter方法转换,二是使用一些工具类进行转换(如BeanUtil.copyProperties)。第一种方式如果对象属性比较多时,要写很多的Getter/Setter代码,很繁琐;第二种方式虽然比第一种方式要简单很多,但是因为使用了反射,性能不佳。故在此推荐,统一使用MapStruct(MapStructPlus),代码简洁且不存在性能问题。
组件坐标
<dependency>
<groupId>dev.macula.boot</groupId>
<artifactId>macula-boot-starter-mapstruct</artifactId>
<version>${macula.version}</version>
</dependency>
使用配置
该组件在编译期生成转换代码,无独立运行时 YAML 配置。继承 Macula Boot 父 POM 的注解处理配置,并在 IDE 启用注解处理;具体写法见“核心功能”。
核心功能
基于MapStruct
MapStruct是一个类型转换工具,通过定义类型转换接口(如下所示),然后在编译的时候自动生成实现类来工作。
@Mapper(componentModel = MappingConstants.ComponentModel.DEFAULT)
public interface SourceTargetMapper {
SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );
@Mapping( source = "username", target = "user" )
TargetDto toTarget( SourceDto s );
}
继承 macula-boot-parent 时已配置 Lombok、mapstruct-plus-processor、lombok-mapstruct-binding 和 -Amapstruct.defaultComponentModel=spring,不必重复复制编译插件配置。默认生成 Spring Bean,优先注入 Mapper;上面的 Mappers.getMapper 示例适用于显式使用默认组件模型且无 Spring 依赖的 Mapper。
仅导入 BOM 不会继承构建插件,需在应用父 POM 中配置对应 annotation processor。此模块无运行时 YAML 属性;转换实现于编译期生成,IDE 也需启用注解处理。
MapStruct更多功能可以参考官方文档
基于MapStruct Plus
下面演示如何使用 MapStruct Plus 来映射两个对象。
假设有两个类 UserDto 和 User,分别表示数据层对象和业务层对象:
public class UserDto {
private String username;
private int age;
private boolean young;
// getter、setter、toString、equals、hashCode
}
public class User {
private String username;
private int age;
private boolean young;
// getter、setter、toString、equals、hashCode
}
测试:
@SpringBootTest
public class QuickStartTest {
private static final Converter converter = new Converter();
@Test
public void test() {
User user = new User();
user.setUsername("jack");
user.setAge(23);
user.setYoung(false);
UserDto userDto = converter.convert(user, UserDto.class);
System.out.println(userDto); // UserDto{username='jack', age=23, young=false}
assert user.getUsername().equals(userDto.getUsername());
assert user.getAge() == userDto.getAge();
assert user.isYoung() == userDto.isYoung();
User newUser = converter.convert(userDto, User.class);
System.out.println(newUser); // User{username='jack', age=23, young=false}
assert user.getUsername().equals(newUser.getUsername());
assert user.getAge() == newUser.getAge();
assert user.isYoung() == newUser.isYoung();
}
}
MapStruct Plus更多功能可以参考官方文档
依赖引入
<dependencies>
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
</dependency>
</dependencies>
版权说明
MapStruct:https://github.com/mapstruct/mapstruct/blob/main/LICENSE.txt
MapStruct Plus:https://github.com/linpeilie/mapstruct-plus/blob/main/LICENSE