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官方推薦的方法。
該插件會創(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 高級配置
可以通過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í)間可能略長,因?yàn)樾枰馕銮短譲ar
- 特殊的jar結(jié)構(gòu)不符合標(biāo)準(zhǔn)jar規(guī)范
- 某些工具可能無法正確處理嵌套jar結(jié)構(gòu)
- 排查類加載問題相對復(fù)雜
1.7 適用場景
- 標(biāo)準(zhǔn)Spring Boot應(yīng)用部署
- 容器化部署(Docker)
- 云平臺部署
- 需要完整Spring Boot功能的場景
二、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 高級配置
處理類沖突
當(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)_突問題
- 配置相對復(fù)雜
- 對于大型應(yīng)用,打包過程可能較慢
2.7 適用場景
- 需要標(biāo)準(zhǔn)jar結(jié)構(gòu)的場景
- 非Spring Boot應(yīng)用
- 有特殊類路徑需求的項(xiàng)目
- 需要最小化最終jar大小的場景
- 需要處理復(fù)雜依賴沖突的項(xiàng)目
三、Maven Assembly插件打包方式
3.1 基本原理
Maven Assembly插件是一個(gè)靈活的打包工具,可以創(chuàng)建自定義格式的分發(fā)包,包括jar、zip、tar等。
對于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描述符
對于更復(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)行方式
對于使用jar-with-dependencies創(chuàng)建的可執(zhí)行jar:
java -jar myapp-jar-with-dependencies.jar
對于自定義分發(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):
- 配置相對復(fù)雜
- 對于簡單應(yīng)用,配置過于繁瑣
- 需要額外處理類路徑和資源文件
3.8 適用場景
- 需要完整分發(fā)包的企業(yè)應(yīng)用
- 包含多個(gè)模塊的復(fù)雜應(yīng)用
- 需要包含配置文件和啟動(dòng)腳本的場景
- 需要為不同環(huán)境創(chuàng)建不同分發(fā)包的場景
- 有特殊分發(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java開發(fā)hutool HttpUtil網(wǎng)絡(luò)請求工具使用demo
這篇文章主要為大家介紹了hutool之HttpUtil網(wǎng)絡(luò)請求工具使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Java實(shí)現(xiàn)Consul/Nacos根據(jù)GPU型號、顯存余量執(zhí)行負(fù)載均衡的步驟詳解
這篇文章主要介紹了Java實(shí)現(xiàn)Consul/Nacos根據(jù)GPU型號、顯存余量執(zhí)行負(fù)載均衡的步驟詳解,本文分步驟結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2025-04-04
IDEA修改java文件后 不用重啟Tomcat服務(wù)便可實(shí)現(xiàn)自動(dòng)更新
這篇文章主要介紹了IDEA修改java文件后 不用重啟Tomcat服務(wù)便可實(shí)現(xiàn)自動(dòng)更新,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
SpringBoot中過濾器Filter+JWT令牌實(shí)現(xiàn)登錄驗(yàn)證
本文主要介紹了SpringBoot中過濾器Filter+JWT令牌實(shí)現(xiàn)登錄驗(yàn)證,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-04-04
關(guān)于post請求內(nèi)容無法重復(fù)獲取的解決方法
這篇文章主要介紹了關(guān)于post請求內(nèi)容無法重復(fù)獲取的解決方法,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-03-03
基于Mybatis plus 自動(dòng)代碼生成器的實(shí)現(xiàn)代碼
本文通過實(shí)例代碼給大家介紹了基于Mybatis-plus 自動(dòng)代碼生成器的相關(guān)知識,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-05-05
Java部分序列化之關(guān)鍵字transient使用及說明
Java序列化將對象轉(zhuǎn)為字節(jié)序列用于存儲或傳輸,需實(shí)現(xiàn)Serializable接口,transient關(guān)鍵字可排除敏感字段或不可序列化對象,避免反序列化時(shí)恢復(fù)無效數(shù)據(jù)或泄露信息2025-09-09

