Maven 多模块项目中依赖模块编译失败的典型原因与解决方案

本文详解 maven 多模块项目中“依赖模块类无法被引用”问题的根本原因:非 spring 项目误用 `spring-boot-maven-plugin` 导致 `mvn clean install` 未生成有效 jar,进而使下游模块编译失败。

在 Maven 多模块项目中,当一个模块(如 runtime-migrations-conversion)依赖另一个本地模块(如 abis-migrations-conversion),常见误区是认为只要 声明正确、父 POM 包含 ,构建就必然成功。但实际构建失败(如大量 package xxx does not exist 或 cannot find symbol 错误)往往源于上游依赖模块自身未正确构建出可用的 artifact

关键线索在于:IDE(如 IntelliJ)可能通过项目内联解析“看似能识别”这些类,但 mvn clean install 是独立、隔离的构建过程,它只依赖 target/xxx.jar 和本地仓库(~/.m2/repository)中的产物。若上游模块构建失败或生成了无效 JAR(例如空 jar、仅含 MANIFEST.MF、无 class 文件),下游模块在编译阶段自然无法解析其包和类。

本案例中,abis-migrations-conversion 模块的 pom.xml 明确声明为普通 jar 打包(jar),且其代码结构不含 Spring Boot 启动类或自动配置逻辑。然而,它错误地引入了 spring-boot-maven-plugin 并执行 repackage 目标:


  
    
      org.springframework.boot
      spring-boot-maven-plugin
      2.3.4.RELEASE
      
        com.hcb.neurotec.migrations.conversion.AbisExportConverter
      
      
        
          
            repackage 
          
        
      
    
  

spring-boot-maven-plugin:repackage 的设计初衷是将普通 JAR 重打包为可执行的 fat-jar(内嵌依赖、修改 MANIFEST)。它要求项目必须是一个合法的 Spring Boot 应用(通常需继承 spring-boot-starter-parent 或显式管理 Spring Boot BOM)。当该插件作用于非 Spring Boot 项目时:

  • 构建过程可能静默跳过关键步骤;
  • target/abis-migrations-conversion-1.0-SNAPSHOT.jar 可能为空或不包含编译后的 class 文件;
  • mvn install 实际安装到本地仓库的是一个无效 artifact;
  • 下游模块 runtime-migrations-conversion 在编译时从本地仓库解压此 JAR,发现其中无任何 class,于是报出所有 package does not exist 错误。

解决方案非常明确:移除上游模块中不匹配的插件配置。
将 abis-migrations-conversion/pom.xml 中的 块完全删除(或至少移除 spring-boot-maven-plugin),保留最简构建配置:



  
    
    
      org.apache.maven.plugins
      maven-compiler-plugin
      3.8.0
      
        1.8
        1.8
      
    
  

随后,按顺序执行:

# 1. 清理并重新构建上游模块(确保生成有效 JAR)
cd abis-migrations-conversion
mvn clean install

# 2. 构建下游模块(此时能正确解析依赖)
cd ../runtime-migrations-conversion
mvn clean install

⚠️ 注意事项:

  • 验证本地仓库内容:构建后检查 ~/.m2/repository/com/hcb/migration/bioenro

    l/abis-migrations-conversion/1.0-SNAPSHOT/,确认 abis-migrations-conversion-1.0-SNAPSHOT.jar 文件存在且大小合理(非 0KB),并可通过 jar -tf 查看内部 class 结构。
  • IDE 同步:IntelliJ 等 IDE 需执行 Reload project(Maven 工具窗口 → 刷新按钮)以更新依赖索引,避免缓存误导。
  • 模块依赖范围:本例中 compile 是默认值,可省略;若仅测试时需要,才应设为 test。
  • Spring Boot 模块的正确用法:若某模块确实是 Spring Boot 应用,则应统一使用 spring-boot-starter-parent,并在 pom.xml 中声明 jar(默认)及 spring-boot-maven-plugin —— 但必须确保其 mainClass 确实存在且为 @SpringBootApplication 类。

总结而言,Maven 多模块依赖失效,首要排查点不是下游写法,而是上游模块是否真正构建出了符合预期的、可被消费的二进制产物。移除不匹配的构建插件、回归标准 Java 模块构建流程,是解决此类问题最直接有效的实践。