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 package
和spring-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 package
和spring-boot:repackage
之間的區別。
另外,我們還學習瞭如何在Maven生命週期的package
階段執行spring-boot:repackage
。