You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何mvn package编译失败但mvn test可通过?如何正确打包多模块项目?

Maven Spring Boot多模块项目打包问题

项目背景

我有一个Maven Spring Boot多模块项目,执行mvn clean test时构建成功,日志如下:

[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for dummy 0.0.1-SNAPSHOT:
[INFO]
[INFO] dummy .............................................. SUCCESS [  0.094 s]
[INFO] common ............................................. SUCCESS [  4.884 s]
[INFO] foo ................................................ SUCCESS [  2.987 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

但执行mvn clean package时,foo模块编译失败,日志如下:

[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for dummy 0.0.1-SNAPSHOT:
[INFO]
[INFO] dummy .............................................. SUCCESS [  0.661 s]
[INFO] common ............................................. SUCCESS [  4.673 s]
[INFO] foo ................................................ FAILURE [  0.178 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.731 s
[INFO] Finished at 2023-02-04T20:04:51-05:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.10.1:compile (default-compile) on project foo: Compilation failure: Compilation failure:

疑问与现状

  • 为何在test阶段编译已通过的情况下,package阶段会出现编译错误?
  • 在IntelliJ IDEA中可正常运行CommonApplication和FooApplication,功能验证通过:
    • CommonApplication可访问/common端点及ws://localhost:8080/ws/common WebSocket;
    • FooApplication可访问/common、/foo端点及对应WebSocket。

需求

如何正确打包该项目?希望能通过单个Jar运行CommonApplication或FooApplication,例如执行java -jar foo.jar即可启动Spring Boot应用,本地可访问/common、/foo及ws://localhost:8080/ws/common。

环境版本

Java版本

java --version
openjdk 14.0.2 2020-07-14
OpenJDK Runtime Environment (build 14.0.2+12-46)
OpenJDK 64-Bit Server VM (build 14.0.2+12-46, mixed mode, sharing)

Maven版本

mvn --version
Apache Maven 3.8.7 (b89d5959fcde851dcb1c8946a785a163f14e1e29)
Maven home: /usr/local/Cellar/maven/3.8.7/libexec
Java version: 14.0.2, vendor: Oracle Corporation, runtime: /usr/local/Cellar/sdkman-cli/5.16.0/libexec/candidates/java/14.0.2-open
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.16", arch: "x86_64", family: "mac"

问题解决

1. package阶段编译失败的原因

mvn clean test和mvn clean package的执行逻辑存在差异:

  • test阶段会编译主代码和测试代码,测试通过后不会清理编译产物;
  • package阶段默认会先执行compile目标,但如果项目中存在模块依赖的编译产物缺失、或者Maven插件配置冲突,就可能导致重新编译时失败。

这种情况多半是foo模块依赖common模块,但common模块的打包配置未正确暴露编译后的类,或者foo模块的maven-compiler-plugin配置存在问题,导致package阶段重新编译foo时无法找到common中的类。另外IDEA能正常运行是因为它会自行管理依赖的编译产物,和Maven的生命周期执行逻辑不同。

2. 正确打包多模块Spring Boot项目的步骤

要实现单个可运行Jar启动应用,需针对每个业务模块配置Spring Boot的maven-spring-boot-plugin,同时注意父模块的打包类型:

步骤1:父模块(dummy)配置

将父模块的打包类型设为pom,仅负责管理依赖和模块,不生成Jar:

<packaging>pom</packaging>

移除父模块中不必要的maven-spring-boot-plugin配置,因为父模块不需要打包成可运行Jar。

步骤2:common模块配置

common模块作为依赖模块,不需要打包成可运行Jar,只需配置普通的编译打包:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
                <source>14</source>
                <target>14</target>
            </configuration>
        </plugin>
    </plugins>
</build>

确保common模块的依赖都正确声明,且foo模块能通过Maven依赖解析到它的编译产物。

步骤3:foo模块配置

foo模块需要打包成可运行Jar,配置maven-spring-boot-plugin并指定启动类:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.7.8</version> <!-- 匹配你的Spring Boot版本 -->
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <mainClass>com.example.foo.FooApplication</mainClass>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
                <source>14</source>
                <target>14</target>
            </configuration>
        </plugin>
    </plugins>
</build>

同时,foo模块要正确依赖common模块:

<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

步骤4:执行打包命令

在项目根目录执行:

mvn clean package

打包完成后,foo/target目录下会生成两个Jar:

  • foo-0.0.1-SNAPSHOT.jar:可运行Jar(直接执行即可)
  • foo-0.0.1-SNAPSHOT.jar.original:普通Jar(无需使用)

直接执行以下命令启动FooApplication:

java -jar foo/target/foo-0.0.1-SNAPSHOT.jar

启动后即可访问对应端点和WebSocket。

步骤5:CommonApplication的打包

如果需要单独打包common模块为可运行Jar,只需在common模块中添加同样的spring-boot-maven-plugin配置,指定mainClass为com.example.common.CommonApplication即可。

额外排查点

如果打包仍失败,检查以下内容:

  • 确认所有模块的Java版本配置一致(均为14);
  • 清理Maven本地仓库中common模块的快照,重新执行mvn clean install后再打包;
  • 查看完整的编译错误日志(你提供的日志截断了具体错误信息),可执行mvn clean package -X查看详细日志,定位具体缺失的类或配置问题。

内容的提问来源于stack exchange,提问作者Jiahua Zhang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 15:35:51