SpringBoot打包的jar包与普通的jar包有什么区别 - Sanarous的博客

SpringBoot打包的jar包与普通的jar包有什么区别

有些人可能会将 SpringBoot 打包成的 jar 包作为项目依赖导入到其它项目中,结果启动就会发现会报找不到类的错误。会有这种操作的误区,是因为混淆了 SpringBoot 打包成的 jar 包与普通的 jar 包。

SpringBoot 中打包的插件

我们常把 SpringBoot 打包成的 jar 包称为可执行 jar 包,而普通 jar 包往往作为依赖使用,这并不是说普通 jar 包不能执行,如果普通 jar 包中确定了 Main 入口主类,也是可以直接通过 java -jar xxx.jar方式运行的。它们之间的主要区别在于 SpringBoot 中有一个默认打包插件 Spring-boot-maven-plugin,这个插件有 5 个方面的功能,从插件配置就可以看出来:

五个功能分别是:

  • build-info:生成项目的构建信息文件 build-info.properties
  • repackage:这个是默认 goal,在 mvnpackage 执行之后,这个命令再次打包生成可执行的 jar,同时将 mvnpackage 生成的 jar 重命名为 *.origin
  • run:这个可以用来运行 Spring Boot 应用
  • start:这个在 mvn integration-test 阶段,进行 SpringBoot 应用生命周期的管理
  • stop:这个在 mvn integration-test 阶段,进行 SpringBoot 应用生命周期的管理

默认情况下使用就是 repackage 功能,其他功能要使用,则需要开发者显式配置。

repackage

repackage 功能的 作用,就是在打包的时候,多做一点额外的事情:

  1. 首先使用命令 mvnpackage 对项目打包时,打包成的 jar 就是一个普通的 jar 包,可以被其它项目依赖
  2. repackage 打包命令就是对上面打成的 jar 包再次打包,将之打成 SpringBoot 可执行的 jar 包,通过将第一步打成的 jar 重命名为 *.original 文件

举个例子,我们对任意一个 SpringBoot 项目进行打包,可以执行 mvnpackage 命令,也可以直接在 IDEA 中点击 package,如下所示:

打包成功后,target 中的文件如下:

其中有两个 jar 包,一个叫做 tumo-0.01-SNAPHOT.jar 这是最终被打包成的可执行 jar 包,第二个就是 tumo-0.01-SNAPHOT.jar.original 则是在打包过程中,被重命名的 jar,通过对这两个文件的解压,我们可以看出这两者之间的差异。

两个 jar 的比较

最终的可执行 jar 解压之后,目录如下:

可以看到,可执行 jar 中,我们自己的代码是存在 于 BOOT-INF/classes/ 目录下,另外,还有一个 META-INF 的目录,该目录下有一个 MANIFEST.MF 文件,打开该文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Manifest-Version: 1.0
Implementation-Title: tumo
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: zuoxiang
Implementation-Vendor-Id: cn.bestzuo
Spring-Boot-Version: 2.1.3.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: cn.bestzuo.TumoBlogApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.6.0
Build-Jdk: 1.8.0_211
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
ot-starter-parent/tumo

可以看到,这里定义了一个 Start-Class,这就是可执行 jar 的入口类, Spring-Boot-Classes 表示我们自己代码编译后的位置, Spring-Boot-Lib 则表示项目依赖的 jar 的位置。

换句话说,如果自己要打一个可执行 jar 包的话,除了添加相关依赖之外,还需要配置 META-INF/MANIFEST.MF 文件。

那么原始的普通 jar 包呢?我们解压一下看一下:

解压后可以看到,根目录就相当于我们的 classpath,解压之后,直接就能看到我们的代码,它也有 META-INF/MANIFEST.MF 文件,但是文件中没有定义启动类等。

1
2
3
4
5
6
7
8
9
Manifest-Version: 1.0
Implementation-Title: tumo
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: zuoxiang
Implementation-Vendor-Id: cn.bestzuo
Created-By: Apache Maven 3.6.0
Build-Jdk: 1.8.0_211
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
ot-starter-parent/tumo

这个 jar 也没有将项目的依赖打包进来。

从这里我们就可以看出,两个 jar ,虽然都是 jar 包,但是内部结构是完全不同的,因此一个可以直接执行,另一个则可以被其他项目依赖。

如果这篇文章对您很有帮助,不妨
-------------    本文结束  感谢您的阅读    -------------
0%