SpringBoot:通过SpringBoot生成可运行jar包与可依赖jar包
1. 产生的问题
Spring Boot 项目打包成的可运行 jar包 ,被其他项目依赖之后,总是报错找不到类的错误?
这是由于还没有搞清楚可执行 jar 和普通 jar 到底有什么区别导致的。
2. 可运行jar与普通jar的区别
- 普通jar包:可以被其他项目应用依赖,不可以用 java -jar xxx.jar 运行。
- 可运行jar包:不可以被其他项目应用依赖,可以用 java -jar xxx.jar 运行。
注:SpringBoot项目默认打包的是可运行jar包,普通项目默认打包的是不可运行的jar包,但是,普通项目也可以打包成可运行jar包。
疑问:
同样是执行mvn package
命令进行项目打包,为什么 Spring Boot 项目就打成了可执行 jar ,而普通项目则打包成了不可执行 jar 呢?
解答:
Spring Boot 项目默认的插件配置 spring-boot-maven-plugin 依赖包,这个打包插件存在 5 个方面的功能,如下:
五个功能分别是:
(1)build-info
:生成项目的构建信息文件 build-info.properties
(2)repackage
:这个是默认 goal,在 mvn package
执行之后,这个命令再次打包生成可执行的 jar,同时将 mvn package
生成的 jar 重命名为 *.origin
(3)run:这个可以用来运行 Spring Boot 应用
(4)start:这个在 mvn integration-test
阶段,进行 Spring Boot 应用生命周期的管理
(5)stop:这个在 mvn integration-test
阶段,进行 Spring Boot 应用生命周期的管理
默认情况下使用就是 repackage 功能,其他功能要使用,则需要开发者显式配置。
3. 了解打包过程
SpringBoot的repackage 功能的 作用,就是在打包的时候,多做一点额外的事情:
(1)首先 mvn package 命令 对项目进行打包,打成一个 jar,这个 jar 就是一个普通的 jar,可以被其他项目依赖,但是不可以被执行
(2)repackage 命令,对第一步 打包成的 jar 进行再次打包,将之打成一个 可执行 jar ,通过将第一步打成的 jar 重命名为 *.original 文件
举例说明:
Spring Boot 项目进行打包,可以执行 mvn package
命令,也可以直接在 IDEA 中点击 package进行打包,打包结果如下显示:
可以看到有两个文件,admin-0.0.1-SNAPSHOT.jar 是可运行jar包,admin-0.0.1-SNAPSHOT.jar.original是被重命名的 可依赖jar包。
4. jar包之间的差异
可执行 jar 包结构:
可执行 jar 中,我们自己的代码是存在 于 BOOT-INF/classes/
目录下,另外,还有一个 META-INF
的目录,该目录下有一个 MANIFEST.MF
文件,打开该文件,内容如下:
Manifest-Version: 1.0 Created-By: Maven Jar Plugin 3.2.0 Build-Jdk-Spec: 14 Implementation-Title: admin Implementation-Version: 0.0.1-SNAPSHOT Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: org.yolo.admin.AdminApplication Spring-Boot-Version: 2.3.4.RELEASE Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Start-Class :
这就是可执行 jar 的入口类
Spring-Boot-Classes
: 代码编译后的位置
Spring-Boot-Lib
: 项目所依赖的 jar 的位置
如果自己要打一个可执行 jar 包的话,除了添加相关依赖之外,还需要配置 META-INF/MANIFEST.MF
文件。
不可执行 jar 包的结构:
首先将默认的后缀 .original
除去,然后给文件重命名 .jar,重命名完成,进行解压 如下:
不可执行 jar 根目录就相当于我们的 classpath,直接就能看到我们的代码,并且也拥有
META-INF/MANIFEST.MF
文件,但是文件中没有定义启动类等配置。
Manifest-Version: 1.0 Created-By: Maven Jar Plugin 3.2.0 Build-Jdk-Spec: 14 Implementation-Title: admin Implementation-Version: 0.0.1-SNAPSHOT
注:这个不可以执行 jar 也没有将项目的依赖打包进来。
由此可见这两个jar包内部结构是完全不同的,因此一个可以直接执行,另一个则可以被其他项目依赖。
5. 同时打包两个jar包
提议:一般来说,Spring Boot 直接打包成可执行 jar 就可以了,不建议将 Spring Boot 作为普通的 jar 被其他的项目所依赖。如果有这种需求,建议将被依赖的部分,单独抽出来做一个普通的 Maven 项目,然后在 Spring Boot 中引用这个 Maven 项目。
依环境必须实现可依赖jar的话,如下可以实现:
pom.xml文件中spring-boot-maven-plugin
插件添加如下配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
classifier
: 表示可执行 jar 的名字 , 执行 repackage
命令时,就不会给 mvn package
所打成的 jar 重命名 , 如下:
第一个 jar 表示可以被其他项目依赖的 jar ,第二个 jar 则表示一个可执行 jar。