场景回顾:
1、有A、B两个模块,其中A模块既作为可单独运行的模块,又在B模块中进行了引用
2、在开发环境下启动A、B两个模块服务都是正常的
3、ci/cd构建时报错,提示找不到正确的打包文件
4、开发环境进行打包也报错
问题分析:
1、开发环境下打包的时候,A打包成功,B打包失败
报错提示B中引用的A程序包不存在,但引入包、代码文件跳转都是正常的。
2、打包问题
打包的时候会生成两种包:可执行jar包和原始包(原始包包含了本包的所有类文件,但没有可执行入口,一般多指工具类的jar包)。
springboot默认打包成可执行jar包,使用的是spring-boot-maven-plugin插件,该jar包是不可以被其他jar包所依赖的。
或者可以理解成:程序会先生成原始包,然后生成执行包,覆盖掉原始包,而原始包是根据其他包读取的,所以会出现找不到包的情况
对应本案例中的情况就是:A、B两个模块打包的时候,A生成的原始包被A的可执行jar包覆盖,导致B可执行jar包需要用到的A原始包找不到。
解决方案:
1、在被调用的模块pom文件里面打包插件增加如下标签,在本案例中就是在A模块的pom文件里面增加该标签配置
<classifier>exec</classifier>
2、打包插件及标签配置完整代码
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 模块启动类路径 -->
<mainClass>com.xx.xxApplication</mainClass>
<includeSystemScope>true</includeSystemScope>
<!-- 可执行jar包添加后缀名,可自定义 -->
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
3、exec为最终的包名称尾部即会生成moduleA.jar和moduleA-exec.jar,“exec”可以换成其他自定义名称。
4、jar包中的MANIFEST.MF文件
(1)原始包:
(2)可执行包:
Start-Class: com.xx.xxApplication启动类信息等主要信息,该信息是可执行 jar 的入口类
Spring-Boot-Classes表示代码编译后的位置,Spring-Boot-Lib则表示项目依赖 jar 的位置
而不可执行的 jar 包并没有把依赖的jar包打进来,两个jar的内部结构是有很多不同的
其他建议:
一般来说,Spring Boot 直接打包成可执行 jar 就可以了,不建议将 Spring Boot 作为普通的 jar 被其他的项目所依赖。如果有这种需求,建议将被依赖的部分,单独抽出来做一个普通的 Maven 项目,然后在 Spring Boot 中引用这个 Maven 项目。