基于 Maven 的多模块项目架构

1. 关键 Maven 组件含义

在多模块项目中,以下四个标签构成了骨架的核心:

1.1 <modules>

  • 含义:聚合(Aggregation)。用于在父(根)项目中声明包含的子模块。
  • 作用:告诉 Maven:"当构建我(根项目)时,请顺带构建以下这些子文件夹"。它决定了 Maven 反应堆(Reactor)的扫描范围。
  • 代码示例(根 POM):
xml 复制代码
<modules>
    <module>dependencies</module>
    <module>server</module>
    <module>hmdianping</module>
</modules>

1.2 <dependencyManagement>

  • 含义:依赖版本锁定。
  • 作用 :它只声明依赖的 groupIdartifactIdversion不下载 Jar 包。它的作用是建立一个"版本字典",供子模块查询。
  • 代码示例(Dependencies 模块):
xml 复制代码
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.26</version>
        </dependency>
    </dependencies>
</dependencyManagement>

1.3 <dependencies>

  • 含义:依赖引入。
  • 作用 :真正的"下单"操作。Maven 会根据这里列出的坐标下载 Jar 包并加入 Classpath。如果在子模块中使用,且父工程/BOM 中已声明版本,则此处不写版本号
  • 代码示例(业务模块 POM):
xml 复制代码
<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
    </dependency>
</dependencies>

1.4 <packaging>pom</packaging>

  • 含义:打包类型为 POM。
  • 作用 :声明该项目是一个"容器"或"配置清单",不包含 Java 代码,也不会生成 JAR 文件。
  • 适用场景:根项目(Root)、版本管理模块(BOM/Dependencies)。

2. 多模块项目介绍与各模块 POM 职责

标准架构通常分为三层:根项目 -> BOM 模块 -> 业务/启动模块

2.1 根项目 (Root)

  • 职责:全局总控。定义全局变量、聚合子模块、配置编译插件。
  • POM 内容
xml 复制代码
<groupId>cn.iocoder.boot</groupId>
<artifactId>SpringDataRedis</artifactId>
<version>${revision}</version>
<packaging>pom</packaging> <modules>
    <module>dependencies</module> <module>hmdianping</module>
</modules>

<properties>
    <revision>2026.2.4-jdk17-SNAPSHOT</revision> </properties>

<dependencyManagement>
     <dependency>
         <groupId>cn.iocoder.boot</groupId>
         <artifactId>dependencies</artifactId>
         <version>${revision}</version>
         <type>pom</type>
         <scope>import</scope>
         <relativePath>dependencies/pom.xml</relativePath> </dependency>
</dependencyManagement>

2.2 依赖管理模块 (Dependencies)

  • 职责:版本大管家。纯配置文件,不写代码。
  • POM 内容
xml 复制代码
<parent>
    <artifactId>SpringDataRedis</artifactId>
    <groupId>cn.iocoder.boot</groupId>
    <version>${revision}</version>
    <relativePath>../pom.xml</relativePath>
</parent>
<artifactId>dependencies</artifactId>
<packaging>pom</packaging>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>3.5.10</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>cn.iocoder.boot</groupId>
            <artifactId>hmdianping</artifactId>
            <version>${revision}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

2.3 业务模块 (hmdianping)

  • 职责:代码实现。
  • POM 内容 :使用 <dependencies> 引入所需 Jar 包(如 MyBatis-Plus),不写版本号。

2.4 启动模块 (Server)

  • 职责:程序入口。
  • POM 内容
  • 引用所有业务模块(如 hmdianping)。
  • 配置 spring-boot-maven-plugin 插件进行打包(Repackage)。

3. POM 文件是如何串联起来的

这几个文件通过继承聚合导入三种机制形成闭环:

  1. 向下聚合 :根 POM 通过 <modules> 找到 dependencieshmdianping,建立构建列表。
  2. 向上继承 :子模块通过 <parent> + <relativePath> 继承根 POM,从而获取 ${revision} 变量和插件配置。
  3. 横向导入
  • 根 POM 在 dependencyManagementimportdependencies 模块。
  • 业务模块在引用依赖时,Maven 会向上追溯到根 POM,根 POM 指向 dependencies 模块,从而解析出正确的版本号。

串联示意图:

Root POM (定义变量) <--(继承)-- Children (获取变量)

Root POM (引用 BOM) --(Import)--> Dependencies POM (提供版本)

Business POM (请求依赖) --(查表)--> Root POM --> Dependencies POM


4. 多模块构建流程 (mvn install)

当在根目录执行 mvn clean install 时:

  1. 解析阶段 :Maven 读取根 POM,解析 ${revision}2026.2.4-jdk17-SNAPSHOT
  2. 计算反应堆 (Reactor) :Maven 扫描 <modules>,分析依赖拓扑,计算出构建顺序:
  • Root -> dependencies -> hmdianping -> server
  1. 执行阶段
  • Root:安装根 POM 到本地仓库。
  • Dependencies:读取 pom.xml,将其安装到本地仓库(作为版本参考文件)。
  • Hmdianping :编译 Java 代码,利用 dependencies 提供的版本号下载 Jar 包,最终打成 hmdianping.jar 安装到仓库。
  • Server :编译启动类,将 hmdianping.jar 和其他三方包解压合并,打成可运行的 Fat-Jar。

5. 为什么继承 spring-boot-starter-parent 会报错

在自定义的多模块架构中,如果根 POM 写了 <parent> 继承 spring-boot-starter-parent,常报 Non-resolvable import POMCould not find artifact

原因分析:

  1. 继承链冲突:Maven 只能单继承。如果你继承了 Spring Boot,就无法形成"根项目作为所有子模块唯一父类"的闭环。
  2. 依赖查找死锁
  • 根 POM 继承 Spring Boot 后,Maven 会优先按照 Spring Boot 的规则初始化。
  • 此时根 POM 试图 import 本地的 dependencies 模块。
  • 由于 Maven 认为父类是远程的 Spring Boot,它会倾向于去远程/本地仓库查找 dependencies 模块,而忽略本地磁盘(Local Disk)。
  • 结果 :因为 dependencies 是你刚写的,仓库里没有,Maven 报错"找不到构件"。

解决方案:

  • 解耦 :根 POM 不要 继承 spring-boot-starter-parent
  • 组合 :在 dependencies 模块中通过 import 方式引入 spring-boot-dependencies
  • 本地路径 :在根 POM 引用 dependencies 时,必须强制指定 <relativePath>dependencies/pom.xml</relativePath>,告诉 Maven:"别去仓库找了,文件就在磁盘这个位置"。
相关推荐
牢七18 小时前
反序列化重点模块 private Object readOrdinaryObject(boolean unshared)废案与反思
java·服务器·前端
够快云库18 小时前
企业数据安全实战复盘:基于零信任架构的数据安全闭环解析
安全·架构·企业文件管理
量子物理学18 小时前
三、C#高级进阶语法——特性(Attribute)
java·算法·c#
刘恒12345678919 小时前
Windows 电脑文件夹手动分类指南
java·windows·python·电脑·php
爱学习的小可爱卢19 小时前
JavaSE基础-Java异常处理全解析:从ClassNotFound到IndexOutOfBounds
java·javase
小王不爱笑13219 小时前
LangChain4j 项目实战--1:硅谷小智(医疗智能客服)笔记
java
XiaoLeisj19 小时前
Android Activity 页面导航基础:Manifest 声明、Intent 显式/隐式跳转与数据传递
android·java
忍者必须死19 小时前
JDK1.7的HashMap的环形链表
java·数据结构·算法·链表
鹿角片ljp19 小时前
短信登录:基于 Session 实现(黑马点评实战)
java·服务器·spring boot·mybatis
北风toto19 小时前
JDK8(JAVA)供应商说明
java·开发语言