SpringBoot 工程部署的 jar 包瘦身
SpringBoot 工程部署的 jar 包瘦身
参考
1、需求背景
我们知道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的文件,难道没有办法优化一下吗?
如今迭代发布时常有的事情,每次都上传一个如此庞大的文件,会浪费很多时间。故而需要jar包瘦身。
2、瘦身原理
我们通过解压命令,看下jar的组成部分。

tar -zxvf spd-1.0.0.jar
我们可以看出,解压出来的包有三个模块
分为三个部分
BOOT-INF
,META-INF
,org
打开 BOOT-INF
classes
: 当前项目编译好的代码是放在 classes 里面的,classes 部分是非常小的。lib
: 我们所依赖的 jar 包都是放在 lib 文件夹下,lib部分会很大。

看了这个结构我们该如何去瘦身呢?项目虽然依赖会很多,但是当版本迭代稳定之后,依赖基本就不会再变动了。如果可以把这些不变的依赖提前都放到服务器上,打包的时候忽略这些依赖,那么打出来的Jar包就会小很多,直接提升发版效率。当然这样做你肯定有疑问?
既然打包的时候忽略这些依赖,那通过java -jar 包名
还可以启动吗?这种方式打的包,在项目启动时,需要通过-Dloader.path
指定lib
的路径,就可以正常启动
Linux环境
java -Dloader.path=./lib -jar xxx.jar
Windows环境
java -Dloader.path=.\spd-lib -Dfile.encoding=utf-8 -Xmx768m -Xms256m -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=80 -jar
%JAR_NAME%.jar --server.port=9528
3、瘦身实例演示
3.1、依赖拆分配置
只需要在项目pom.xml文件中添加下面的配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--<includeSystemScope>false</includeSystemScope>-->
<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
这种方式打的包,在项目启动时,需要通过-Dloader.path
指定lib的路径:
java -Dloader.path=.\jin-lib -Dfile.encoding=utf-8 -Xmx768m -Xms256m -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=80 -jar
%JAR_NAME%.jar --server.port=9528
虽然这样打包,三方依赖的大小并没有任何的改变,但有个很大的不同就是我们自己的业务包
和依赖包
分开了;
在不改变依赖的情况下,也就只需要第一次上传lib目录到服务器
,后续业务的调整、bug修复,在没调整依赖的情况下,就只需要上传更新小小的业务包即可;
4、依赖自己公司的其它模块如何处理?
我们在做项目开发时,除了会引用第三方依赖,也会依赖自己公司的其它模块。这种依赖自己其它项目的工程,也是会经常变动的,所以不宜打到外部的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.jin</groupId>
<artifactId>jin-util</artifactId>
</include>
</includes>
</configuration>
</plugin>
这样只有include
中所有添加依赖依然会打进当前业务包中。