SpringBoot 瘦身
1.介绍
本教程中,我们将研究如何使用 spring-boot-thin-launcher 项目来将 Spring Boot 项目瘦身。
Spring Boot 出了名的把所有依赖打包成单个可执行的 Fat JAR,同时也被广泛应用于微服务。有时候和 Fat JAR 不一致的是,反复包括相同的依赖会成为一种资源浪费。
2.先决条件
首先,我们当然需要一个 Spring Boot 项目。在本文中,我们将研究 Maven 构建和 Gradle 构建的最常见配置。
这里是不可能覆盖所有构建系统和相应的配置,但是希望我们能够有常用的构建系统配置以便参考。
2.1 Maven 项目
用 Maven 构建一个 Spring Boot 项目,我们首先要在 pom.xml 或者它的 parent 等任何一个祖先添加 Spring Boot 的 Maven 插件:
在这里,我们指的是插件的版本2.3.0.RELEASE
,这是编写本文时的最新版本。Spring Boot 所用的依赖版本通常是用 BOM 或者从父的 POM 继承的了:<br />
2.2 Gradle 项目
用 Gradle 构建 Spring Boot 项目,我们会有相应的 Gradle 插件
请注意,本文只考虑 Spring Boot 2.x 或者更高的版本,Thin Launcher 也支持旧的版本,但是可能有稍微不同的版本,具体请查看项目的主页。
3.怎么创建一个 Thin Jar
Spring Boot Thin Launcher 是一个比较小的类库,它从打包的文件中读取项目工程的依赖关系,然后从 maven 仓库下载这些依赖,最后启动应用程序。所以在第一次启动下载相应依赖的时候会消耗一定的时间。
所以,当我们用库构建一个项目时,我们会得到一个包含代码的 JAR 文件,一个包含依赖关系的文件,以及执行入口的主类。
当然,事情会比我们简单的解析微妙得多,本文下面会继续探讨。
4.基本用法
现在让我们看下如何构建一个 thin jar 的 Spring Boot 项目。
我们将使用通常的 java -jar 启动应用程序,并使用可选的附加命令行参数来控制 Thin Launcher。
我们将在以下部分中看到其中使用参数的几个例子; 该项目的主页包含完整参数列表。
4.1 Maven 项目
在 Maven 项目中,我们必须修改 SpringBoot 的插件,添加相应的依赖:
Thin Launcher 将会从 Maven 存储在 JAR 下的 META-INF/maven 目录中生成的 pom.xml 文件读取依赖关系。
我们像往常一样执行构建就行,例如使用 mvn install
如果我们需要同时打包 fat jar 和*thin jar*,我们可以在 maven 的 profile 中定义 springboot 插件。
4.2 Maven 依赖:thin.properties
除了 pom.xml 之外,我们也可以让 maven 生产 thin.properties。在这种情况下,该文件会包含完整的依赖列表,包括可传递的依赖列表,但是相对 pom.xml 来说,thin Launcher 对 thin.properties 更加友好。
默认情况下,插件在 src/main/resources/META-INF 中输出 thin.properties,但是我们可以用 thin.output 属性来指定它的位置:
4.3 Gradle 项目
不同的是,在 Gradle 项目中,我们需要添加了一个专用的插件:
为了获取 thin jar, 我们需要执行 thinJar 任务:
4.4 Graldle 依赖:pom.xml
在前一小节的代码示例中,除了 Thin Launcher 之外,我们还声明了 Maven 插件(我们已经事先看到 Spring Boot 的依赖管理插件)
这是因为和我们之前的 Maven 案例一样,打包后的文件包含了一个 pom.xml 来列举应用程序所需要的依赖关系。pom.xml 文件是由 thinPom 任务生成。 我们可以用专门的一个任务来定制生成 pom.xml, 在这里,我们复制下插件已经做的东西:
为了使用我们的自定义 pom.xml 文件,我们将上述任务添加到 jar 任务的依赖项中:
4.5 Gralde 依赖:thin.properties
和前面的 maven 项目一样,我们也可以让 Gradle 生成 thin.properties 而不是 pom.xml, 生成 thin.properties 文件的任务叫做 thinProperties,默认情况下是不使用它的。我们也可以把它添加到任务的依赖中:
5.保存依赖
thin jar 的目的是为了避免依赖项和应用程序绑在一起,然后依赖是不会消失的,这些依赖只是存储在其他地方而已。
特别地,Thin Launcher 是使用 maven 的基础架构来解决依赖的,所以:
会检查本地的 Maven 仓库,默认是指
~/.m2/repository
,当然也可以移到其他地方。会从 maven 中央仓库中下载缺失的依赖
最后会缓存所下载的依赖到本地 maven 仓库中,下次启动的时候就不会再继续下载了。
当然,下载依赖阶段是比较缓慢而且容易出错的部分,主要是因为是通过网络访问 maven 中央仓库来下载依赖,总之这些是不可靠的。
幸运的是,有很多种方式将依赖和应用程序一起部署,例如可以预打包在容器中。
5.1 运行预热的程序
缓存依赖的最简单方法就是在目标环境中对程序进行预热运行。正如前面所说的,预热运行会把所依赖的文件缓存到本地的 maven 仓库中去。如果我们运行了多个应用程序,maven 仓库中已经饱和了所依赖的库的话,就没有必要重复下载了。
由于运行应用程序可能会导致不必要的副作用,我们还可以执行“试运行”,它只解析和下载依赖项,而不运行任何用户代码:
5.2 在构建的时候打包依赖
另外一个选择就是在构建的时候打包依赖,当然,这不是把依赖打包到 JAR 中,然后我们可以复制这些依赖到目标的环境中。
通常这会更加简单,因为没必要在目标环境中运行应用程序。但是,如果我们部署多个环境,就必须手动或用脚本合并他们的依赖关系。
在构建过程中,Maven 和 Gradle 的 Thin 插件打包的依赖格式与 maven 的本地仓库是一样的:
实际上,我们还可以在运行的时候使用 thin.root 参数来指定依赖的目录:
5.3 用 maven 打包依赖
为了能让 maven 帮我们打包依赖,我们需要添加 spring-boot-thin-maven
插件
构建项目后,我们将找到一个目录target/thin/root/
会出现上一节讨论的结构。
5.4 用 Gradle 打包依赖
如我们用 thin-launcher 插件,我们会有 thinResolve 任务可以用。这个任务会保存应用和它的依赖在 build/thin/root/ 目录中,跟 maven 的一样:
6.总结和进一步阅读
在这篇文章中,我们学习了如何制作 Spring Boot 的 thin jar,同时也看到了如何使用 maven 的架构来下载和存储应用的依赖关系。
在项目主页 也有一些其他的使用指导,好比如一些命令参数等。
版权声明: 本文为 InfoQ 作者【JFound】的原创文章。
原文链接:【http://xie.infoq.cn/article/f57d6af28c40e96f8ed407038】。文章转载请联系作者。
评论