跳至主要內容

spring boot 工程 jar 包瘦身

Yaien Blog原创大约 4 分钟SpringBoot插件

spring boot 工程 jar 包瘦身

Spring Boot项目的pom.xml文件中一般都会带有spring-boot-maven-plugin插件,该插件的作用就是会将依赖的jar包全部打包进去。
但是该文件包含了所有的依赖和资源文件,会导致打出来的包会比较大。

而如果我们使用一般的打包命令时

mvn clean package

不会把依赖的jar包也打进去,这样打出来的包就会很小。

问题描述

但当一个系统上线运行后,肯定会有需求迭代和Bug修复,那也就免不了进行重新打包部署。

此时有一个场景:线上有一个紧急BUG,并且BUG很快被定位并且修复,其实就是一行代码的事情,现在代码修改好了并且完成了构建然后开始打包交付时发现,jar包很大,一直在上传。

而当经常需要迭代发布,每一次都上传一个庞大的jar包文件,会浪费很多时间。

此时就需要为jar包瘦瘦身,降低jar包文件的大小。

瘦身原理

一个spring boot正常的打包,包含所有依赖时打出的jar包有120多M:

解压查看内部有三个包,BOOT-INFMETA-INFOorg

打开BOOT-INF

  • classes: 存放当前项目编译好的代码,这部分是非常小的。
  • lib: 存放我们所依赖的 jar 包,lib部分会很大。

原理

当一个项目的依赖越多,lib包就会越大。虽然依赖多,但是当版本迭代稳定之后,依赖基本就不会再变动了。

我们就可以把这些不变的依赖提前都放到服务器上,打包的时候忽略这些依赖,只打本项目编译好的文件,这样打出来的jar包就会很小,提高发版效率。

配置实现


<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!-- 设置主函数 -->
                <mainClass>cn.yanggl.xxxMain</mainClass>
                <layout>ZIP</layout>
                <!--这里是填写需要包含进去的jar,
                     必须项目中的某些模块,会经常变动,那么就应该将其坐标写进来
                     如果没有则nothing ,表示不打包依赖 -->
                <includes>
                    <!-- 需要一起打包到项目jar包的依赖 -->
                    <include>
                        <groupId>nothing</groupId>
                        <artifactId>nothing</artifactId>
                    </include>
                </includes>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

        <!--拷贝依赖到jar外面的lib目录-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <!-- 指定依赖导出位置 -->
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                        <!--  不需要导出的依赖 -->
                        <excludeArtifactIds>
                            cn.yanggl
                        </excludeArtifactIds>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

调整了配置之后,再次打包我们会发现发现target目录中多了个lib文件夹,里面保存了所有的依赖jar。本项目的jar包只有几百K。

当include标签只填groupId标签时,表示groupId标识下的所有依赖都包含

问题

启动问题

Spring Boot默认打包方式,将所有依赖文件全部打入项目jar包,我们在启动项目时可以通过

java -jar xxx.jar

直接运行。

而当进行瘦身之后,因为我们已经将项目依赖到外部lib包,我们就不能再通过以上那种方式启动,而是要通过通过-Dloader.path指定lib的路径:

java -jar -Dloader.path="/lib" xxx.jar

依赖问题

如果你有一个项目A,它依赖于项目B,而项目B又依赖于项目C,那么项目A实际上也是依赖于项目C的。

这种情况下,如果使用了spring-boot-maven-plugin并配置了includes标签,实际上是在设置要包含哪些依赖,而不是要排除哪些依赖。
所以,当你把B模块添加到includes标签下时,实际上你只是包含了B模块本身,而不是它的所有依赖,例如C

当想要A也包含C的依赖,则需要显示的添加到includes标签下

lib包更新问题

现在项目A显示的引入了项目B,当项目C更新或者添加了新地依赖D的时候,项目A就需要重新构建以便获取最新版本的
B以及其依赖,并且将最新的lib包更新到A的服务器上。

上次编辑于:
贡献者: yanggl