推薦一個神器,MapStruct,你用過嗎?

推薦一個神器,MapStruct,你用過嗎?

官網地址:http://mapstruct.org/

MapStruct是一個代碼生成器,簡化了不同的Java Bean之間映射的處理,所以映射指的就是從一個實體變化成一個實體。例如我們在實際開發中,DAO層的實體和一些數據傳輸對象(DTO),大部分屬性都是相同的,只有少部分的不同,通過mapStruct,可以讓不同實體之間的轉換變的簡單。我們只需要按照約定的方式進行配置即可。

MapStruct是一個可以處理註解的Java編譯器插件,可以在命令行中使用,也可以在IDE中使用。MapStruct有一些默認配置,但是也為用戶提供了自己進行配置的途徑。

1 開發環境搭建--基於Maven

MapStruct主要由兩部分組成:

org.mapstruct:mapstruct:包含了一些必要的註解,例如@Mapping。我們使用的JDK版本高於1.8,當我們在pom裡面導入依賴時候,建議使用座標是:org.mapstruct:mapstruct-jdk8,這可以幫助我們利用一些Java8的新特性。

org.mapstruct:mapstruct-processor:註解處理器,根據註解自動生成mapper的實現。

<code>... 

<properties>
<org.mapstruct.version>1.1.0.Beta1/<org.mapstruct.version>/<properties>
...
<dependencies>
<dependency>
<groupid>org.mapstruct/<groupid>
<artifactid>mapstruct-jdk8/<artifactid>
<version>${org.mapstruct.version}/<version>
/<dependency>
<dependency>
<groupid>junit/<groupid>
<artifactid>junit/<artifactid>
<version>4.12/<version>
/<dependency>
/<dependencies>
...
<build>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins/<groupid>
<artifactid>maven-compiler-plugin/<artifactid>
<version>3.5.1/<version>
<configuration>
<source>1.8/<source>
<target>1.8/<target>
<annotationprocessorpaths>
<path>
<groupid>org.mapstruct/<groupid>
<artifactid>mapstruct-processor/<artifactid>
<version>${org.mapstruct.version}/<version>
/<path>
/<annotationprocessorpaths>
/<configuration>
/<plugin>
/<plugins>/<build>
.../<code>

2 MapStruct2分鐘入門

下面的代碼演示瞭如何使用Map Struct實現Java Bean之間的映射。假設我們有一個表示汽車的類Car,並且還有一個數據傳輸對象(DTO)CarDTO。

這兩個類非常相似,只是表示作為數量的屬性名稱是不同的並且,在Car對象中,表示汽車類型的字段是一個枚舉,而在CarDTO中,直接使用字符串表示。

Car.java

<code>public class Car {
private String make;
private int numberOfSeats;
private CarType type;
//constructor, getters, setters etc.
}

static enum CarType {
SEDAN
}/<code>

CarDTO.java

<code>public class CarDto {

private String make;
private int seatCount;
private String type;

//constructor, getters, setters etc.
}/<code>

2.1 Mapper接口

要生成一個CarDTO與Car對象相互轉換的映射器,我們需要定義一個mapper接口。

CarMapper.java

<code>@Mapper 1
public interface CarMapper {

CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); 3

@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car); 2
}/<code>

1、@Mapper註解標記這個接口作為一個映射接口,並且是編譯時MapStruct處理器的入口。

2、真正實現映射的方法需要源對象作為參數,並返回目標對象。映射方法的名字是隨意的。對於在源對象和目標對象中,屬性名字不同的情況,可以通過@Mapping註解來配置這些名字。我們也可以將源類型與目標類型中類型不同的參數進行轉換,在這裡就是通過type屬性將枚舉類型轉換為一個字符串。當然在一個接口裡可以定義多個映射方法。MapStruct都會為其生成一個實現。

3、自動生成的接口的實現可以通過Mapper的class對象獲取。按照慣例,接口中會聲明一個成員變量INSTANCE,從而讓客戶端可以訪問Mapper接口的實現。

2.2 編譯

因為MapStruct是以Java編譯器插件的形式來處理註解,生成mapper接口的實現。因此在使用之前我們必須手工的編譯(IDE的自動編譯功能不會使用到MapStruct這個插件功能)。

執行maven命令:

<code>mvn compile/<code>

可以看到在target目錄來多個一個類CarMapperImpl.class,如下圖所示:

推薦一個神器,MapStruct,你用過嗎?

這個類實際上就是map struct插件自動幫助我們根據CarMapper接口生成的實現類。我們可以通過IDE的反編譯功能查看自動生成的實現類的源碼,如下圖所示:

推薦一個神器,MapStruct,你用過嗎?

通過反編譯的源碼,我們可以看出,對於屬性名稱不同的情況(seatCount與numberOfSeats)、以及屬性類型不同(枚舉類型的type與字符串類型的type)都自動幫助我們轉換了。對於屬性名稱不同的轉換,我們是通過在@Mapping註解指定的,而不同屬性類型的轉換,這是MapStruct的默認配置。個人感覺這個很好,很強大


2.3 使用Mapper

CarMapperTest.java

<code>public class CarMapperTest {
@Test
public void shouldMapCarToDto() {
//given
Car car = new Car( "Morris", 5, CarType.SEDAN );

//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );

//then
Assert.assertNotNull(carDto);
Assert.assertEquals(carDto.getMake(),"Morris");
Assert.assertEquals(carDto.getSeatCount() ,5);
Assert.assertEquals(carDto.getType() ,"SEDAN");
}

}/<code>

運行這個單元測試,如果沒有報錯的話,就說明我們已經成功運行這個案例了!



分享到:


相關文章: