1. 產生的問題
Spring Boot 項目打包成的可運行 jar包 ,被其他項目依賴之后,總是報錯找不到類的錯誤?
這是由於還沒有搞清楚可執行 jar 和普通 jar 到底有什么區別導致的。
2. 可運行jar與普通jar的區別
- 普通jar包:可以被其他項目應用依賴,不可以用 java -jar xxx.jar 運行。
- 可運行jar包:不可以被其他項目應用依賴,可以用 java -jar xxx.jar 運行。
注:SpringBoot項目默認打包的是可運行jar包,普通項目默認打包的是不可運行的jar包,但是,普通項目也可以打包成可運行jar包。
疑問:
同樣是執行mvn package
命令進行項目打包,為什么 Spring Boot 項目就打成了可執行 jar ,而普通項目則打包成了不可執行 jar 呢?
解答:
Spring Boot 項目默認的插件配置 spring-boot-maven-plugin 依賴包,這個打包插件存在 5 個方面的功能,如下:
五個功能分別是:
(1)build-info
:生成項目的構建信息文件 build-info.properties
(2)repackage
:這個是默認 goal,在 mvn package
執行之后,這個命令再次打包生成可執行的 jar,同時將 mvn package
生成的 jar 重命名為 *.origin
(3)run:這個可以用來運行 Spring Boot 應用
(4)start:這個在 mvn integration-test
階段,進行 Spring Boot 應用生命周期的管理
(5)stop:這個在 mvn integration-test
階段,進行 Spring Boot 應用生命周期的管理
默認情況下使用就是 repackage 功能,其他功能要使用,則需要開發者顯式配置。
3. 了解打包過程
SpringBoot的repackage 功能的 作用,就是在打包的時候,多做一點額外的事情:
(1)首先 mvn package 命令 對項目進行打包,打成一個 jar,這個 jar 就是一個普通的 jar,可以被其他項目依賴,但是不可以被執行
(2)repackage 命令,對第一步 打包成的 jar 進行再次打包,將之打成一個 可執行 jar ,通過將第一步打成的 jar 重命名為 *.original 文件
舉例說明:
Spring Boot 項目進行打包,可以執行 mvn package
命令,也可以直接在 IDEA 中點擊 package進行打包,打包結果如下顯示:
可以看到有兩個文件,admin-0.0.1-SNAPSHOT.jar 是可運行jar包,admin-0.0.1-SNAPSHOT.jar.original是被重命名的 可依賴jar包。
4. jar包之間的差異
可執行 jar 包結構:
可執行 jar 中,我們自己的代碼是存在 於 BOOT-INF/classes/
目錄下,另外,還有一個 META-INF
的目錄,該目錄下有一個 MANIFEST.MF
文件,打開該文件,內容如下:
Manifest-Version: 1.0 Created-By: Maven Jar Plugin 3.2.0 Build-Jdk-Spec: 14 Implementation-Title: admin Implementation-Version: 0.0.1-SNAPSHOT Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: org.yolo.admin.AdminApplication Spring-Boot-Version: 2.3.4.RELEASE Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Start-Class :
這就是可執行 jar 的入口類
Spring-Boot-Classes
: 代碼編譯后的位置
Spring-Boot-Lib
: 項目所依賴的 jar 的位置
如果自己要打一個可執行 jar 包的話,除了添加相關依賴之外,還需要配置 META-INF/MANIFEST.MF
文件。
不可執行 jar 包的結構:
首先將默認的后綴 .original
除去,然后給文件重命名 .jar,重命名完成,進行解壓 如下:
不可執行 jar 根目錄就相當於我們的 classpath,直接就能看到我們的代碼,並且也擁有
META-INF/MANIFEST.MF
文件,但是文件中沒有定義啟動類等配置。
Manifest-Version: 1.0 Created-By: Maven Jar Plugin 3.2.0 Build-Jdk-Spec: 14 Implementation-Title: admin Implementation-Version: 0.0.1-SNAPSHOT
注:這個不可以執行 jar 也沒有將項目的依賴打包進來。
由此可見這兩個jar包內部結構是完全不同的,因此一個可以直接執行,另一個則可以被其他項目依賴。
5. 同時打包兩個jar包
提議:一般來說,Spring Boot 直接打包成可執行 jar 就可以了,不建議將 Spring Boot 作為普通的 jar 被其他的項目所依賴。如果有這種需求,建議將被依賴的部分,單獨抽出來做一個普通的 Maven 項目,然后在 Spring Boot 中引用這個 Maven 項目。
依環境必須實現可依賴jar的話,如下可以實現:
pom.xml文件中spring-boot-maven-plugin
插件添加如下配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration> <classifier>exec</classifier> </configuration>
</plugin>
</plugins>
</build>
classifier
: 表示可執行 jar 的名字 , 執行 repackage
命令時,就不會給 mvn package
所打成的 jar 重命名 , 如下:
第一個 jar 表示可以被其他項目依賴的 jar ,第二個 jar 則表示一個可執行 jar。