开发者

SpringBoot中Fat Jar的三种打包方式详解

目录
  • 一、Spring Boot Maven/Gradle插件默认打包方式
    • 1.1 基本原理
    • 1.2 配置方式
    • 1.3 打包结构分析
    • 1.4 运行方式
    • 1.5 高级配置
    • Gradle
    • 1.6 优缺点分析
    • 1.7 适用场景
  • 二、Maven Shade插件打包方式
    • 2.1 基本原理
    • 2.2 配置方式
    • 2.3 打包结构分析
    • 2.4 运行方式
    • 2.5 高级配置
    • 2.6 优缺点分析
    • 2.7 适用场景
  • 三、Maven Assembly插件打包方式
    • 3.1 基本原理
    • 3.2 配置方式
    • 3.3 自定义Assembly描述符
    • 3.4 创建可执行jar
    • 3.5 打包结构分析
    • 3.6 运行方式
    • 3.7 优缺点分析
    • 3.8 适用场景
  • 四、总结

    在Spring Boot应用开发中,打包是将应用及其所有依赖整合到一个可执行文件中的过程,这种包含所有依赖的jar文件通常被称为"Fat Jar"。

    一、Spring Boot Maven/Gradle插件默认打包方式

    1.1 基本原理

    Spring Boot提供了官方的Maven和Gradle插件,用于创建可执行的jar或war文件。

    这是最常用的打包方式,也是Spring Boot官方推荐的方法。

    该插件会创建一个包含应用代码、依赖库以及嵌入式容器(如果需要)的自包含可执行jar文件。

    Spring Boot的jar包采用了特殊的"嵌套jar"结构,它通过自定义的JarLauncher类加载各个嵌套的jar包,避免了传统"胖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>

    执行打包命令:

    mvn clean package

    Gradle配置

    build.gradle文件中应用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'
    }

    执行打包命令:

    ./gradlew bootJar

    1.3 打包结构分析

    Spring Boot Maven/Gradle插件创建的Fat Jar具有以下结构:

    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:包含启动类信息和类加载器信息
    • BOOT-INF/classes:应用的编译类文件
    • BOOT-INF/lib:应用的所有依赖jar文件
    • org/springframework/boot/loader:Spring Boot自定义的类加载器

    1.4 运行方式

    通过以下命令运行打包后的Fat Jar:

    java -jar myapp.jar

    也可以指定配置文件或JVM参数:

    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>
            <!-- 包含系统范围依赖 -->
            <includeSystemScope>true</includeSystemScope>
            <!-- 排除开发工具 -->
            <excludeDevtools>true</excludeDevtools>
            <!-- 创建分层jar -->
            <layers>
                <enabled>true</enabled>
            </layers>
        </configuration>
    </plugin>

    Gradle

    bootJar {
    &nbsp; &nbsp; archiveBaseName = 'myapp'
    &nbsp; &nbsp; archiveVersion = '1.0.0'
    &nbsp; &nbsp; mainClass = 'com.example.myapp.Application'
    &nbsp; &nbsp;&nbsp;
    &nbsp; &nbsp; // 排除特定依赖
    &nbsp; &nbsp; excludeDevtools = true
    &nbsp; &nbsp;&nbsp;
    &nbsp; &nbsp; // 启用分层支持
    &nbsp; &nbsp; layered {
    &nbsp; &nbsp; &nbsp; &nbsp; enabled = true
    &nbsp; &nbsp; }
    }

    1.6 优缺点分析

    优点:

    • 官方支持,与Spring Boot完全兼容
    • 采用嵌套jar结构,避免了依赖冲突
    • 支持直接运行
    • 提供丰富的配置选项

    缺点:

    • 启动时间可能略长,因为需要解析嵌套jar
    • 特殊的jar结构不符合标准jar规范
    • 某些工具可能无法正确处理嵌套jar结构
    • 排查类加载问题相对复杂

    1.7 适用场景

    • 标准Spring Boot应用部署
    • 容器化部署(docker)
    • 云平台部署
    • 需要完整Spring Boot功能的场景

    二、Maven Shade插件打包方式

    2.1 基本原理

    Maven Shade插件是一个通用的打包工具,不仅限于Spring Boot应用。

    它通过将所有依赖解压并重新打包到一个jar文件中,创建一个包含所有类文件的单一jar包。

    与Spring Boot插件不同,Shade创建的jar包没有嵌套结构,所有类都位于同一个类路径下。

    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&g编程客栈t;
                            <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>
                                <!-- 设置主类 -->
                                <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>
                            <!-- 创建可执行jar -->
                            <createDependencyReducedPom>false</createDependencyReducedPom>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    执行打包命令:

    mvn clean package

    2.3 打包结构分析

    Shade插件创建的Fat Jar具有以下结构:

    myapp.jar

    ├── META-INF

    │   ├── MANIFEST.MF

    │   ├── spring.factories

    │   ├── spring.handlers

    │   ├── spring.schemas

    │   └── maven

    │       └── ...

    ├── com

    │   └── example

    │       └── myapp

    │           └── ...

    ├── org

    │   └── springframework

    │       └── ...

    └── ...

    主要特点:

    • 所有依赖的类文件都被解压并重新打包到同一个jar中
    • 没有嵌套jar结构,所有类都在同一个类路径下
    • 需要特殊处理合并META-INF下的特殊文件

    2.4 运行方式

    与Spring Boot插件创建的jar包相同,可以通过以下命令运行:

    java -jar myapp.jar

    2.5 高级配置

    处理类冲突

    当多个依赖包含相同的类时,可以使用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 优缺点分析

    优点:

    • 创建标准jar结构,兼容性好
    • 支持类重定位,解决依赖冲突
    • 可以最小化最终jar大小
    • 可以处理非Spring Boot应用

    缺点:

    • 需要手动处理META-INF资源文件合并
    • 可能存在类路径冲突问题
    • 配置相对复杂
    • 对于大型应用,打包过程可能较慢

    2.7 适用场景

    • 需要标准jar结构的场景
    • 非Spring Boot应用
    • 有特殊类路径需求的项目
    • 需要最小化最终jar大小的场景
    • 需要处理复杂依赖冲突的项目

    三、Maven Assembly插件打包方式

    3.1 基本原理

    Maven Assembly插件是一个灵活的打包工具,可以创建自定义格式的分发包,包括jar、zip、tar等。

    对于Spring Boot应用,它可以创建包含所有依赖的可执行jar,类似于Shade插件,但配置方式和功能有所不同。

    A编程客栈ssembly插件更注重于创建完整的分发包,可以包含配置文件、启动脚本等。

    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>

    执行打包命令:

    mvn clean package

    3.3 自定义Assembly描述符

    对于更复杂的打包需求,可以创建自定义的Assembly描述符文件:

    创建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>
            <!-- 应用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>
            <!-- 启动脚本 -->
            <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 创建可执行jar

    如果需要创建可执行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 打包结构分析

    使用默认jar-with-dependencies描述符创建的Fat Jar结构:

    myapp-jar-with-dependencies.jar

    ├── META-INF

    │   ├── MphpANIFEST.MF

    │   └── maven

    │       └── ...

    ├── com

    │   └── example

    │       └── myapp

    │           └── ...

    ├── org

    │   └── springframework

    │       └── ...

    └── ...

    使用自定义描述符创建的分发包结构:

    myapp-distribution.zip

    ├── bin

    │   ├── start.sh

    │ &编程客栈nbsp; └── start.bat

    ├── config

    │   ├── application.yml

    │   └── logback.xml

    └── lib

        ├── myapp.jar

        ├── dependency1.jar

        ├── dependency2.jar

        └── ...

    3.6 运行方式

    对于使用jar-with-dependencies创建的可执行jar:

    java -jar myapp-jar-with-dependencies.jar

    对于自定义分发包,使用提供的启动脚本:

    cd myapp-distribution
    ./bin/start.sh

    或手动启动:

    cd myapp-distribution
    java -cp "lib/*" com.example.myapp.Application

    3.7 优缺点分析

    优点:

    • 高度灵活,支持自定义分发包格式
    • 可以包含配置文件、启动脚本等
    • 支持多种打包格式(jar, zip, tar等)
    • 可以为不同环境创建不同的分发包
    • 适合创建完整的应用分发包

    缺点:

    • 配置相对复杂
    • 对于简单应用,配置过于繁琐
    • 需要额外处理类路径和资源文件

    3.8 适用场景

    • 需要完整分发包的企业应用
    • 包含多个模块的复杂应用
    • 需要包含配置文件和启动脚本的场景
    • 需要为不同环境创建不同分发包的场景
    • 有特殊分发需求的项目

    四、总结

    合理的打包策略能显著提升开发和部署效率,是应用成功运行的重要环节。

    通过选择合适的打包方式,可以减少环境差异带来的问题,提升应用的可移植性和可维护性。

    到此这篇关于SpringBoot中Fat Jar的三种打包方式详解的文章就介绍到这了,更多相关SpringBoot打包Fat Jar内容请搜编程客栈索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜