从零搭建开发脚手架 Spring Boot应用瘦身打包便于部署

背景
Spring Boot 默认打的应用瘦于部Jar,包含应用程序代码及其所有依赖项(内置tomcat jar就不小了),身打署所以打包出来的包便jar文件很大,动不动就几十,从零上百M,搭建称之为Fat jar。脚手架
在网速不给力的应用瘦于部情况下,上传服务器非常耗时。身打署然而,包便其中我们引用到的从零Tomcat、Spring以及其他第三方组件,搭建它们大部分时间是脚手架不会修改的而且占用了很大的空间,每次打包打进去。其实,我们经常改动的内容都是我们自己编写的代码,其大小大概也就几十KB,每次升级我们只需替换这些文件即可。
Spring社区大概也考虑到了开发者有这样的需求,所以提供了spring-boot-thin-launcher这个插件用来将项目的依赖和配置从jar包中分离出去。服务器托管
使用
官网地址:https://github.com/spring-projects-experimental/spring-boot-thin-launcher
在Spring Boot pom文件中新增插件如下:
<project ...> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot.experimental</groupId> <artifactId>spring-boot-thin-layout</artifactId> <version>1.0.27.RELEASE</version> </dependency> </dependencies> </plugin> </plugins> </build> </project>然后还像以前一样执行mvn clean package,这时生成的jar包仅几十KB。
我这里因为项目有很多静态文件所以比较大有2MB。
执行java -jar xxx.jar即可直接运行程序。
除了jar文件减小了,其他效果看着与Fat jar是一样。
尝鲜之后,来看下其内部原理吧。
工作原理
我们来看下Jar包内部的构成。
Manifest-Version: 1.0 Implementation-Title: map Implementation-Version: 0.0.1-SNAPSHOT Start-Class: com.laker.map.LakerMapApplication Spring-Boot-Classes: Build-Jdk-Spec: 1.8 Spring-Boot-Version: 2.3.7.RELEASE Created-By: Maven Jar Plugin 3.2.0 Main-Class: org.springframework.boot.loader.wrapper.ThinJarWrapper即启动类实际为:ThinJarWrapper
ThinJarWrapper类
我们编写的代码
项目的Pom文件
当执行java -jar xxx.jar时,实际执行的是ThinJarWrapper,它会先在指定目录搜索看看依赖的jar包是否都存在,存在则直接使用,如果不存在,先从Maven中央仓库下载到本地,然后,再执行我们自己编写的main()入口方法。这种方式有点类似很多在线安装程序:用户下载后得到的是一个很小的exe安装程序,执行安装程序时,会首先在线下载所需的源码库若干巨大的文件,再进行真正的安装。
这个spring-boot-thin-launcher在启动时搜索的默认目录是用户主目录的.m2,我们也可以指定下载目录,例如,将下载目录指定为当前目录:
java -Dthin.root=. -jar xxx.jar执行后发现当前目录下自动生成了一个repository目录,这和Maven的默认下载目录~/.m2/repository的结构是完全一样的,只是它仅包含xxx.jar所需的运行期依赖项。
repository/ com/ net/ org/ ...“注意:只有首次运行时会自动下载依赖项,再次运行时由于无需下载,所以启动速度会大大加快。如果删除了repository目录,再次运行时就会再次触发下载。
额外补充
运行应用程序进行预热
缓存依赖项的最简单方法是在目标环境中对应用程序进行预热运行。正如我们之前看到的,这将导致依赖项被下载并缓存在本地 Maven 存储库中。如果我们运行多个应用程序,存储库最终将包含所有依赖项而没有重复项。
由于运行应用程序可能会产生不必要的云服务器提供商副作用,我们还可以执行“试运行”,只解析和下载依赖项,而无需运行任何用户代码:
java -Dthin.dryrun=true -Dthin.root=. -jar xxx.jar使用Maven在编译期打包依赖项
添加以下依赖
<plugin> <groupId>org.springframework.boot.experimental</groupId> <artifactId>spring-boot-thin-maven-plugin</artifactId> <version>${ thin.version}</version> <executions> <execution> <!-- Download the dependencies at build time --> <id>resolve</id> <goals> <goal>resolve</goal> </goals> <inherited>false</inherited> </execution> </executions> </plugin>构建项目后,目录为target/thin/root/。
生产环境
生产环境中,大部分都是内外网隔离的,建议先在本地“试运行”,然后把repository目录,瘦jar一起复制到服务器,设置thin.root指定目录,设置thin.offline切换到“离线”模式。所有依赖项都必须在本地可用.
java -Dthin.root=. -Dthin.offline=true -jar xxx.jar参考:
https://www.liaoxuefeng.com/wiki/1252599548343744/1304267002478625