简介
MapStruct
是一个代码生成工具,用来简化Bean之间的转换。没有MapStruct
时,我们通常用以下两种方案来解决问题:
BeanUtils.copyProperties
:基于反射来实现,效率较低,只实现了浅拷贝。get/set
:手动调用两个bean的get/set方法来实现对象拷贝,性能高,支持深拷贝,但需要耗时去编写索然无味的代码,容易出错,Bean属性发生变化后需手动修改绑定代码。
MapStruct
采用的是get/set方法来实现两个Bean之间的深拷贝,它简化了这个过程,用户不需要手动编写get/set的调用,只需要配置两个bean之间的映射。
使用方法
- 项目引入MapStruct
<properties>
<org.mapstruct.version>1.5.5.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>1.8</source> <!-- depending on your project -->
<target>1.8</target> <!-- depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
如果使用了Spring Boot
和Lombok
,需要在annotationProcessorPaths中把它们的processor也加上。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source> <!-- depending on your project -->
<target>1.8</target> <!-- depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot.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>
- IDE安装MapStruct Support插件。
- 编写Mapper类
// Car.java
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
//constructor, getters, setters etc.
}
// CatDto.java
public class CarDto {
private String make;
private int seatCount;
private String type;
//constructor, getters, setters etc.
}
// CarMapper
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
// 使用
public void test() {
Car car = new Car( "Morris", 5, CarType.SEDAN );
// 使用MapStruct将Car转换成CarDto
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
}
更多功能
除了基本的字段映射外,MapStruct还支持更多高级绑定特性:
- 绑定时忽略某个字段(不绑定某个字段)
@Mapping(target = "make", ignore = true)
CarDto carToCarDto(Car car);
- 类型转换
@Mapper
public interface CarMapper {
Car carDtoToCar(CarDto carDto);
CarType stringToCarType(String carType) {
CarType carType = xxx;
return carType;
}
}
- 使用@AfterMapping在绑定后增加自定义逻辑
@AfterMapping
default void afterMappingCar(Car car, @MappingTarget CarDto carDto) {
// TODO 为转换后的carDto对象增加自定义逻辑
}
- 使用装饰类实现自定义转换逻辑
// CarMapper
@Mapper
@DecoratedWith(CarMapperDecorator.class)
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
@RequiredArgsConstructor
public abstract class CarMapperDecorator implements CarMapper {
private final CarMapper delegate;
public CarDto carToCarDto(Car car) {
// 增加转换前的逻辑
CarDto carDto = delegate.carToCarDto(car);
// 增加转换后的逻辑
}
}