多 module Spring-Boot 项目 repackage 问题 | LIXI.FUN
0%

多 module Spring-Boot 项目 repackage 问题

某项目拆分通用工具类出来为单个 Module 时出现的问题,以下为模拟项目报错

1
2
3
4
5
6
7
[ERROR] Failed to execute goal 
org.apache.maven.plugins:maven-compiler-plugin:3.8.1:testCompile
(default-testCompile) on project module-b: Compilation failure

[ERROR] /D:/github/multi-modules/module-b/
src/test/java/com/nevertrouble/demo/moduleb/CallModuleAClassTest.java:[3,42]
程序包com.nevertrouble.demo.modulea.util不存在

引起问题的原因:拆分出来模块实际并不为 spring-boot 项目,却使用了 spring-boot-maven-plugin 进行打包,导致其他模块在编译时找不到此模块的包(idea 内部可以跳转)。

spring-boot-maven-plugin 中的 repackage 打包出来 jar 包不可被依赖。

问题项目还原

父项目 multi-modules

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
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<project>
<!-- SpringBoot 项目版本 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.nevertrouble.demo</groupId>
<artifactId>multi-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>

<name>multi-modules</name>
<description>多模块项目</description>

<!-- 父项目仅作为整合入口 -->
<packaging>pom</packaging>

<!-- 模块 -->
<modules>
<module>module-a</module>
<module>module-b</module>
</modules>

<dependencies>
<!-- 子模块公共依赖 -->
</dependencies>

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

</project>

module-a 模块 pom.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<project>
<!-- 父项目 -->
<parent>
<groupId>com.nevertrouble.demo</groupId>
<artifactId>multi-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>module-a</artifactId>
<name>module-a</name>

<dependencies>
<!-- module-a 自己的依赖 -->
</dependencies>

<build>
<plugins>
<!-- module-a 为工具类的模块,被依赖 -->
<!-- 做模块拆分的人没有更改这里,导致其他 module 在打包编译时找不到程序包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

module-b 的 pom.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<project>
<parent>
<groupId>com.nevertrouble.demo</groupId>
<artifactId>multi-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>module-b</artifactId>
<name>module-b</name>

<dependencies>
<!--b 依赖 a-->
<dependency>
<groupId>com.nevertrouble.demo</groupId>
<artifactId>module-a</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

<build>
<plugins>
<!-- b 本身为 springboot 可执行程序,此处无问题 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

当在父项目中存在 spring-boot-maven-plugin 时,子模块即便没有此插件,依旧会使用此插件进行打包,所以仅删除 module-a 中的 spring-boot-maven-plugin 是不可行的,在编译 module-a 时依旧会使用此插件。

解决方法

方法 1

同时删除 父项目 multi-modules 和 子模块 module-a 中的 spring-boot-maven-plugin 插件,则在 multi-modules 项目下进行 mvn clean package 时可以顺利打包。

这个方案有一些小瑕疵, module-a 打出来包,没有其所依赖的那些 lib,仅仅是它本身的类的编译结果。

方法 2

  • 删除父项目里的 spring-boot-maven-plugin 插件
  • 修改 module-a 中的 spring-boot-maven-plugin 插件配置,跳过 repackage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugins>
<!--跳过父项目传递过来的 spring-boot-maven-plugin 的 repackage -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<!-- 跳过 repackage -->
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

这个方案同样有 方法 1 中的问题,module-a 打出来的包不包含其依赖的 lib。

module-a 打包依赖 lib

方法 1方案 2 的基础上,添加 maven-shade-plugin 插件,用于打包 module-a 的依赖 lib。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugins>
<!-- maven-shade-plugin 是为了打包其依赖的 lib -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<configuration>
<!--不生成 dependency-reduced-pom.xml-->
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

总结

  • spring-boot-maven-plugin 中的 repackage 打包出来 jar 包不可被依赖。
  • 对非 spring-boot 的模块,如果父项目有 spring-maven-plugin,需要在此模块中跳过 repackage
  • 如果要打包非 spring-boot 的项目及其依赖包,需要使用其他插件,这里举例使用了 maven-shade-plugin
  • ps: spring-boot-maven-plugin 也依赖了 maven-shade-plugin 插件。
觉得有收获就鼓励下作者吧