最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MapStruct Plus的使用教程

 更新時間:2024年12月06日 09:14:21   作者:使用  
MapStruct和MapStructPlus是Java類型映射的工具,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

Mapstruct 是一個代碼生成器,基于約定優(yōu)于配置的方法,極大簡化了 Java bean 類型之間映射的實現(xiàn),特點:速度快、類型安全且易于理解。

Mapstruct Plus 是 MapStruct 的增強工具(類似于 Mybatis 和 Mybatis Plus 的關系),其在 MapStruct 的基礎上,實現(xiàn)了自動生成 Mapper 接口的功能,并強化了部分功能,使 Java 類型轉換更便捷、優(yōu)雅。

MapStruct Plus 內嵌 MapStruct,和 MapStruct 完全兼容,如果之前已經使用 MapStruct,可以無縫替換依賴。
參考網站:
MapStruct 官網
MapStruct Plus 官網

一、為什么要用 MapStruct(背景)

目前的系統(tǒng)開發(fā)中,對象模型之間需要相互轉換,比如一個 User 對象需要轉換為 UserVo 對象:

@Data
public class User {
    private String name;
    private int age;
    private String password;
}
@Data
public class UserVo {
    private String name;
    private int age;
}

常規(guī)的有兩種方式:

  • 使用 getter 和 setter 方法進行賦值,但是這個方法有著大量枯燥且重復的工作,一旦出錯也不易于發(fā)現(xiàn),可讀性差。
  • 使用 spring 提供的 BeanUtils 工具類進行對象之間的轉換,如下代碼塊所示,但是因為內部采用反射實現(xiàn),性能低下,出現(xiàn)問題時不容易調試。
// 創(chuàng)建一個 User 對象
User user = new User();
user.setName("wen");
user.setAge(18);
user.setPassword("123456");
// 創(chuàng)建一個 UserVo 對象
UserVo userVo = new UserVo();
// 一行代碼實現(xiàn) user => userVo
BeanUtils.copyProperties(user, userVo);

所以 MapStruct 應運而生,這個框架是基于 Java 注釋處理器,定義一個轉換接口,在編譯的時候會根據接口類和方法相關的注解,自動生成實現(xiàn)類,底層是基于 getter 和 setter 方法的,比 BeanUtils 的性能要高。然而美中不足的是,當需要轉換的對象較多或者結構復雜的時候,需要定義較多的轉換接口和轉換方法。

此時,就可以使用 MapStruct Plus ,一個注解就可以生成兩個類之間的轉換接口,使 Java 類型轉換更加便捷和優(yōu)雅。

二、MapStruct Plus 的快速開始

本文以 Spring Boot 項目為例,版本:
Spring Boot:3.3.2
JDK:17
Lombok:1.18.34

1. 引入依賴

引入 mapstruct-plus-spring-boot-starter 依賴

<dependency>
    <groupId>io.github.linpeilie</groupId>
    <artifactId>mapstruct-plus-spring-boot-starter</artifactId>
    <version>1.4.3</version>
</dependency>

引入 Maven 插件,配置項目的構建過程(這一步非常非常重要?。。。?/strong>引入 Maven 插件,配置項目的構建過程(這一步非常非常重要?。。。?/strong>引入 Maven 插件,配置項目的構建過程(這一步非常非常重要!?。。?/strong>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>17</source>
					<target>17</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>

最新版本依賴可以查看:MapStruct Plus 的 Maven 倉庫地址

2. 指定對象映射關系

在 User 或者 UserVo 上面增加注解 —— @AutoMapper,并設置 target 為對方類。
以下面代碼舉例,添加注解:@AutoMapper(target = UserVo.class)

  • User 類
@Data
@AutoMapper(target = UserVo.class)
public class User {
    private String username;
    private int age;
    private String password;
}
  • UserVo 類
@Data
@AutoMapper(target = UserVo.class)
public class User {
    private String username;
    private int age;
    private String password;
}

3. 編寫測試代碼

@SpringBootTest
public class QuickStartTest {

    @Autowired
    private Converter converter;

    @Test
    public void test() {
        // 創(chuàng)建 User 對象
        User user = new User();
        user.setUsername("wen");
        user.setAge(18);
        user.setPassword("123456");

        // 使用 MapStruct plus 進行對象間轉換:User =》 UserVo
        UserVo userVo = converter.convert(user, UserVo.class);
        // 輸出轉換之后的對象
        System.out.println(userVo);
        // 斷言測試
        assert user.getUsername().equals(userVo.getUsername());
        assert user.getAge() == userVo.getAge();
    }

}

4. 運行結果

測試通過,輸出:

在這里插入圖片描述

5. 原理解析

通過以上示例可以看出,User 對象轉化為 UserVo 對象主要是UserVo userVo = converter.convert(user, UserVo.class);這行代碼,其底層也很簡單,原理是通過 getter 和 setter 實現(xiàn)的:

public UserVo convert(User arg0) {
        if ( arg0 == null ) {
            return null;
        }

        UserVo userVo = new UserVo();

        userVo.setUsername( arg0.getUsername() );
        userVo.setAge( arg0.getAge() );

        return userVo;
    }

該代碼被保存在 target 包中,具體路徑:target/generated-sources/annotations/實體類存放路徑

在這里插入圖片描述

通過上圖,可以看到,哪怕沒有給 UserVo 實體類使用@AutoMapper注解,MapStruct Plus 會自動生成 User 轉 UserVo 的接口和實現(xiàn)類,同時也會生成 UserVo 轉換為 User 的實體類和接口。

以上為重要規(guī)則,下面也能用得到?。?!

三、自定義實體類中的屬性轉換

在上面的例子中,兩個實體類中對應的屬性都是同一種類型,那么想要自定義屬性比如:后端存儲的是字符串 String 類型的屬性,想給前端返回一個 List 類型的屬性,可以根據規(guī)則進行轉換。

下面的舉例是 String 屬性和 List 屬性之間的相互轉化(String 《===》List)

有兩種方式:

  • 自定義一個類型轉換器,通過 @AutoMapper 的 uses 屬性引入
  • 通過 @AutoMapping 中配置的 expression 表達式配置

1. 自定義一個類型轉換器

首先定義兩個類型轉換器,一個是 String 轉為 List,一個是 List 是 String。且兩個類型轉換器需要定義為 Spring 的 Bean,即使用 @Component 注解。
String 轉為 List 的轉換器:

@Component
public class StringToListConverter {

    public List<String> stringToList(String str) {
        if (str == null) {
            return Collections.emptyList();
        }
        return Arrays.asList(str.split(","));
    }

}

List 轉為 String 的轉換器:

@Component
public class ListToStringConverter {

    public String listToString(List<String> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        return String.join(",", list);
    }

}

2. 使用類型轉換器

第二步,使用該類型轉換器,即在 @AutoMapper 注解中使用 uses,且給需要轉化的屬性加上 @AutoMapping 注解,target 指向另一個需要轉化的屬性。
User 類:

@Data
@AutoMapper(target = UserVo.class, uses = StringToListConverter.class)
public class User {
    private String name;
    private int age;
    private String password;
    @AutoMapping(target = "tagList")
    private String tags;
}

UserVo 類:

@Data
@AutoMapper(target = User.class, uses = ListToStringConverter.class)
public class UserVo {
    private String name;
    private int age;
    @AutoMapping(target = "tags")
    private List<String> tagList;
}

3. 進行測試

第三步,進行測試。

@SpringBootTest
public class QuickStartTest {

    @Autowired
    private Converter converter;

    @Test
    public void test() {
        // 創(chuàng)建一個 User 對象
        User user = new User();
        user.setName("wen");
        user.setAge(18);
        user.setPassword("123456");
        user.setTags("Java,Python,C++");

        // 轉換
        UserVo userVo = converter.convert(user, UserVo.class);
        System.out.println(userVo);
        assert userVo.getTagList().size() == 3;
    }

}

測試結果:
測試用例通過,User 類中的 String 類型的 tags 屬性,成功轉化為 UserVo 類中的 List 類型的 tagList 屬性。

在這里插入圖片描述

還有一種方法是直接在注解中寫表達式,但是博主覺得這種方式沒有自定義轉換器好,所以在本文中不列舉
如果感興趣,詳情請參考:表達式自定義屬性轉換

四、Map 轉為 Object

MapStruct Plus 提供了 Map<String, Object> 轉化為對象的功能。

轉換邏輯:針對目標類中的一個屬性,首先會判斷 Map 中是否存在該鍵,如果存在的話,首先判斷類型,

  • 如果類型相同,直接強轉
  • 若果類型不同,會使用 Hutool 提供的類型轉換工具嘗試轉換為目標類型

MapStruct Plus 在 1.4.0+ 版本取消了內置 Hutool 框架,如果需要用到 Map 轉化為對象的功能時,需要引入 hutool-core 這個依賴,最新版本查看:Hutool 依賴庫

<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-core</artifactId>
   <version>5.8.29</version>
</dependency>

1. 使用步驟

  • 引入 hutool-core 依賴
  • 在目標類上添加 @AutoMapMapper 注解
  • 同時支持自定義類作為屬性,需要在自定義類上增加 @AutoMapMapper 注解

2. 定義對象

為了更好的理解,直接用最復雜的 Map 轉對象的例子舉例,即內部屬性既有基本類型,也有自定義的對象

定義一個 Body 類,里面有身高體重屬性,定義一個 Person 類,里面有基本信息和一個 Body 類型的屬性。

Body 類:

@Data
@AutoMapMapper
public class Body {
    private int height;
    private int weight;
}

Person 類:

@Data
@AutoMapMapper
public class Person {
    private String name;
    private Integer age;
    private Body body;
}

3. 轉換測試

@SpringBootTest
public class MapToObjectTest {

    @Autowired
    private Converter converter;

    @Test
    public void test() {
        // 創(chuàng)建一個 Map,鍵是 Body 的屬性名,值是屬性值
        Map<String, Object> map1 = new HashMap<>();
        map1.put("height", 180);
        map1.put("weight", 150);

        // 創(chuàng)建第二個 Map,鍵是 Person 的屬性名,值是屬性值
        Map<String, Object> map2 = new HashMap<>();
        map2.put("name", "wen");
        map2.put("age", 18);
        map2.put("body", map1);

        // 將 Map2 轉化為 Person 對象
        Person person = converter.convert(map2, Person.class);
        System.out.println(person);
    }

}

測試成功,Map 對象成功轉化為 Person 對象:

在這里插入圖片描述

五、枚舉類型轉換

枚舉類型的轉換,需要在枚舉類上添加 @AutoEnumMapper 注解,增加該注解后,在任意類型中需要轉換該枚舉時都可以自動轉換。
使用 @AutoEnumMapper 注解的時候,需要注意:這個枚舉類必須要有一個可以保證唯一的字段,并將該字段添加到注解的 value屬性中

1. 定義一個枚舉類

定義一個狀態(tài)枚舉類,唯一字段是 code,用來表示開始還是關閉:

@Getter
@AllArgsConstructor
@AutoEnumMapper("code")
public enum StateEnum {
    ENABLE(1, "啟用"),
    DISABLE(0, "禁用");
    private final int code;
    private final String desc;
}

2. 定義要轉換的對象

定義一個保存枚舉類的類 Course,再定義一個需要轉換的 CourseVo 類:

Course 類:

@Data
@AutoMapper(target = CourseVo.class)
public class Course {

    private StateEnum state;

}

CourseVo 類:

@Data
public class CourseVo {

    private Integer state;

}

3. 轉換測試

@SpringBootTest
public class EnumToValueTest {

    @Autowired
    private Converter converter;

    @Test
    public void test() {
        // 創(chuàng)建一個 Course 對象
        Course course = new Course();
        course.setState(StateEnum.ENABLE);

        // 將 Course 對象轉換為 CourseVo 對象
        CourseVo courseVo = converter.convert(course, CourseVo.class);
        System.out.println(courseVo);

        // 將 CourseVo 對象轉換為 Course 對象
        Course course1 = converter.convert(courseVo, Course.class);
        System.out.println(course1);
    }

}

測試成功,Enum 可以轉化為整形,整形也可以轉化為 Enum:

在這里插入圖片描述

4. 注意

枚舉和使用枚舉的類需要在同一個模塊(module)中。

當枚舉與要使用的類型,不在同一個模塊中,是不能自動轉換的,需要指定依賴關系。在 @AutoMapper 注解中,可以通過 useEnums 來指定需要依賴的枚舉類列表。

六、一個類與多個類之間的轉換

MapStruct Plus 還支持一個類和多個類進行轉換,可以通過 @AutoMappers 來配置,該注解支持配置多個 @AutoMapper。

在配置多個類進行轉化的時候,多個類可能有相同的屬性,為了解決屬性沖突的問題,可以使用 @AutoMappings 指定多個轉換規(guī)則,并且在使用 @AutoMapping 注解時,配置 targetClass 屬性,指定當前規(guī)則的目標轉化類。

如果配置 @AutoMapping 注解時,沒有指定 targetClass,那么當前規(guī)則就會應用所有類轉換。

1. 定義對象

定義一個 User 類,一個 Course 類,一個 UserVo 類。其中 UserVo 類將與 User 類和 Course 類互相映射(UserVo 《===》User、Course)。User 類和 Course 類都有 name 屬性,但是只將 User 類中的 name 屬性映射。

User 類:

@Data
@AutoMapper(target = UserVo.class, uses = StringToListConverter.class)
public class User {

    private String name;

    private int age;

    private String password;

    @AutoMapping(target = "tagList")
    private String tags;
}

Course 類:

@Data
@AutoMapper(target = UserVo.class)
public class Course {

    @AutoMapping(targetClass = UserVo.class, ignore = true) // 忽略 UserVo 中的 name 屬性
    private String name;

    private String teacher;

}

UserVo 類:

@Data
@AutoMappers({
        @AutoMapper(target = User.class, uses = ListToStringConverter.class),
        @AutoMapper(target = Course.class)
})
public class UserVo {

    @AutoMappings({
            @AutoMapping(targetClass = User.class),
            @AutoMapping(targetClass = Course.class, ignore = true)
    })
    private String name;

    private int age;

    @AutoMapping(targetClass = User.class, target = "tags")
    private List<String> tagList;

    private String teacher;
}

2. 轉換測試

@SpringBootTest
public class OneToOthersTest {

    @Autowired
    private Converter converter;

    @Test
    public void test() {
        // 創(chuàng)建 User 對象
        User user = new User();
        user.setName("wen");
        user.setAge(18);
        user.setPassword("123456");
        user.setTags("Java,Python,Go,C++");

        // 創(chuàng)建 Course 對象
        Course course = new Course();
        course.setName("Java 開發(fā)");
        course.setTeacher("教 Java 的老師");

        // 轉換(User 對象和 Course 對象)為 UserVo 對象
        UserVo userVo = converter.convert(user, UserVo.class);
        userVo = converter.convert(course, userVo);
        System.out.println(userVo);

        // 轉換 UserVo 對象為(User 對象和 Course 對象)
        user = converter.convert(userVo, User.class);
        course = converter.convert(userVo, Course.class);
        System.out.println(user);
        System.out.println(course);
    }

}

3. 測試結果

在這里插入圖片描述

總結

本文使用大量示例詳細解釋了在 Spring Boot 項目開發(fā)中使用 MapStruct Plus 的方法,多加練習熟能生巧。技術沒有高低之分,不管是使用原始的 getter/setter 方法,還是使用 BeanUtils,亦或者使用本文所介紹的 MapStruct Plus,只要找到解決問題的合適方案就可以。

到此這篇關于MapStruct Plus的使用教程的文章就介紹到這了,更多相關MapStruct Plus內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java中數(shù)組和String相互轉換的幾種常見方法

    Java中數(shù)組和String相互轉換的幾種常見方法

    這篇文章主要介紹了Java中數(shù)組和String相互轉換的幾種常見方法,每種類型都有相應的轉換方法,如使用String類的構造函數(shù)、toCharArray()、String.join()、Arrays.toString()、StringBuilder等,這些方法能幫助開發(fā)者高效地進行數(shù)據類型之間的轉換,需要的朋友可以參考下
    2025-04-04
  • JavaWeb表單注冊界面的實現(xiàn)方法

    JavaWeb表單注冊界面的實現(xiàn)方法

    這篇文章主要介紹了JavaWeb表單注冊界面的實現(xiàn)方法的相關資料,希望通過本文大家能掌握這部分內容,需要的朋友可以參考下
    2017-09-09
  • Java中初始化List集合的八種方式匯總

    Java中初始化List集合的八種方式匯總

    List?是?Java?開發(fā)中經常會使用的集合,下面這篇文章主要給大家介紹了關于Java中初始化List集合的八種方式,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-06-06
  • springboot實現(xiàn)配置文件關鍵信息加解密

    springboot實現(xiàn)配置文件關鍵信息加解密

    在項目配置文件中常常會配置如數(shù)據庫連接信息,redis連接信息等,連接密碼明文配置在配置文件中會很不安全,所以本文就來聊聊如何使用springboot實現(xiàn)配置文件關鍵信息加解密吧
    2025-05-05
  • java內存模型jvm虛擬機簡要分析

    java內存模型jvm虛擬機簡要分析

    Java 內存模型的主要目的是定義程序中各種變量的訪問規(guī)則, 關注在虛擬機中把變量值存儲到內存和從內存中取出變量值這樣的底層細節(jié)
    2021-09-09
  • 學習Java之如何正確地向上轉型與向下轉型

    學習Java之如何正確地向上轉型與向下轉型

    面向對象的第三個特征是多態(tài),實現(xiàn)多態(tài)有三個必要條件:繼承、方法重寫和向上轉型,在學習多態(tài)之前,我們還要先學習Java的類型轉換,本篇文章就來帶大家認識什么是類型轉換,看看類型轉換都有哪幾種情況,以及如何避免類型轉換時出現(xiàn)異常
    2023-05-05
  • 在idea環(huán)境下構建springCloud項目

    在idea環(huán)境下構建springCloud項目

    本篇文章主要介紹了在idea環(huán)境下構建springCloud項目,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • java動態(tài)代理實現(xiàn)代碼

    java動態(tài)代理實現(xiàn)代碼

    這篇文章主要介紹了java 動態(tài)代理的的相關資料,文中講解非常細致,代碼幫助大家更好的理解和學習,感興趣的朋友可以了解下,希望能給你帶來幫助
    2021-07-07
  • Java Socket編程實例(二)- UDP基本使用

    Java Socket編程實例(二)- UDP基本使用

    這篇文章主要講解Java Socket編程中UDP的基本使用,希望能給大家做一個參考。
    2016-06-06
  • Spring Boot整合logback一個簡單的日志集成架構

    Spring Boot整合logback一個簡單的日志集成架構

    今天小編就為大家分享一篇關于Spring Boot整合logback一個簡單的日志集成架構,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01

最新評論

勃利县| 保德县| 韩城市| 虹口区| 合作市| 巢湖市| 广南县| 江口县| 金寨县| 马龙县| 神木县| 益阳市| 遂平县| 邯郸市| 江达县| 宁河县| 绵竹市| 尉氏县| 沙河市| 电白县| 麟游县| 克东县| 华坪县| 兰西县| 进贤县| 蕉岭县| 长乐市| 普陀区| 伊吾县| 香格里拉县| 新邵县| 南宁市| 临洮县| 贞丰县| 波密县| 明溪县| 沈丘县| 西昌市| 龙川县| 朔州市| 呼伦贝尔市|