java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot打包Fat Jar

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

作者:风象南

Spring Boot开发中,打包是将应用及其所有依赖整合到一个可执行文件中的过程,这种包含所有依赖的jar文件通常被称为"Fat Jar",下面我们来看看SpringBoot打包Fat Jar的三种方式吧

在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
                └── ...

主要组成部分:

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 优缺点分析

优点:

缺点:

1.7 适用场景

二、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>
                        <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
│       └── ...
└── ...

主要特点:

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 优缺点分析

优点:

缺点:

2.7 适用场景

三、Maven Assembly插件打包方式

3.1 基本原理

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

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

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

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
│   ├── MANIFEST.MF
│   └── maven
│       └── ...
├── com
│   └── example
│       └── myapp
│           └── ...
├── org
│   └── springframework
│       └── ...
└── ...

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

myapp-distribution.zip
├── bin
│   ├── start.sh
│   └── 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 优缺点分析

优点:

缺点:

3.8 适用场景

四、总结

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

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

到此这篇关于SpringBoot中Fat Jar的三种打包方式详解的文章就介绍到这了,更多相关SpringBoot打包Fat Jar内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文