springboot 打包插件spring-boot-maven-plugin打包機制及內部結構分析


今日思語:I miss you? 何解? 我錯過你了?我想你了?

 

當下許多公司都會選擇使用springboot作為服務應用開發框架,springboot框架提供了一套自己的打包機制,是通過spring-boot-maven-plugin插件來實現的。

1、spring-boot-maven-plugin引入pom

對於新建的一個springboot項目來說,pom中會加入插件:

通過idea可以看到maven中包含了spring-boot-maven-plugin插件:

功能說明:

  • build-info:生成項目的構建信息文件 build-info.properties

  • repackage:這個是默認 goal,在 mvn package 執行之后,這個命令再次打包生成可執行的 jar,同時將 mvn package 生成的 jar 重命名為 *.origin

  • run:這個可以用來運行 Spring Boot 應用

  • start:這個在 mvn integration-test 階段,進行 Spring Boot 應用生命周期的管理

  • stop:這個在 mvn integration-test 階段,進行 Spring Boot 應用生命周期的管理

spring-boot-maven-plugin插件默認在父工程sprint-boot-starter-parent中被指定為repackage,可以點擊sprint-boot-starter-parent進入父pom進行查看,如下圖:

如果需要設置其他屬性,需要在當前應用的pom中進行設置。

2、執行打包命令

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,可以被引用在其他服務中。

3、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包結構的一些分析。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM