如何正確匯入mapstruct,同時避免編譯時mapstruct與lombok衝突

牛奶盒發表於2024-11-12

本文介紹編譯時產生的衝突,導包時期產生的衝突請勞駕查詢其他解決方法

一般情況下只需要按照官網的匯入即可,但如果同時使用了lombok,則需要小心。詳細資訊可以檢視官網文件:MapStruct 1.5.5.Final 整合lombok

注意:在編譯測試的時候,一定先清理再編譯。這樣可以解決80%的報錯問題

出現如下問題請清理後再編譯

[WARNING] 批註處理不適用於隱式編譯的檔案。
  使用 -implicit 指定用於隱式編譯的策略。

如果配置不正確,則可能在編譯的時候出現如下問題:

[ERROR] /E:/my_project_move/12_milkbox2/milkbox2-api/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/enums/SysMenuTypeEnum.java:[16,9] 無法將列舉 top.milkbox.sys.modular.menu.enums.SysMenuTypeEnum中的構造器 SysMenuTypeEnum應用到給定型別;
  需要: 沒有引數
  找道:    java.lang.String,java.lang.String
  原因: 實際引數列表和形式引數列表長度不同

匯入lombok和mapstruct

<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

<!-- mapstruct 資料類(bean)轉換工具 -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${org.mapstruct.version}</version>
</dependency>

除了匯入mapstruct基礎的包之外還需要配置這三個path

<!-- mapstruct與lombok同時使用的時候必須要加這個,否則某些使用lombok註解的類會在編譯的時候報錯 -->
<!-- 注意:lombok一定要放到mapstruct之前,否則在編譯的時候某些欄位可能無法被mapstruct正確處理 -->
<path>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
</path>
<!-- mapstruct 處理器 -->
<path>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>${org.mapstruct.version}</version>
</path>
<!-- additional annotation processor required as of Lombok 1.18.16 -->
<!-- 從 Lombok 1.18.16 開始需要額外的註解處理器,這個版本之前的不用加 -->
<path>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-mapstruct-binding</artifactId>
    <version>0.2.0</version>
</path>

完整的配置如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>top.milkbox</groupId>
    <artifactId>milkbox-api</artifactId>
    <version>1.0-DEV</version>
    <packaging>pom</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.1</version>
    </parent>

    <dependencies>
        <!-- spring全家桶導包...... -->
        <!-- 其他技術導包...... -->

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- mapstruct 資料類(bean)轉換工具 -->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

        <!-- 其他工具包結束 -->
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        
        <!-- 鎖定依賴版本號 -->
        <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>UTF-8</encoding>
                    <annotationProcessorPaths>
                        <!-- mapstruct與lombok同時使用的時候必須要加這個,否則某些使用lombok註解的類會在編譯的時候報錯 -->
                        <!-- 注意:lombok一定要放到mapstruct之前,否則在編譯的時候某些欄位可能無法被mapstruct正確處理 -->
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <!-- mapstruct 處理器 -->
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                        <!-- additional annotation processor required as of Lombok 1.18.16 -->
                        <!-- 從 Lombok 1.18.16 開始需要額外的註解處理器,這個版本之前的不用加 -->
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>0.2.0</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

以下為官方文件原文中英對照(豆包ai翻譯)

14.2. Lombok

MapStruct works together with Project Lombok as of MapStruct 1.2.0.Beta1 and Lombok 1.16.14.
MapStruct 與 MapStruct 1.2.0.Beta1 和 Lombok 1.16.14 的 Lombok 專案一起工作。

MapStruct takes advantage of generated getters, setters, and constructors and uses them to generate the mapper implementations.
MapStruct 利用生成的 getter、setter 和建構函式,並使用它們來生成 mapper 實現。

Lombok 1.18.16 introduces a breaking change (changelog). The additional annotation processor (Maven) must be added otherwise MapStruct stops working with Lombok. This resolves the compilation issues of Lombok and MapStruct modules.lombok-mapstruct-binding
Lombok 1.18.16 引入了一個重大更改(更新日誌)。必須新增額外的註釋處理器 (Maven),否則 MapStruct 將停止與 Lombok 一起工作。這將解決 Lombok 和 MapStruct 模組的編譯問題。lombok-mapstruct-binding

<path>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok-mapstruct-binding</artifactId>
   <version>0.2.0</version>
</path>

14.2.1. Set up 設定

The set up using Maven or Gradle does not differ from what is described in Set up. Additionally, you need to provide Lombok dependencies.
使用 Maven 或 Gradle 的設定與 設定中描述的設定沒有區別。此外,您需要提供 Lombok 依賴項。

Example 116. Maven configuration
例 116.Maven 配置

<properties>
   <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
   <org.projectlombok.version>1.18.16</org.projectlombok.version>
   <maven.compiler.source>1.8</maven.compiler.source>
   <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
   <dependency>
       <groupId>org.mapstruct</groupId>
       <artifactId>mapstruct</artifactId>
       <version>${org.mapstruct.version}</version>
   </dependency>

   <!-- Lombok dependency should not end up on classpath -->
   <!-- Lombok 依賴最終不應該出現在類路徑上。(意思就是讓你加上這個:<scope>provided</scope>) -->
   <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <version>${org.projectlombok.version}</version>
       <scope>provided</scope>
   </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>
               <target>1.8</target>
               <annotationProcessorPaths>
                   <!-- (注:這裡我不清楚是不是官方文件弄錯了,應該把lombok放到mapstruct前面,否則生成的程式碼可能會缺少許多欄位) -->
                   <path>
                       <groupId>org.mapstruct</groupId>
                       <artifactId>mapstruct-processor</artifactId>
                       <version>${org.mapstruct.version}</version>
                   </path>
                   <path>
                       <groupId>org.projectlombok</groupId>
                       <artifactId>lombok</artifactId>
                       <version>${org.projectlombok.version}</version>
                   </path>

                   <!-- additional annotation processor required as of Lombok 1.18.16 -->
                   <!-- 從 Lombok 1.18.16 開始需要額外的註解處理器 -->
                   <path>
                       <groupId>org.projectlombok</groupId>
                       <artifactId>lombok-mapstruct-binding</artifactId>
                       <version>0.2.0</version>
                   </path>
               </annotationProcessorPaths>
           </configuration>
       </plugin>
   </plugins>
</build>

Example 117. Gradle configuration (3.4 and later)
例 117.Gradle 配置(3.4 及更高版本)

dependencies {

   implementation "org.mapstruct:mapstruct:${mapstructVersion}"
   compileOnly "org.projectlombok:lombok:1.18.16"
   annotationProcessor "org.projectlombok:lombok-mapstruct-binding:0.2.0"
   annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
   annotationProcessor "org.projectlombok:lombok:1.18.16"
}

The usage combines what you already know from Defining a mapper and Lombok.
該用法結合了您在定義對映器和 Lombok 中已經瞭解的內容。

Example 118. Usage of MapStruct with Lombok
例 118.MapStruct 在 Lombok 中的使用

@Data
public class Source {

   private String test;
}

public class Target {

   private Long testing;

   public Long getTesting() {
       return testing;
   }

   public void setTesting( Long testing ) {
       this.testing = testing;
   }
}

@Mapper
public interface SourceTargetMapper {

   SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );

   @Mapping( source = "test", target = "testing" )
   Target toTarget( Source s );
}

A working example can be found on the GitHub project mapstruct-lombok.
可以在 GitHub 專案 mapstruct-lombok 上找到一個工作示例。

相關文章