spring-boot:repackage和Maven:package之間的區別

    1.概述

    Apache Maven是一種廣泛使用的項目依賴項管理工具和項目構建工具。

    在過去的幾年中,Spring Boot已經成為構建應用程序的非常流行的框架。還有一個Spring Boot Maven插件在Apache Maven中提供Spring Boot支持。

    我們知道,當我們想使用Maven將應用程序打包在JAR或WAR工件中時,可以使用mvn package 。但是,Spring Boot Maven插件附帶了一個repackage目標,它也在mvn命令中被調用。

    有時,這兩個mvn命令令人困惑。在本教程中,我們將討論mvn packagespring-boot:repackage的區別。

    2. Spring Boot應用示例

    首先,我們將創建一個簡單的Spring Boot應用程序作為示例:

    @SpringBootApplication
    
     public class DemoApplication {
    
     public static void main(String[] args) {
    
     SpringApplication.run(DemoApplication.class, args);
    
     }
    
     }

    為了驗證我們的應用程序是否已啟動並正在運行,讓我們創建一個簡單的REST端點:

    @RestController
    
     public class DemoRestController {
    
     @GetMapping(value = "/welcome")
    
     public ResponseEntity welcomeEndpoint() {
    
     return ResponseEntity.ok("Welcome to Baeldung Spring Boot Demo!");
    
     }
    
     }

    3. Maven的package目標

    我們只需要spring-boot-starter-web依賴關係來構建我們的Spring Boot應用程序:

    <artifactId>spring-boot-artifacts-2</artifactId>
    
     <packaging>jar</packaging>
    
     ...
    
     <dependency>
    
     <groupId>org.springframework.boot</groupId>
    
     <artifactId>spring-boot-starter-web</artifactId>
    
     </dependency>
    
     ...

    Maven的package目標將採用編譯後的代碼並將其打包為可分發格式,在這種情況下為JAR格式:

    $ mvn package
    
     [INFO] Scanning for projects...
    
     [INFO] ------< com.baeldung.spring-boot-modules:spring-boot-artifacts-2 >------
    
     [INFO] Building spring-boot-artifacts-2 1.0.0-SNAPSHOT
    
     [INFO] --------------------------------[ jar ]---------------------------------
    
     ...
    
     [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ spring-boot-artifacts-2 ---
    
     [INFO] Building jar: /home/kent ... /target/spring-boot-artifacts-2.jar
    
     [INFO] ------------------------------------------------------------------------
    
     [INFO] BUILD SUCCESS
    
     [INFO] ------------------------------------------------------------------------
    
     ...

    執行mvn package命令後,我們可以在target目錄下找到已構建的JAR文件spring-boot-artifacts-2.jar 。讓我們檢查創建的JAR文件的內容:

    $ jar tf target/spring-boot-artifacts-2.jar
    
     META-INF/
    
     META-INF/MANIFEST.MF
    
     com/
    
     com/baeldung/
    
     com/baeldung/demo/
    
     application.yml
    
     com/baeldung/demo/DemoApplication.class
    
     com/baeldung/demo/DemoRestController.class
    
     META-INF/maven/...
    

    從上面的輸出中可以看到, mvn package命令創建的JAR文件僅包含來自項目源的資源和已編譯的Java類

    我們可以將此JAR文件用作另一個項目中的依賴項。但是,即使它是Spring Boot應用程序,我們也不能使用java -jar JAR_FILE執行JAR文件。這是因為沒有捆綁運行時依賴項。例如,我們沒有Servlet容器來啟動Web上下文。

    要使用簡單的java -jar命令啟動我們的Spring Boot應用程序,我們需要構建一個胖的JAR。 Spring Boot Maven插件可以幫助我們。

    4. Spring Boot Maven插件的repackage目標

    現在,讓我們弄清楚spring-boot:repackage作用。

    4.1。添加Spring Boot Maven插件

    要執行repackage目標,我們需要在pom.xml添加Spring Boot Maven插件:

    <build>
    
     <finalName>${project.artifactId}</finalName>
    
     <plugins>
    
     <plugin>
    
     <groupId>org.springframework.boot</groupId>
    
     <artifactId>spring-boot-maven-plugin</artifactId>
    
     </plugin>
    
     </plugins>
    
     </build>

    4.2。執行spring-boot:repackage目標

    現在,讓我們清理先前構建的JAR文件,並嘗試使用spring-boot:repackage

    $ mvn clean spring-boot:repackage
    
     ...
    
     [INFO] --- spring-boot-maven-plugin:2.3.3.RELEASE:repackage (default-cli) @ spring-boot-artifacts-2 ---
    
     [INFO] ------------------------------------------------------------------------
    
     [INFO] BUILD FAILURE
    
     [INFO] ------------------------------------------------------------------------
    
     ...
    
     [ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.3.3.RELEASE:repackage (default-cli)
    
     on project spring-boot-artifacts-2: Execution default-cli of goal
    
     org.springframework.boot:spring-boot-maven-plugin:2.3.3.RELEASE:repackage failed: Source file must not be null -> [Help 1]
    
     ...
    

    糟糕,這行不通。這是因為**spring-boot:repackage目標將現有的JAR或WAR歸檔文件作為源,並將最終項目中的所有項目運行時依賴項與項目類一起重新打包。這樣,可以使用命令行java -jar JAR_FILE.jar來執行重新打包的工件。**

    因此,我們需要在執行spring-boot:repackage目標之前先構建JAR文件:

    $ mvn clean package spring-boot:repackage
    
     ...
    
     [INFO] Building spring-boot-artifacts-2 1.0.0-SNAPSHOT
    
     [INFO] --------------------------------[ jar ]---------------------------------
    
     ...
    
     [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ spring-boot-artifacts-2 ---
    
     [INFO] Building jar: /home/kent/.../target/spring-boot-artifacts-2.jar
    
     [INFO]
    
     [INFO] --- spring-boot-maven-plugin:2.3.3.RELEASE:repackage (default-cli) @ spring-boot-artifacts-2 ---
    
     [INFO] Replacing main artifact with repackaged archive
    
     [INFO] ------------------------------------------------------------------------
    
     [INFO] BUILD SUCCESS
    
     ...

    4.3。重新打包的JAR文件的內容

    現在,如果我們檢查target目錄,我們將看到重新打包的JAR文件和原始JAR文件:

    $ ls -1 target/*jar*
    
     target/spring-boot-artifacts-2.jar
    
     target/spring-boot-artifacts-2.jar.original
    

    讓我們檢查重新打包的JAR文件的內容:

    $ jar tf target/spring-boot-artifacts-2.jar
    
     META-INF/
    
     META-INF/MANIFEST.MF
    
     ...
    
     org/springframework/boot/loader/JarLauncher.class
    
     ...
    
     BOOT-INF/classes/com/baeldung/demo/
    
     BOOT-INF/classes/application.yml
    
     BOOT-INF/classes/com/baeldung/demo/DemoApplication.class
    
     BOOT-INF/classes/com/baeldung/demo/DemoRestController.class
    
     META-INF/maven/com.baeldung.spring-boot-modules/spring-boot-artifacts-2/pom.xml
    
     META-INF/maven/com.baeldung.spring-boot-modules/spring-boot-artifacts-2/pom.properties
    
     BOOT-INF/lib/
    
     BOOT-INF/lib/spring-boot-starter-web-2.3.3.RELEASE.jar
    
     ...
    
     BOOT-INF/lib/spring-boot-starter-tomcat-2.3.3.RELEASE.jar
    
     BOOT-INF/lib/tomcat-embed-core-9.0.37.jar
    
     BOOT-INF/lib/jakarta.el-3.0.3.jar
    
     BOOT-INF/lib/tomcat-embed-websocket-9.0.37.jar
    
     BOOT-INF/lib/spring-web-5.2.8.RELEASE.jar
    
     ...
    
     BOOT-INF/lib/httpclient-4.5.12.jar
    
     ...
    

    如果我們檢查上面的輸出,則它比mvn package命令構建的JAR文件長得多。

    在這裡,在重新打包的JAR文件中,我們不僅具有來自項目的已編譯Java類,而且還具有啟動Spring Boot應用程序所需的所有運行時庫。例如,嵌入式tomcat庫被打包到BOOT-INF/lib目錄中。

    接下來,讓我們啟動我們的應用程序並檢查它是否有效:

    $ java -jar target/spring-boot-artifacts-2.jar
    
     . ____ _ __ _ _
    
     /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
    
     ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
    
     \\/ ___)| |_)| | | | | || (_| | ) ) ) )
    
     ' |____| .__|_| |_|_| |_\__, | / / / /
    
     =========|_|==============|___/=/_/_/_/
    
    
    
     2020-12-22 23:36:32.704 INFO 115154 [main] com.baeldung.demo.DemoApplication : Starting DemoApplication on YK-Arch with PID 11515...
    
     ...
    
     2020-12-22 23:36:34.070 INFO 115154 [main] osbwembedded.tomcat.TomcatWebServer: Tomcat started on port(s): 8080 (http) ...
    
     2020-12-22 23:36:34.078 INFO 115154 [main] com.baeldung.demo.DemoApplication : Started DemoApplication in 1.766 seconds ...
    

    我們的Spring Boot應用程序已啟動並正在運行。現在,讓我們通過調用/welcome端點來驗證它:

    $ curl http://localhost:8080/welcome
    
     Welcome to Baeldung Spring Boot Demo!

    大!我們得到了預期的答复。我們的應用程序正常運行。

    4.4。在Maven的軟件包生命週期中執行spring-boot:repackage目標

    我們可以在pom.xml配置Spring Boot Maven插件,以在Maven生命週期的package階段重新打包工件。換句話說,當我們執行mvn package, spring-boot:repackage將被自動執行。

    配置非常簡單。我們只是將repackage目標添加到execution元素中:

    <build>
    
     <finalName>${project.artifactId}</finalName>
    
     <plugins>
    
     <plugin>
    
     <groupId>org.springframework.boot</groupId>
    
     <artifactId>spring-boot-maven-plugin</artifactId>
    
     <executions>
    
     <execution>
    
     <goals>
    
     <goal>repackage</goal>
    
     </goals>
    
     </execution>
    
     </executions>
    
     </plugin>
    
     </plugins>
    
     </build>

    現在,讓我們再次運行mvn clean package

    $ mvn clean package
    
     ...
    
     [INFO] Building spring-boot-artifacts-2 1.0.0-SNAPSHOT
    
     [INFO] --------------------------------[ jar ]---------------------------------
    
     ...
    
     [INFO] --- spring-boot-maven-plugin:2.3.3.RELEASE:repackage (default) @ spring-boot-artifacts-2 ---
    
     [INFO] Replacing main artifact with repackaged archive
    
     [INFO] ------------------------------------------------------------------------
    
     [INFO] BUILD SUCCESS
    
     ...

    輸出顯示重新打包目標已執行。如果檢查文件系統,我們會發現重新打包的JAR文件已創建:

    $ ls -lh target/*jar*
    
     -rw-r--r-- 1 kent kent 29M Dec 22 23:56 target/spring-boot-artifacts-2.jar
    
     -rw-r--r-- 1 kent kent 3.6K Dec 22 23:56 target/spring-boot-artifacts-2.jar.original
    

    5.結論

    在本文中,我們討論了mvn packagespring-boot:repackage之間的區別。

    另外,我們還學習瞭如何在Maven生命週期的package階段執行spring-boot:repackage