springBoot 打包 fat、thin jar

一、什么是fat、thin jar

springBoot项目可以运行java -jar xxx.jar 来启动,默认情况下它会把所有的依赖都打到一个jar里面,称作fat jar。但是一般情况下很多外部依赖的jar大多数不可变,若是每次的jar都是很大,势必在网络不好的情况下上传到服务器很慢。基于此,我们可以利用maven的2个插件也可以打出thin jar。

备注:java -jar xx.jar 是java自带的命令,和sprignBoot没半毛钱关系,因此我们只需要按照这个jar文件的规范,也可以将任何项目打包成可执行的jar。

二、MANIFEST.MF 文件

每一个jar包下面都谁有它,可见其重要性,它列出了jar包一些信息/清单。

  • 正常的springBoot可执行jar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Manifest-Version: 1.0
Implementation-Title: af-app
Implementation-Version: 0.0.1-SNAPSHOT
// springBoot启动类
Start-Class: com.af.app.afapp.AfAppApplication
//类文件
Spring-Boot-Classes: BOOT-INF/classes/
//依赖路径
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.1.5.RELEASE
Created-By: Maven Archiver 3.4.0
//通过它来启动 Start-Class
Main-Class: org.springframework.boot.loader.JarLauncher
  • mvn-jar-plugin 插件打出来的可执行jar
1
2
3
4
5
6
7
8
9
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: yons
// 类path,依赖的所有jar
Class-Path: ../lib/data-asset-tag-api-1.0.0.jar ...
Created-By: Apache Maven 3.6.0
Build-Jdk: 1.8.0_201
// 启动类
Main-Class: com.dtwave.asset.tag.provider.DataAssetTagStarter

三、springBoot 可执行jar的maven插件

1
2
3
4
5
6
7
8
9
10
11
12
 <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- 可选-->
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

这里我们直接给出springboot提供好的插件,就可以打出可执行的jar。注意若我们的工程没有继承spring-boot-starter-parent(这里面有了repackage 这个阶段),则还需要在上述的插件里面加个repackage,它就是将jar包可执化的关键。

四、maven-jar-plugin+maven-dependency-plugin 插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<!--设置manifest.mf文件-->
<manifest>
<!-- 添加依赖jar路径 Class-Path -->
<addClasspath>true</addClasspath>
<!-- 设置入口程序 -->
<mainClass>com.af.app.afapp.AfAppApplication</mainClass>
<classpathPrefix>../libs</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<!--拷贝项目依赖-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!--自动在target目录下新建libs目录放依赖-->
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>

maven-jar-plugin 插件可以指定主程序入口,和可搜索的类路径。
dependency-plugin 主要用于依赖的copy,瘦身jar。

有兴趣的朋友可以研究下springBoot 启动的原理,它是怎么使用org.springframework.boot.loader.JarLauncher 来找到我们的启动类,完成程序的启动的。