SpringBoot中Fat Jar的三種打包方式詳解
在Spring Boot應(yīng)用開發(fā)中,打包是將應(yīng)用及其所有依賴整合到一個(gè)可執(zhí)行文件中的過程,這種包含所有依賴的jar文件通常被稱為"Fat Jar"。
一、Spring Boot Maven/Gradle插件默認(rèn)打包方式
1.1 基本原理
Spring Boot提供了官方的Maven和Gradle插件,用于創(chuàng)建可執(zhí)行的jar或war文件。
這是最常用的打包方式,也是Spring Boot官方推薦的方法。
該插件會(huì)創(chuàng)建一個(gè)包含應(yīng)用代碼、依賴庫以及嵌入式容器(如果需要)的自包含可執(zhí)行jar文件。
Spring Boot的jar包采用了特殊的"嵌套jar"結(jié)構(gòu),它通過自定義的JarLauncher
類加載各個(gè)嵌套的jar包,避免了傳統(tǒng)"胖jar"中的類路徑問題。
1.2 配置方式
Maven配置
在pom.xml
文件中添加Spring Boot Maven插件:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.7.0</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
執(zhí)行打包命令:
mvn clean package
Gradle配置
在build.gradle
文件中應(yīng)用Spring Boot插件:
plugins { id 'org.springframework.boot' version '2.7.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } // 其他配置... bootJar { archiveBaseName = 'myapp' archiveVersion = '1.0.0' }
執(zhí)行打包命令:
./gradlew bootJar
1.3 打包結(jié)構(gòu)分析
Spring Boot Maven/Gradle插件創(chuàng)建的Fat Jar具有以下結(jié)構(gòu):
myapp.jar
├── META-INF
│ ├── MANIFEST.MF
│ └── maven
│ └── ...
├── BOOT-INF
│ ├── classes
│ │ └── com
│ │ └── example
│ │ └── myapp
│ │ └── ...
│ └── lib
│ ├── dependency1.jar
│ ├── dependency2.jar
│ └── ...
└── org
└── springframework
└── boot
└── loader
└── ...
主要組成部分:
META-INF/MANIFEST.MF
:包含啟動(dòng)類信息和類加載器信息BOOT-INF/classes
:應(yīng)用的編譯類文件BOOT-INF/lib
:應(yīng)用的所有依賴jar文件org/springframework/boot/loader
:Spring Boot自定義的類加載器
1.4 運(yùn)行方式
通過以下命令運(yùn)行打包后的Fat Jar:
java -jar myapp.jar
也可以指定配置文件或JVM參數(shù):
java -Dspring.profiles.active=prod -Xmx512m -jar myapp.jar
1.5 高級(jí)配置
可以通過Spring Boot插件配置自定義打包行為:
Maven
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!-- 排除指定依賴 --> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> <!-- 指定主類 --> <mainClass>com.example.myapp.Application</mainClass> <!-- 包含系統(tǒng)范圍依賴 --> <includeSystemScope>true</includeSystemScope> <!-- 排除開發(fā)工具 --> <excludeDevtools>true</excludeDevtools> <!-- 創(chuàng)建分層jar --> <layers> <enabled>true</enabled> </layers> </configuration> </plugin>
Gradle
bootJar { archiveBaseName = 'myapp' archiveVersion = '1.0.0' mainClass = 'com.example.myapp.Application' // 排除特定依賴 excludeDevtools = true // 啟用分層支持 layered { enabled = true } }
1.6 優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 官方支持,與Spring Boot完全兼容
- 采用嵌套jar結(jié)構(gòu),避免了依賴沖突
- 支持直接運(yùn)行
- 提供豐富的配置選項(xiàng)
缺點(diǎn):
- 啟動(dòng)時(shí)間可能略長(zhǎng),因?yàn)樾枰馕銮短譲ar
- 特殊的jar結(jié)構(gòu)不符合標(biāo)準(zhǔn)jar規(guī)范
- 某些工具可能無法正確處理嵌套jar結(jié)構(gòu)
- 排查類加載問題相對(duì)復(fù)雜
1.7 適用場(chǎng)景
- 標(biāo)準(zhǔn)Spring Boot應(yīng)用部署
- 容器化部署(Docker)
- 云平臺(tái)部署
- 需要完整Spring Boot功能的場(chǎng)景
二、Maven Shade插件打包方式
2.1 基本原理
Maven Shade插件是一個(gè)通用的打包工具,不僅限于Spring Boot應(yīng)用。
它通過將所有依賴解壓并重新打包到一個(gè)jar文件中,創(chuàng)建一個(gè)包含所有類文件的單一jar包。
與Spring Boot插件不同,Shade創(chuàng)建的jar包沒有嵌套結(jié)構(gòu),所有類都位于同一個(gè)類路徑下。
2.2 配置方式
在pom.xml
文件中添加Maven Shade插件:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <!-- 合并META-INF/spring.factories文件 --> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.factories</resource> </transformer> <!-- 合并META-INF/spring.handlers文件 --> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <!-- 合并META-INF/spring.schemas文件 --> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> <!-- 設(shè)置主類 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.example.myapp.Application</mainClass> </transformer> </transformers> <!-- 過濾一些文件 --> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <!-- 創(chuàng)建可執(zhí)行jar --> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> </execution> </executions> </plugin> </plugins> </build>
執(zhí)行打包命令:
mvn clean package
2.3 打包結(jié)構(gòu)分析
Shade插件創(chuàng)建的Fat Jar具有以下結(jié)構(gòu):
myapp.jar
├── META-INF
│ ├── MANIFEST.MF
│ ├── spring.factories
│ ├── spring.handlers
│ ├── spring.schemas
│ └── maven
│ └── ...
├── com
│ └── example
│ └── myapp
│ └── ...
├── org
│ └── springframework
│ └── ...
└── ...
主要特點(diǎn):
- 所有依賴的類文件都被解壓并重新打包到同一個(gè)jar中
- 沒有嵌套jar結(jié)構(gòu),所有類都在同一個(gè)類路徑下
- 需要特殊處理合并META-INF下的特殊文件
2.4 運(yùn)行方式
與Spring Boot插件創(chuàng)建的jar包相同,可以通過以下命令運(yùn)行:
java -jar myapp.jar
2.5 高級(jí)配置
處理類沖突
當(dāng)多個(gè)依賴包含相同的類時(shí),可以使用relocation功能重命名包名以避免沖突:
<configuration> <relocations> <relocation> <pattern>com.google.common</pattern> <shadedPattern>com.example.shaded.com.google.common</shadedPattern> </relocation> </relocations> </configuration>
最小化最終jar
可以配置Shade插件僅包含必要的類:
<configuration> <minimizeJar>true</minimizeJar> </configuration>
自定義輸出文件名
<configuration> <finalName>myapp-${project.version}-fat</finalName> </configuration>
2.6 優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 創(chuàng)建標(biāo)準(zhǔn)jar結(jié)構(gòu),兼容性好
- 支持類重定位,解決依賴沖突
- 可以最小化最終jar大小
- 可以處理非Spring Boot應(yīng)用
缺點(diǎn):
- 需要手動(dòng)處理META-INF資源文件合并
- 可能存在類路徑?jīng)_突問題
- 配置相對(duì)復(fù)雜
- 對(duì)于大型應(yīng)用,打包過程可能較慢
2.7 適用場(chǎng)景
- 需要標(biāo)準(zhǔn)jar結(jié)構(gòu)的場(chǎng)景
- 非Spring Boot應(yīng)用
- 有特殊類路徑需求的項(xiàng)目
- 需要最小化最終jar大小的場(chǎng)景
- 需要處理復(fù)雜依賴沖突的項(xiàng)目
三、Maven Assembly插件打包方式
3.1 基本原理
Maven Assembly插件是一個(gè)靈活的打包工具,可以創(chuàng)建自定義格式的分發(fā)包,包括jar、zip、tar等。
對(duì)于Spring Boot應(yīng)用,它可以創(chuàng)建包含所有依賴的可執(zhí)行jar,類似于Shade插件,但配置方式和功能有所不同。
Assembly插件更注重于創(chuàng)建完整的分發(fā)包,可以包含配置文件、啟動(dòng)腳本等。
3.2 配置方式
在pom.xml
文件中添加Assembly插件:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifest> <mainClass>com.example.myapp.Application</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
執(zhí)行打包命令:
mvn clean package
3.3 自定義Assembly描述符
對(duì)于更復(fù)雜的打包需求,可以創(chuàng)建自定義的Assembly描述符文件:
創(chuàng)建src/assembly/dist.xml
文件:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd"> <id>distribution</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>true</includeBaseDirectory> <fileSets> <!-- 應(yīng)用jar文件 --> <fileSet> <directory>${project.build.directory}</directory> <outputDirectory>lib</outputDirectory> <includes> <include>${project.build.finalName}.jar</include> </includes> </fileSet> <!-- 配置文件 --> <fileSet> <directory>src/main/resources</directory> <outputDirectory>config</outputDirectory> <includes> <include>application*.yml</include> <include>application*.properties</include> <include>logback*.xml</include> </includes> </fileSet> <!-- 啟動(dòng)腳本 --> <fileSet> <directory>src/main/scripts</directory> <outputDirectory>bin</outputDirectory> <includes> <include>*.sh</include> <include>*.bat</include> </includes> <fileMode>0755</fileMode> </fileSet> </fileSets> <!-- 所有依賴 --> <dependencySets> <dependencySet> <outputDirectory>lib</outputDirectory> <excludes> <exclude>${project.groupId}:${project.artifactId}</exclude> </excludes> </dependencySet> </dependencySets> </assembly>
然后在pom.xml中引用該描述符:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <descriptors> <descriptor>src/assembly/dist.xml</descriptor> </descriptors> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin>
3.4 創(chuàng)建可執(zhí)行jar
如果需要?jiǎng)?chuàng)建可執(zhí)行jar,需要添加maven-jar-plugin
配置主類:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.example.myapp.Application</mainClass> </manifest> </archive> </configuration> </plugin>
3.5 打包結(jié)構(gòu)分析
使用默認(rèn)jar-with-dependencies
描述符創(chuàng)建的Fat Jar結(jié)構(gòu):
myapp-jar-with-dependencies.jar
├── META-INF
│ ├── MANIFEST.MF
│ └── maven
│ └── ...
├── com
│ └── example
│ └── myapp
│ └── ...
├── org
│ └── springframework
│ └── ...
└── ...
使用自定義描述符創(chuàng)建的分發(fā)包結(jié)構(gòu):
myapp-distribution.zip
├── bin
│ ├── start.sh
│ └── start.bat
├── config
│ ├── application.yml
│ └── logback.xml
└── lib
├── myapp.jar
├── dependency1.jar
├── dependency2.jar
└── ...
3.6 運(yùn)行方式
對(duì)于使用jar-with-dependencies
創(chuàng)建的可執(zhí)行jar:
java -jar myapp-jar-with-dependencies.jar
對(duì)于自定義分發(fā)包,使用提供的啟動(dòng)腳本:
cd myapp-distribution ./bin/start.sh
或手動(dòng)啟動(dòng):
cd myapp-distribution java -cp "lib/*" com.example.myapp.Application
3.7 優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 高度靈活,支持自定義分發(fā)包格式
- 可以包含配置文件、啟動(dòng)腳本等
- 支持多種打包格式(jar, zip, tar等)
- 可以為不同環(huán)境創(chuàng)建不同的分發(fā)包
- 適合創(chuàng)建完整的應(yīng)用分發(fā)包
缺點(diǎn):
- 配置相對(duì)復(fù)雜
- 對(duì)于簡(jiǎn)單應(yīng)用,配置過于繁瑣
- 需要額外處理類路徑和資源文件
3.8 適用場(chǎng)景
- 需要完整分發(fā)包的企業(yè)應(yīng)用
- 包含多個(gè)模塊的復(fù)雜應(yīng)用
- 需要包含配置文件和啟動(dòng)腳本的場(chǎng)景
- 需要為不同環(huán)境創(chuàng)建不同分發(fā)包的場(chǎng)景
- 有特殊分發(fā)需求的項(xiàng)目
四、總結(jié)
合理的打包策略能顯著提升開發(fā)和部署效率,是應(yīng)用成功運(yùn)行的重要環(huán)節(jié)。
通過選擇合適的打包方式,可以減少環(huán)境差異帶來的問題,提升應(yīng)用的可移植性和可維護(hù)性。
到此這篇關(guān)于SpringBoot中Fat Jar的三種打包方式詳解的文章就介紹到這了,更多相關(guān)SpringBoot打包Fat Jar內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java使用Filter實(shí)現(xiàn)自動(dòng)登錄的方法
這篇文章主要為大家詳細(xì)介紹了java使用Filter實(shí)現(xiàn)自動(dòng)登錄的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04如何避免在Java項(xiàng)目里大批量使用if-else?
想起剛開始接觸JAVA時(shí),若遇到大量流程判斷語句,幾乎滿屏都是if-else語句,多得讓自己都忘了哪里是頭,哪里是尾,但是,縱然滿屏是if-else,但彼時(shí)也沒有覺得多別扭.等到編程能力漸漸提升之后,再回過頭去看曾經(jīng)寫過的滿屏if-else時(shí),感覺全都是翔.....,需要的朋友可以參考下2021-06-06JDBC 實(shí)現(xiàn)通用的增刪改查基礎(chǔ)類方法
下面小編就為大家分享一篇JDBC 實(shí)現(xiàn)通用的增刪改查基礎(chǔ)類方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01springboot全局配置文件與多環(huán)境配置的全過程
SpringBoot項(xiàng)目在多環(huán)境配置上表現(xiàn)的非常優(yōu)秀,只需要非常簡(jiǎn)單的操作就可以完成配置,下面這篇文章主要給大家介紹了關(guān)于springboot全局配置文件與多環(huán)境配置的相關(guān)資料,需要的朋友可以參考下2021-12-12Java類成員訪問權(quán)限控制知識(shí)總結(jié)
這篇文章主要介紹了Java類成員訪問權(quán)限控制知識(shí)總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04