当前位置: 首页 > news >正文

Maven 详解(下)

在标准的 Maven 多模块项目中,<parent><modules> 不仅可以同时出现,它们是“黄金搭档”,同时存在才能完整实现父子工程的聚合与继承功能。

这两个标签共同构成了 Maven 多模块项目的骨架。理解它们的作用、位置和工作机制是掌握模块化开发的关键。

一、 <modules> 标签 (在父 POM 中) - 聚合 (Aggregation)

  • 作用: 告诉 Maven:“我这个项目(父工程)是由哪些子模块组成的”。它实现了项目聚合

  • 位置: 父工程 (packaging=pom) 的 pom.xml 文件中

  • 语法:

    <modules><module>relative/path/to/module1</module><module>relative/path/to/module2</module><!-- ... -->
    </modules>
  • <module> 元素的值:

    • 这是一个相对路径,指向子模块目录的位置。
    • 路径是相对于父 POM 文件所在目录的。
    • 常见形式:
      • <module>module-common</module> (子模块与父 POM 同级)
      • <module>../shared-lib</module> (子模块在父工程的上一级目录,较少见)
      • <module>services/user-service</module> (更深层级的目录结构)
    • 路径指向的是包含 pom.xml 文件的子模块目录,而不是文件本身。
  • 工作原理 (聚合机制):

    1. 当你在父工程根目录执行 Maven 命令时(例如 mvn clean install),Maven 首先会读取父 POM。
    2. Maven 发现 <modules> 标签,就知道这是一个聚合项目。
    3. Maven 会遍历 <modules> 列表中的每一个路径,找到对应的子模块 pom.xml
    4. Maven 分析所有子模块之间的依赖关系(通过查看每个子模块 pom.xml 中的 <dependencies>)。
    5. Maven 根据依赖关系自动计算出一个正确的构建顺序(有依赖的模块必须先构建)。
    6. Maven 按照计算出的顺序,依次对每个子模块执行指定的生命周期阶段。
  • 关键点:

    • 聚合是可选的:你可以有一个父 POM 用于继承,但不包含 <modules>,这样你就不能在父目录下用一条命令构建所有模块。
    • 聚合不等于继承<modules> 只负责“把哪些模块一起构建”,它本身不提供任何配置继承。继承是由 <parent> 标签实现的。
    • 独立性:即使没有 <modules>,你也可以单独进入某个子模块目录运行 mvn 命令来构建它。

二、 <parent> 标签 (在子 POM 中) - 继承 (Inheritance)

  • 作用: 告诉 Maven:“我的这个子模块要继承哪个父 POM 的配置”。它实现了配置继承

  • 位置: 每个需要继承的子模块的 pom.xml 文件中

  • 语法:

    <parent><groupId>com.example</groupId><artifactId>my-parent-project</artifactId><version>1.0.0-SNAPSHOT</version><!-- 相对路径,告诉 Maven 如何找到父 POM 文件 --><relativePath>../pom.xml</relativePath>
    </parent>
  • 各个元素的含义:

    • <groupId><artifactId><version>: 这三个元素精确地定位了父 POM 的坐标。Maven 会根据这三个信息去查找父 POM。
    • <relativePath>:
      • 最重要的属性之一
      • 它是一个相对路径,告诉 Maven 在哪里可以找到父 POM 的 pom.xml 文件。
      • 路径是相对于当前子模块的 pom.xml 文件所在目录的。
      • 默认值../pom.xml。这意味着 Maven 默认假设父 POM 在子模块目录的上一级目录。
      • 何时需要显式声明:
        • 当你的标准结构被打破时(例如,子模块不在父工程目录下)。
        • 为了代码清晰,建议总是显式写出 <relativePath>
        • 如果父 POM 已经发布到远程仓库,而你希望优先从仓库下载而不是找本地文件,可以设置 <relativePath/>(空值)。
  • 工作原理 (继承机制):

    1. 当 Maven 处理一个子模块的 pom.xml 时,发现 <parent> 标签。
    2. Maven 会根据 <groupId><artifactId><version> 和 <relativePath> 去定位并读取父 POM 文件。
    3. Maven 将父 POM 中的配置与子模块自身的配置进行合并
    4. 继承的内容包括
      • 父 POM 的 groupId (子模块通常会继承,除非自己声明)
      • 父 POM 的 version (子模块通常会继承,除非自己声明)
      • <properties>
      • <dependencyManagement>
      • <pluginManagement>
      • <repositories> / <pluginRepositories>
      • <build> 中直接定义的配置(如果父 POM 不是在 <pluginManagement> 下定义插件)。
    5. 子模块可以在自己的 pom.xml 中覆盖补充这些继承来的配置。
  • 关键点:

    • 继承是可选的:一个子模块可以选择不继承任何父 POM。
    • 单继承: Maven POM 只支持单一父类继承(就像 Java 类一样)。一个子模块只能有一个 <parent>
    • 链式继承: 继承可以形成链条。例如,Child -> Parent -> GrandParentChild 会继承 Parent 和 GrandParent 的所有配置。
    • BOM 导入也是继承的一种应用: Spring Boot 的 spring-boot-starter-parent 本质上就是一个提供了大量默认配置的父 POM。

三、 <parent> 与 <modules> 的协同工作

虽然 <parent><modules> 分别位于不同的 POM 文件中,但它们共同协作,使多模块项目得以高效运行。

典型工作流程:

  1. 结构建立:

    • 你在父工程的 pom.xml 中用 <modules> 列出了所有子模块。
    • 你在每个子模块的 pom.xml 中用 <parent> 指向了父工程。
  2. 构建触发:

    • 你在父工程根目录执行 mvn install
  3. Maven 执行过程:

    • 步骤 1 (聚合): Maven 读取父 POM,发现 <modules>,知道了要构建 module-commonmodule-servicemodule-web
    • 步骤 2 (依赖分析): Maven 解析每个子模块的 pom.xml,发现 module-web 依赖 module-servicemodule-service 依赖 module-common
    • 步骤 3 (排序): Maven 计算出构建顺序:module-common -> module-service -> module-web
    • 步骤 4 (继承与构建):
      • 开始构建 module-common。由于它的 pom.xml 中有 <parent>,Maven 加载父 POM 配置,合并后得到 Effective POM,然后执行 install
      • 构建 module-service。同样,通过 <parent> 继承父 POM 配置,并且它的依赖 module-common 已经在本地构建好了(在 ~/.m2/repository 或模块间直接引用),可以顺利编译。
      • 构建 module-web。同理,继承父 POM,并成功依赖已构建好的 module-service

四、 总结对比表

特性<modules><parent>
中文含义模块 (复数)父级
主要目的聚合 (Aggregation) - “一起构建哪些模块”继承 (Inheritance) - “从谁那里继承配置”
所在位置父工程的 pom.xml 中子工程的 pom.xml 中
定义方向自上而下 (父告诉世界它有哪些孩子)自下而上 (子告诉世界它的父亲是谁)
内容包含一个或多个 <module> 元素,每个是子模块目录的相对路径包含 <groupId><artifactId><version> 和 <relativePath>,用于定位父 POM
是否必需对于聚合构建是必需的对于配置继承是必需的
能否省略可以省略,意味着不能一键构建所有模块可以省略,意味着子模块不继承任何父配置

一句话概括

<modules>父工程聚合子模块,用 <parent>子工程继承父工程的配置。两者结合,才能实现 Maven 多模块项目的统一管理和一键构建。

让我们通过一个具体的项目结构来说明:

my-project/                 # 父工程根目录
├── pom.xml                 # 父 POM (包含 <modules>)
├── common/                 # 子模块1
│   └── pom.xml             # 子 POM1 (包含 <parent>)
├── service/                # 子模块2
│   └── pom.xml             # 子 POM2 (包含 <parent>)
└── web/                    # 子模块3└── pom.xml             # 子 POM3 (包含 <parent>)

1. 父 POM (my-project/pom.xml) - 包含 <modules>

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>my-project</artifactId><version>1.0.0-SNAPSHOT</version><packaging>pom</packaging><!-- ✅ 父模块使用 <modules> 来声明它的子模块 --><modules><module>common</module><module>service</module><module>web</module></modules><!-- ... 其他配置如 dependencyManagement, properties 等 ... -->
</project>

2. 子 POM (web/pom.xml) - 包含 <parent>

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"><modelVersion>4.0.0</modelVersion><!-- ✅ 子模块使用 <parent> 来声明它的父模块 --><parent><groupId>com.example</groupId><artifactId>my-project</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath> <!-- 指向父 POM --></parent><artifactId>web</artifactId><!-- version 继承自父模块 --><!-- ... 子模块自己的 dependencies, build 等配置 ... -->
</project>

如果缺少其中一个会怎样?

情况结果
有 <modules> 但没有 <parent>只有聚合,没有继承
• 你可以在父目录用 mvn install 一键构建所有模块。
• 但是,所有子模块无法继承父 POM 中定义的 dependencyManagementpropertiespluginManagement 等配置。每个子模块都需要自己重复定义这些公共配置,失去了统一管理的意义。
有 <parent> 但没有 <modules>只有继承,没有聚合
• 所有子模块都可以继承父 POM 的配置,实现了统一管理。
• 但是,你无法在父目录运行一条命令来构建所有模块。你必须手动进入每个子模块目录,依次执行 mvn install。这在模块数量多时非常低效。
两者都有 ✅完美的聚合与继承
• 在父目录运行 mvn clean install,Maven 会:
1. 通过 <modules> 知道有哪些子模块。
2. 通过 <parent> (在子 POM 中) 确保每个子模块都继承了公共配置。
3. 自动分析依赖关系并按正确顺序构建所有模块。
• 这是开发大型项目的最佳实践。

结论

  • <parent> 和 <modules> 不仅可以同时出现,而且是构建一个功能完整的 Maven 多模块项目所必需的。
  • 它们是互补的关系,分别解决了配置继承项目聚合这两个核心问题。
  • <modules> 在父 POM 中定义,负责“组织”。
  • <parent> 在每个子 POM 中定义,负责“传承”。
  • 两者缺一不可。只有当它们“同时出现”时,Maven 的父子工程模式才能发挥出最大的威力,实现高效、统一的项目管理。
http://www.dtcms.com/a/561473.html

相关文章:

  • 网站建设和托管商业网站建设与维护
  • 国内优秀的企业网站seo排名优化服务
  • 网站开发毕设文档上海软件外包公司名单
  • 4.2 IPv4【2009统考真题】
  • Photoshop - Photoshop 工具栏(21)吸管工具
  • 网站建设专公众号平台有哪些
  • wordpress 全站过滤河南省建设厅官网查询
  • AEB对碰撞安全的作用
  • [论文阅读] AI + 教育 | AI赋能“三个课堂”的破局之道——具身认知与技术路径深度解读
  • 男的和女的做那种短视频网站网站标签的作用
  • 响应式网站开发的特点万网域名管理平台
  • 车载软件需求开发与管理 --- 需求分析与分解
  • 点击劫持攻击完整防护指南
  • 预备知识总结
  • 想自己做网站流程抚顺市营商环境建设局网站
  • 西安网站关键词优化费用淄博网站制作服务优化
  • alsa之ASOC架构学习
  • 技术深度解析:优秘智能企业智脑5.1.0版本 AI大管家架构设计与实现原理
  • 小型电商网站开发2022世界500强企业排名
  • 免费行情网站大全公司网站域名申请流程
  • PYNZ搭建高性能CNN部署的快速 FPGA 原型验证框架
  • Arduino硬件原理3:核心单片机
  • 学习周报二十
  • 建筑培训网站有哪些哪里有网站建设项目
  • 哪里可以捡到玉石谷歌seo零基础教程
  • 5G-NR标准的QC-LDPC码
  • Google NotebookLM重磅升级:从摘要工具到智能研究引擎的范式转移
  • C++11 面试题插入(左值引用和右值引用的区别)移动构造和移动赋值C++新标准如何解决传值返回但对象销毁问题
  • 住房城乡与建设厅网站首页智慧团建团员注册入口
  • 网站地图可以自己做么杭州网站制作 乐云践新