注册

如何优雅的给SpringBoot部署的jar包瘦身?

一、需求背景


我们知道Spring Boot项目,是可以通过java -jar 包名 启动的。


那为什么Spring Boot项目可以通过上述命令启动,而其它普通的项目却不可以呢?


原因在于我们在通过以下命令打包时


mvn clean package

一般的maven项目的打包命令,不会把依赖的jar包也打包进去的,所以这样打出的包一般都很小



但Spring Boot项目的pom.xml文件中一般都会带有spring-boot-maven-plugin插件。


该插件的作用就是会将依赖的jar包全部打包进去。该文件包含了所有的依赖和资源文件。


也就会导致打出来的包比较大。



打完包就可以通过java -jar 包名 启动,确实是方便了。


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


我们可以想象一种场景,线上有一个紧急致命Bug,你也很快定位到了问题,就改一行代码的事情,当提交代码并完成构建打包并交付给运维。


因为打包的jar很大,一直处于上传中.......


如果你是老板肯定会发火,就改了一行代码却上传几百MB的文件,难道没有办法优化一下吗?


如今迭代发布是常有的事情,每次都上传一个如此庞大的文件,会浪费很多时间。


下面就以一个小项目为例,来演示如何瘦身。


二、瘦身原理


这里有一个最基础 SpringBoot 项目,整个项目代码就一个SpringBoot启动类,单是打包出来的jar就有20多M;


我们通过解压命令,看下jar的组成部分。


tar -zxvf spring-boot-maven-slim-1.0.0.jar


我们可以看出,解压出来的包有三个模块


分为 BOOT-INF,META-INF,org 三个部分


打开 BOOT-INF



classes: 当前项目编译好的代码是放在 classes 里面的,classes 部分是非常小的。


lib: 我们所依赖的 jar 包都是放在 lib 文件夹下,lib部分会很大。


看了这个结构我们该如何去瘦身呢?


项目虽然依赖会很多,但是当版本迭代稳定之后,依赖基本就不会再变动了。


如果可以把这些不变的依赖提前都放到服务器上,打包的时候忽略这些依赖,那么打出来的Jar包就会小很多,直接提升发版效率。


当然这样做你肯定有疑问?


既然打包的时候忽略这些依赖,那通过java -jar 包名 还可以启动吗?


这种方式打的包,在项目启动时,需要通过-Dloader.path指定lib的路径,就可以正常启动


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

三、瘦身实例演示


1、依赖拆分配置


只需要在项目pom.xml文件中添加下面的配置:


 <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<layout>ZIP</layout>
<!--这里是填写需要包含进去的jar,
必须项目中的某些模块,会经常变动,那么就应该将其坐标写进来
如果没有则nothing ,表示不打包依赖 -->

<includes>
<include>
<groupId>nothing</groupId>
<artifactId>nothing</artifactId>
</include>
</includes>
</configuration>
</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>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

再次打包


mvn clean package


发现target目录中多了个lib文件夹,里面保存了所有的依赖jar。



自己业务相关的jar也只有小小的168kb,相比之前20.2M,足足小了100多倍;


这种方式打的包,在项目启动时,需要通过-Dloader.path指定lib的路径:


java -Dloader.path=./lib -jar spring-boot-maven-slim-1.0.0.jar


虽然这样打包,三方依赖的大小并没有任何的改变,但有个很大的不同就是我们自己的业务包和依赖包分开了;


在不改变依赖的情况下,也就只需要第一次上传lib目录到服务器,后续业务的调整、bug修复,在没调整依赖的情况下,就只需要上传更新小小的业务包即可;


2、自己其它项目的依赖如何处理?


我们在做项目开发时,除了会引用第三方依赖,也会依赖自己公司的其它模块。


比如



这种依赖自己其它项目的工程,也是会经常变动的,所以不宜打到外部的lib,不然就会需要经常上传更新。


那怎么做了?


其实也很简单 只需在上面的插件把你需要打进jar的填写进去就可以了


<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<layout>ZIP</layout>
<!--这里是填写需要包含进去的jar,如果没有则nothing -->
<includes>
<include>
<groupId>com.jincou</groupId>
<artifactId>xiaoxiao-util</artifactId>
</include>
</includes>
</configuration>
</plugin>

这样只有include中所有添加依赖依然会打进当前业务包中。


四、总结


使用瘦身部署,你的业务包确实小了 方便每次的迭代更新,不用每次都上传一个很大的 jar 包,从而节省部署时间。


但这种方式也有一个弊端就是增加了Jar包的管理成本,多人协调开发,构建的时候,还需要专门去关注是否有人更新依赖。


作者:二进制狂人
来源:juejin.cn/post/7260772691501301817

0 个评论

要回复文章请先登录注册