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插件:

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

在这里,我们指的是插件的版本2.3.0.RELEASE,这是编写本文时的最新版本。Spring Boot所用的依赖版本通常是用BOM或者从父的POM继承的了:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/>
</parent>

2.2 Gradle 项目

用Gradle构建Spring Boot项目,我们会有相应的Gradle插件

buildscript {
ext {
springBootPlugin = 'org.springframework.boot:spring-boot-gradle-plugin'
springBootVersion = '2.3.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("${springBootPlugin}:${springBootVersion}")
}
}
// elided
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
springBoot {
mainClassName = 'DemoApplication'
}

请注意,本文只考虑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的插件,添加相应的依赖:

<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.23.RELEASE</version>
</dependency>
</dependencies>
</plugin>

Thin Launcher将会从Maven存储在JAR下的META-INF/maven目录中生成的pom.xml文件读取依赖关系。

我们像往常一样执行构建就行,例如使用 mvn install

如果我们需要同时打包fat jarthin 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属性来指定它的位置:

mvn org.springframework.boot.experimental:spring-boot-thin-maven-plugin:properties -Dthin.output=.

4.3 Gradle项目

不同的是,在Gradle项目中,我们需要添加了一个专用的插件:

buildscript {
ext {
//...
thinPlugin = 'org.springframework.boot.experimental:spring-boot-thin-gradle-plugin'
thinVersion = '1.0.23.RELEASE'
}
//...
dependencies {
//...
classpath("${thinPlugin}:${thinVersion}")
}
}
//elided
apply plugin: 'maven'
apply plugin: 'org.springframework.boot.experimental.thin-launcher'

为了获取thin jar, 我们需要执行 thinJar 任务:

./gradlew thinJar

4.4 Graldle依赖:pom.xml

在前一小节的代码示例中,除了Thin Launcher之外,我们还声明了Maven插件(我们已经事先看到Spring Boot的依赖管理插件)

这是因为和我们之前的Maven案例一样,打包后的文件包含了一个pom.xml来列举应用程序所需要的依赖关系。pom.xml文件是由thinPom任务生成。 我们可以用专门的一个任务来定制生成pom.xml, 在这里,我们复制下插件已经做的东西:

task createPom {
def basePath = 'build/resources/main/META-INF/maven'
doLast {
pom {
withXml(dependencyManagement.pomConfigurer)
}.writeTo("${basePath}/${project.group}/${project.name}/pom.xml")
}
}

为了使用我们的自定义pom.xml文件,我们将上述任务添加到jar任务的依赖项中:

bootJar.dependsOn = [createPom]

4.5 Gralde依赖:thin.properties

和前面的maven项目一样,我们也可以让Gradle生成thin.properties而不是pom.xml, 生成thin.properties文件的任务叫做thinProperties,默认情况下是不使用它的。我们也可以把它添加到任务的依赖中:

bootJar.dependsOn = [thinProperties]

5.保存依赖

thin jar的目的是为了避免依赖项和应用程序绑在一起,然后依赖是不会消失的,这些依赖只是存储在其他地方而已。

特别地,Thin Launcher是使用maven的基础架构来解决依赖的,所以:

  • 会检查本地的Maven仓库,默认是指 ~/.m2/repository,当然也可以移到其他地方。
  • 会从maven中央仓库中下载缺失的依赖
  • 最后会缓存所下载的依赖到本地maven仓库中,下次启动的时候就不会再继续下载了。

当然,下载依赖阶段是比较缓慢而且容易出错的部分,主要是因为是通过网络访问maven中央仓库来下载依赖,总之这些是不可靠的。

幸运的是,有很多种方式将依赖和应用程序一起部署,例如可以预打包在容器中。

5.1 运行预热的程序

缓存依赖的最简单方法就是在目标环境中对程序进行预热运行。正如前面所说的,预热运行会把所依赖的文件缓存到本地的maven仓库中去。如果我们运行了多个应用程序,maven仓库中已经饱和了所依赖的库的话,就没有必要重复下载了。

由于运行应用程序可能会导致不必要的副作用,我们还可以执行“试运行”,它只解析和下载依赖项,而不运行任何用户代码:

java -Dthin.dryrun=true -jar my-app-1.0.jar

5.2 在构建的时候打包依赖

另外一个选择就是在构建的时候打包依赖,当然,这不是把依赖打包到JAR中,然后我们可以复制这些依赖到目标的环境中。

通常这会更加简单,因为没必要在目标环境中运行应用程序。但是,如果我们部署多个环境,就必须手动或用脚本合并他们的依赖关系。

在构建过程中,Maven和Gradle的Thin 插件打包的依赖格式与maven的本地仓库是一样的:

root/
repository/
com/
net/
org/
...

实际上,我们还可以在运行的时候使用 thin.root参数来指定依赖的目录:

$ java -jar my-app-1.0.jar --thin.root=my-app/deps

5.3 用maven打包依赖

为了能让maven帮我们打包依赖,我们需要添加 spring-boot-thin-maven插件

<plugin>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-maven-plugin</artifactId>
<version>${thin.version}</version>
<executions>
<execution>
<id>resolve</id>
<goals>
<goal>resolve</goal>
</goals>
<inherited>false</inherited>
</execution>
</executions>
</plugin>

构建项目后,我们将找到一个目录target/thin/root/会出现上一节讨论的结构。

5.4 用Gradle打包依赖

如我们用_thin-launcher_插件,我们会有_thinResolve_任务可以用。这个任务会保存应用和它的依赖在_build/thin/root/_ 目录中,跟maven的一样:

gradlew thinResolve

6.总结和进一步阅读

在这篇文章中,我们学习了如何制作Spring Boot的thin jar,同时也看到了如何使用maven的架构来下载和存储应用的依赖关系。

项目主页 也有一些其他的使用指导,好比如一些命令参数等。

微信关注我,发现更多java领域知识

SpringBoot瘦身的更多相关文章

  1. SpringBoot瘦身部署(15.9 MB - 92.3 KB)

    1. 简介   SpringBoot项目部署虽然简单,但是经常因为修改了少量代码而需要重新打包上传服务器重新部署,而公网服务器的网速受限,可能整个项目的代码文件仅仅只有1-2MB甚至更少,但是需要上传 ...

  2. SpringBoot-Maven打包压缩瘦身

    SpringBoot-Maven打包压缩瘦身 一.Spring Boot 可执行 jar 分析 1.1 打包 1.2 两种 jar 的比较 1.3 一次打包两个 jar 二.SpringBoot迭代发 ...

  3. SpringBoot Jar包瘦身 - 跟大文件说再见!

    前言 SpringBoot部署起来配置非常少,如果服务器部署在公司内网,上传速度还行,但是如果部署在公网(阿里云等云服务器上),部署起来实在头疼.就是 编译出来的 Jar 包很大,如果工程引入了许多开 ...

  4. springboot 打包插件去除jar包瘦身

    1.pom文件配置 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>s ...

  5. springboot项目打包瘦身

    默认情况下,Spring Boot 项目发布时会将项目代码和项目的所有依赖文件一起打成一个可执行的 jar 包.但如果项目的依赖包很多,那么这个文件就会非常大.这样每次即使只改动一点东西,就需要将整个 ...

  6. maven war包打包去除jar包瘦身

    1.pom文件配置 <!-- war包 --> <plugin> <groupId>org.apache.maven.plugins</groupId> ...

  7. Spring Boot打包瘦身 Docker 使用全过程 动态配置、日志记录配置

    springBoot打包的时候代码和jar包打包在同一个jar包里面,会导致jar包非常庞大,在不能连接内网的时候调试代码,每次只改动了java代码就需要把所有的jar包一起上传,导致传输文件浪费了很 ...

  8. Spring Boot 项目瘦身指南,瘦到不可思议!129M->1.3M

    之前在 从使用传统Web框架到切换到Spring Boot后的总结 中提到关于 Spring Boot 编译打包,Spring Boot 应用程序不用额外部署到外部容器中,可以直接通过 Maven 命 ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. 【手把手教你】win10 虚拟机 VMware Workstation Pro 15下安装Ubuntu 19.04

    虚拟机 VMware Workstation Pro 15.5.0 及永久激活密钥 https://www.cnblogs.com/zero-vic/p/11584437.html Ubuntu19. ...

  2. SpringCloud入门(十一):Sleuth 与 Zipkin分布式链路跟踪

    现今业界分布式服务跟踪的理论基础主要来自于 Google 的一篇论文<Dapper, a Large-Scale Distributed Systems Tracing Infrastructu ...

  3. 短视频sdk:选择一个靠谱的短视频SDK 你需要了解这些

    2017 年,短视频成为了内容创业的新风口,各种短视频 App 如雨后春笋般先后上线.随着互联网内容消费升级,视频越来越像文字.图片一样,成为每一个 App 不可或缺的一部分. 为了能够更好地聚焦于业 ...

  4. Heartbeat+Haproxy实现负载均衡高可用

    环境说明: 主机名 角色 IP地址 mylinux1.contoso.com heartbeat+haproxy eth0:192.168.100.121 eth1:172.16.100.121 my ...

  5. centos6 yum安装jdk1.8+

    一.环境Linux操作系统: centos6.9 安装jdk版本: jdk1.8+ 二.安装步骤1. 检查系统是否自带有jdk[root@VM_0_11_centos ~]# rpm -qa |gre ...

  6. Binary Index Tree

    0 引言 Leetcode307 这道题给一个可变数组,求从\(i\)到\(j\)的元素之和. 一个naive的做法是,每次查询都从\(i\)累加到\(j\): class NumArray { pu ...

  7. Hardware Introduction

    计算机硬件组成可以概括为下图: CPU CPU生产商主要是Intel和AMD. Intel的产品主要有四种: Celeron(赛扬):低端处理器 Pentium(奔腾):比赛扬强,比酷睿弱 Xeon( ...

  8. 一只简单的网络爬虫(基于linux C/C++)————socket相关及HTTP

    socket相关 建立连接 网络通信中少不了socket,该爬虫没有使用现成的一些库,而是自己封装了socket的相关操作,因为爬虫属于客户端,建立套接字和发起连接都封装在build_connect中 ...

  9. python的unittest框架中的assert断言

    unittest框架自带断言,如果想用assert断言,一定要引入unittest.TestCase框架才行,不然不会自动识别assert断言

  10. Java——多线程之Lock锁

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...