mapstruct官方文檔連結,點選跳轉
mapstruct是什麼?
MapStruct 是一個代碼生成器,它基于約定優于配置方法極大地簡化了 Java bean 類型之間映射的實作。
生成的映射代碼使用簡單的方法調用,是以速度快、類型安全且易于了解。
為什麼要使用mapstruct?
多層應用程式通常需要在不同的對象模型(例如實體和 DTO)之間進行映射。編寫這樣的映射代碼是一項繁瑣且容易出錯的任務。MapStruct 旨在通過盡可能自動化來簡化這項工作。
與其他映射架構相比,MapStruct 在編譯時生成 bean 映射,這確定了高性能,允許快速的開發人員回報和徹底的錯誤檢查。
如何使用?
MapStruct 是一個注釋處理器,它被插入到 Java 編譯器中,可以在指令行建構(Maven、Gradle 等)中使用,也可以在 IDE 中使用。MapStruct 使用合理的預設值,但在配置或實作特殊行為時會避開您的方式。
入門案例
引入maven依賴
...
<properties>
<org.mapstruct.version>1.5.3.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>
實體類
/**
* @author 雲川
* @description: 車 實體類
* @date 2023/2/14 22:51
*/
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
public Car() {
}
public Car(String make, int numberOfSeats, CarType type) {
this.make = make;
this.numberOfSeats = numberOfSeats;
this.type = type;
}
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public int getNumberOfSeats() {
return numberOfSeats;
}
public void setNumberOfSeats(int numberOfSeats) {
this.numberOfSeats = numberOfSeats;
}
public CarType getType() {
return type;
}
public void setType(CarType type) {
this.type = type;
}
@Override
public String toString() {
return "Car{" +
"make='" + make + '\'' +
", numberOfSeats=" + numberOfSeats +
", type=" + type +
'}';
}
}
CartType枚舉類
/**
* @author 雲川
* @description: 車的類型枚舉值
* @date 2023/2/14 22:52
*/
public enum CarType {
TYPE_A, TYPE_B, TYPE_C;
}
DTO類
/**
* @author 雲川
* @description: 車 dto類
* @date 2023/2/14 23:01
*/
public class CarDto {
private String make;
private int seatCount;
private String type;
public CarDto() {
}
public CarDto(String make, int seatCount, String type) {
this.make = make;
this.seatCount = seatCount;
this.type = type;
}
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public int getSeatCount() {
return seatCount;
}
public void setSeatCount(int seatCount) {
this.seatCount = seatCount;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "CarDto{" +
"make='" + make + '\'' +
", seatCount=" + seatCount +
", type='" + type + '\'' +
'}';
}
}
建立映射器接口
上面的Car類和CarDTO這兩種類型非常相似
不同點:
- 隻是座位數屬性的名稱不同
- type 屬性在Car類中是一個引用類型,Car但在 DTO 中是一個普通字元串。
現在想要把Car對象轉換成CarDto對象,通過mapstruct實作,首先需要定義一個Mapper轉換器
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* @author 雲川
* @description: 轉換器
* @date 2023/2/14 23:07
*/
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
使用映射器
基于映射器接口,用戶端可以以非常簡單且類型安全的方式執行對象映射:
/**
* @author 雲川
* @description: 測試類
* @date 2023/2/14 23:22
*/
public class MapStructTest {
@Test
public void shouldMapCarToDto() {
//given
Car car = new Car( "Morris", 5, CarType.TYPEA );
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
//then
System.out.println(carDto);
}
}
結果:
檢視編譯自動生成的接口實作類
可以看到編譯之後自動生成了個實作類
位元組碼檔案反編譯:
public class CarMapperImpl implements CarMapper {
public CarMapperImpl() {
}
public CarDto carToCarDto(Car car) {
if (car == null) {
return null;
} else {
CarDto carDto = new CarDto();
carDto.setSeatCount(car.getNumberOfSeats());
carDto.setMake(car.getMake());
if (car.getType() != null) {
carDto.setType(car.getType().name());
}
return carDto;
}
}
}
MapStruct的原理是生成和我們自己寫的代碼一樣的代碼,這意味着這些值是通過簡單的
getter/setter
調用而不是反射或類似的方法從
source
類複制到
target
類的。使得MapStruct的性能會比動态架構更加優秀