今日思語:I miss you? 何解? 我錯過你了?我想你了?java
當下許多公司都會選擇使用springboot做爲服務應用開發框架,springboot框架提供了一套本身的打包機制,是經過spring-boot-maven-plugin插件來實現的。spring
一、spring-boot-maven-plugin引入pom
對於新建的一個springboot項目來講,pom中會加入插件:springboot
經過idea能夠看到maven中包含了spring-boot-maven-plugin插件:框架
功能說明:maven
-
build-info:生成項目的構建信息文件 build-info.propertieside
-
repackage:這個是默認 goal,在
mvn package
執行以後,這個命令再次打包生成可執行的 jar,同時將mvn package
生成的 jar 重命名爲*.origin
spring-boot -
run:這個能夠用來運行 Spring Boot 應用工具
-
start:這個在
mvn integration-test
階段,進行Spring Boot
應用生命週期的管理開發工具 -
stop:這個在
mvn integration-test
階段,進行Spring Boot
應用生命週期的管理ui
spring-boot-maven-plugin插件默認在父工程sprint-boot-starter-parent中被指定爲repackage,能夠點擊sprint-boot-starter-parent進入父pom進行查看,以下圖:
若是須要設置其餘屬性,須要在當前應用的pom中進行設置。
二、執行打包命令
mvn clean package
或者經過開發工具如idea執行clean和package倆命令:
執行以上命令時會自動觸發spring-boot-maven-plugin插件的repackage目標,完後能夠在target目錄下看到生成的jar,以下圖:
這裏能夠看到生成了兩個jar相關文件,其中common.jar是spring-boot-maven-plugin插件從新打包後生成的可執行jar,便可以經過java -jar common.jar命令啓動。common.jar.original這個則是mvn package打包的原始jar,在spring-boot-maven-plugin插件repackage命令操做時重命名爲xxx.original,這個是一個普通的jar,能夠被引用在其餘服務中。
三、jar內部結構
對這兩個jar文件解壓看看裏面的結構差別:
3.1 common.jar目錄結構以下:
其中BOOT-INF主要是一些啓動信息,包含classes和lib文件,classes文件放的是項目裏生成的字節文件class和配置文件,lib文件是項目所須要的jar依賴。
META-INF目錄下主要是maven的一些元數據信息,MANIFEST.MF文件內容以下:
Manifest-Version: 1.0 Implementation-Title: java-common-utils Implementation-Version: 0.0.1-SNAPSHOT Start-Class: com.common.util.CommonUtilsApplication Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Build-Jdk-Spec: 1.8 Spring-Boot-Version: 2.1.9.RELEASE Created-By: Maven Archiver 3.4.0 Main-Class: org.springframework.boot.loader.JarLauncher
其中Start-Class是項目的主程序入口,即main方法。Springboot-Boot-Classes和Spring-Boot-Lib指向的是生成的BOOT-INF下的對應位置。
Main-Class屬性值爲org.springframework.boot.loader.JarLauncher,這個值能夠經過設置屬性layout來控制,以下:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!--使用-Dloader.path須要在打包的時候增長<layout>ZIP</layout>,不指定的話-Dloader.path不生效--> <layout>ZIP</layout> <!-- 指定該jar包啓動時的主類[建議] --> <mainClass>com.common.util.CommonUtilsApplication</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>
設置<layout>ZIP</layout>時Main-Class爲org.springframework.boot.loader.PropertiesLauncher,具體layout值對應Main-Class關係以下:
- JAR,即一般的可執行jar
Main-Class: org.springframework.boot.loader.JarLauncher
- WAR,即一般的可執行war,須要的servlet容器依賴位於WEB-INF/lib-provided
Main-Class: org.springframework.boot.loader.warLauncher
- ZIP,即DIR,相似於JAR
Main-Class: org.springframework.boot.loader.PropertiesLauncher
- MODULE,將全部的依賴庫打包(scope爲provided的除外),可是不打包Spring Boot的任何Launcher
- NONE,將全部的依賴庫打包,可是不打包Spring Boot的任何Launcher
common.jar之因此可使用java -jar運行,和MANIFEST.MF文件裏的配置關係密切
3.2 original jar包結構
能夠看到經過mvn package構建的jar是一個普通的jar,包含的都是項目的字節文件和一些配置文件,沒有將項目依賴的第三方jar包含進來。再看下MANIFEST.MF文件:
Manifest-Version: 1.0 Implementation-Title: java-common-utils Implementation-Version: 0.0.1-SNAPSHOT Build-Jdk-Spec: 1.8 Created-By: Maven Archiver 3.4.0
其中沒有包含Start-Class、Main-Class等信息,這個與可執行jar的該文件存在不少差別,並且目錄結構也有很大差別。
通常對使用spring-boot-maven-plugin插件打出的可執行jar不建議做爲jar給其餘服務引用,由於可能出現訪問可執行jar中的一些配置文件找不到的問題。若是想讓構建出來的原始jar不被從新打包,能夠對spring-boot-maven-plugin插件配置classifier屬性,自定義一個可運行jar名稱,這樣該插件就不會對原始的jar重命名操做了。
<configuration> <!-- 指定該jar包啓動時的主類[建議] --> <mainClass>com.common.util.CommonUtilsApplication</mainClass> <!--配置的 classifier 表示可執行 jar 的名字,配置了這個以後,在插件執行 repackage 命令時, 就不會給 mvn package 所打成的 jar 重命名了,這樣就能夠被其餘項目引用了,classifier命名的爲可執行jar--> <classifier>myexec</classifier> </configuration>
效果以下:
以上是對spring-boot-maven-plugin插件的打包機制和jar包結構的一些分析。