Maven 聚合与继承
1. 背景
在这个技术发展飞速的时代,各类用户对软件的要求越来越高,软件本身也变得越
来越复杂。因此,软件设计人员往往会采用各种方式对软件划分模块,以得到更清晰的
设计及更高的重用性。
Maven 的聚合特性能够把项目的各个模块聚合在一起构建,而 Maven 的继承特性
则能帮助抽取各模块相同的依赖和插件等配置,在简化 pom 配置的同时,还能促进各个
模块配置的一致性。
2. 聚合
到目前为止,我们都是一个项目一个项目的构建。一个简单的需求就出来了,我们
会想要一此构建两个项目,而不是到两个模块分别执行 mvn 命令,Maven 聚合(或者
称为多模块)这一特性就是为该需求服务的。
a) 创建聚合模块
需要创建一个新的模块,来聚合构建项目中其他所有模块。
<modelVersion>4.0.0</modelVersion> <groupId>org.lichee</groupId> <artifactId>lichee</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <name>lichee :: project</name> <description>This is a project demo of lynch</description> <inceptionYear>2013-2014</inceptionYear> <modules> <module>parent</module> <module>core</module> <module>common</module> <module>support</module> <module>test</module> <module>simple-example</module> </modules>
b) 聚合模块特征
i. Maven 项目
聚合模块本身也是一个 Maven 项目。
ii. 目录差异
准确说除了其他模块目录和 pom.xml,没有其他任何 src、test、target 等相关目录。
iii. pom.xml
1) 相同的 groupId、version
2) packaging 必须是 pom
继承父模块也一样必须是 pom。
3) name 提供一个相对容易阅读的名字
配置合理的 name 字段,会让 Maven 的构建输出更清晰。
4) modules
实现聚合的最核心配置,用户可以通过一个打包方式为 pom 的 Maven 项目中声明,
任意数量的 module 元素来实现模块的聚合。每个 module 的值都是一个当前 pom 的相对目录。
5) 模块所处的目录名称与其 artifactId 一致
文件的目录名称和 artifactId 相同,但不绝对,只是 module 里面的配置,
必须和文件目录上的名字一样。
6) 推荐目录格式
通常将聚合模块放在项目目录的最顶层,其他模块则作为聚合模块的子目录存在,
方便用户寻找聚合模块来构建整个项目。
c) 解析过程
Maven 会首先解析聚合模块的 pom、分析要构建的模块、并计算出一个反应堆构建顺序
(Reactor Build Order),然后根据这个顺序依次构建各个模块。
i. 项目构建小结报告
ii. 各个模块构建成功与否、花费时间
iii. 整个构建花费的时间、使用内存等
3. 继承
很多项目中,不同的子模块有着相同的 groupId、version,相同的 spring、junit等依赖,
相同的 maven-compiler-plugin 插件等配置。这就是重复,重复意味着更多的劳动和更多的潜在问题。
在 Maven 世界中,有机制能让我们抽取出重复的配置,这就是 pom 的继承。
a) 创建继承模块
我们需要创建 pom 的父子结构,在父 pom 中声明一些配置供子 pom 继承,一处声明,多处使用。
父模块:
<groupId>org.lichee</groupId> <artifactId>lichee-parent</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <name>lichee :: parent</name>
子模块:
<parent> <groupId>org.lichee</groupId> <artifactId>lichee-parent</artifactId> <version>1.0.0</version> <relativePath>../parent/</relativePath> </parent> <artifactId>lichee-core</artifactId> <packaging>jar</packaging> <name>lichee :: core</name>
b) 继承模块特征
i. Maven 项目
继承模块本身也是一个 Maven 项目。
ii. 目录差异
准确说除了 pom.xml,没有其他任何 src、test、target 等相关目录。
iii. pom.xml
1) groupId、version
虽然子模块没有声明,不过不代表子模块没有这两个属性,隐式地从父模块继承了这两个元素,
这也就消除一些不必要的配置。如果子模块需要使用和父模块,
不一样的 groupId 或者 version 的情况,那么用户完全可以在子模块中显式声明。
对于 artifactId 元素来说,子模块应该显式声明。
2) packaging 必须是 pom
和聚合模块一样。
3) name 提供一个相对容易阅读的名字
配置合理的 name 字段,会让 Maven 的构建输出更清晰。
4) relativePath
表示父模块 pom 的相对路径,默认值为../pom.xml,也就是说,
Maven默认父 pom 在上一层目录下。如果子模块没有设置正确的 relativePath,
Maven 将无法找到父 pom,这将直接导致构建失败。
4. 可继承的 pom 元素
a) groupId
项目组 Id,项目坐标的核心元素。
b) version
项目版本,项目坐标的核心元素。
c) description
项目的描述信息。
d) organization
项目的组织信息。
e) inceptionYear
项目的创始年份。
f) url
项目的 url 地址。
g) developers
项目的开发者信息。
h) contributors
项目的贡献者信息。
i) distributionManagement
项目的部署配置。
j) issueManagement
项目的缺陷跟踪系统信息。
k) ciManagement
项目的持续集成系统信息。
l) scm
项目的版本控制系统信息。
m) mailingLists
项目的邮件信息列表。
n) properties
自定义的 Maven 属性。
o) dependencies
项目的依赖配置。
p) dependencyManagement
项目的依赖管理配置。
q) repositories
项目的仓库配置。
r) build
包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等。
s) reporting
包括项目的报告输出目录配置、报告插件配置等。
5. 依赖管理
通过 dependencies 元素,可以将父模块的依赖继承到子类中,但并不是每一个子模块
都需要相同的依赖。也不合理。
a) dependencyManagement
让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性。
在这个元素下的依赖声明不会引入实际的依赖,不过它能够约束 dependencies 下的依赖使用。
父模块:
<properties> <junit.version>4.11</junit.version> <spring.version>3.2.5.RELEASE</spring.version> <jdk.version>1.6</jdk.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> </dependencies> </dependencyManagement>
子模块:
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> </dependencies>
i. 变量提取
spring 和 junit 依赖的版本以 maven 变量的形式提取出来,不仅消除了一些重复,
也使得个依赖的版本处于更加明显的位置。
ii. 引入时机
dependencyManagement 声明的依赖不会被任何一个子模块引入,
不过这段配置是会被子模块继承的。子模块的引入这些依赖就很简单了。
1) 只配置 groupId 和 artifactId
省去 version 和 scope,这些想信息可以被省略是因为子模块继承了,
父模块的 dependencyManagement,完整的依赖声明在父 pom 中,
子模块只需要配置简单的 groupId 和 artifactId 就能获得对应的依赖信息,
从而引入正确的依赖。
2) 选择性引入依赖
如果子模块的 pom 中不声明某个依赖的使用,即使该依赖已经在父 pom
的 dependencyManagement 中声明了,也不会产生任何实际的效果,
也就是说不会被引入到子模块的依赖中。
3) 最佳推荐
这种依赖管理机制似乎不能减少太多的 pom 配置,不过还是推荐采用这种方式。
因为在父 pom 中使用 dependencyManagement 声明依赖能够统一项目范围中的依赖版本,
子模块在使用过程中无需声明版本,也不会发生多个子模块使用的依赖版本不一致,
这可以降低依赖冲突的几率,对于后期升级或者修改依赖版本,也是提供了大大的便利。
4) import 依赖范围
这个范围的依赖只在 dependencyManagement 元素下才有效果,使用该范围的依赖通常
指向一个 pom,作用是将目标 pom 中的dependencyManagement 配置导入并合并到,
当前 pom 的dependencyManagement 元素中。import 范围依赖由于其特俗性,
一般都是指向打包类型为 pom 的模块。
6. 插件管理
Maven 提供了 dependencyManagement 元素帮助管理依赖,类似的,
Maven 也提供了 pluginManagement 元素帮助管理插件。
a) pluginManagement
该元素中配置的依赖插件不会造成实际插件的行为,当子模块 pom 中配置了真正的plugin 元素,
并且 groupId、artifactId 与 pluginManagement 中配置的插件匹配时,
pluginManagement 的配置才会影响实际的插件行为。
父模块:
<pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.6</source> <target>1.6</target> <showWarnings>true</showWarnings> </configuration> </plugin> </plugins> </pluginManagement>
子模块:
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> </plugins>
i. 变量提取
和 dependencyManagement 一样。
ii. 引入时机
和 dependencyManagement 一样。
iii. 最佳推荐
当项目中的多个模块有同样的插件配置时,应当将配置移到父 pom 的pluginManagement 元素中。
甚至可以要求将所有用到的插件的版本在父pom的pluginManagement元素中声明,
子模块使用插件时不配置版本信息,这么做可以统一插件的版本,
避免潜在的插件不一致或者不稳定问题,也便易于维护。
7. 聚合与继承的关系
a) 相同点
聚合 pom 和继承关系中的父 pom 的 packaging 都必须是 pom,
聚合模块与继承关系中的父模块除了 pom 之外都没有实际的内容。
往往也会发现,一个 pom 既是聚合 pom,也是父 pom,这么做主要是为了方便,
融合使用聚合与继承也没有什么问题。
b) 不同点
i. 聚合
为了方便快速构建项目。它知道有哪些被聚合的模块,但那些被聚合的模块不知道这个聚合模块。
ii. 继承
为了消除重复配置。它不知道有哪些子模块继承与它,但那些子模块都必须知道,
自己的父 pom 是什么。
c) 如图所示
8. 约定优于配置
Maven 提倡“约定优于配置”(Convention Over Configuration),这是 Maven最核心的设计理念之一。
原因之一就是使用约定可以大量减少配置。
a) 源码目录为 src/main/java/
b) 源码资源目录为 src/main/resources/
c) 测试目录为 src/test/java/
d) 测试资源目录为 src/test/resources/
e) 编译输出目录为 target/classes/
f) 打包方式为 jar
g) 包输出目录为 target/
h) 超级 pom
超级 pom 定义以上的目录结构、核心插件设定版本。Maven 设定核心插件的原因,
是防止由于插件版本的变化而造成构建的不稳定。
遵循约定虽然损失了一定的灵活性,用户不能随意安排目录结构,但是却能减少配置。
更重要的是,遵循约定能够帮用户遵循构建标准。个性往往意味着牺牲通用性,
意味着增加无谓的复杂度。
9. 反应堆
反应堆(Reactor)是指所有模块组成的一个构建结构。对于单模块的项目,反应堆就
是该模版本身,但对于多模块项目来说,反应堆就包含了各模块之间继承与依赖的关系。
a) 反应堆的构建顺序
一般情况按照 modules 的声明顺序,不过也有特俗情况。Maven 按序读取 pom,
如果该 pom 没有依赖模块,那么就构建该模块,否则就先构建其依赖模块,
如果该依赖还依赖于其他模块,则进一步先构建依赖的依赖。
i. 继承或者依赖
Maven 还需要考虑模块之间的继承和依赖关系。
ii. 有向非循环图
模块间的依赖关系会将反应堆构成一个有向非循环图。
b) 裁剪反应堆
用户会想要仅仅构建完整反应堆中的某些个模块。也就是用户需要实时地裁剪反应堆。
Maven 提供很多命令行选项支持裁剪反应堆,mvn –h 查看。
略(不常用)
相关推荐
**三、继承与聚合的结合** 在实际项目中,聚合和继承往往结合使用。`parent`项目作为一个聚合项目,包含了多个子项目,同时作为父项目,它定义了通用的配置供子项目继承。这种方式有助于保持项目结构清晰,减少代码...
Maven聚合(Aggregation)功能则允许我们将多个Maven项目组合成一个单一的构建单元。通过在父POM中使用`<modules>`标签,可以列出所有子模块,Maven在构建时会按顺序编译和打包每个子模块。这在处理大型多模块项目时...
最后是"Maven聚合"。聚合(Aggregation)是指在单个Maven项目中管理多个子项目的能力。在`pom.xml`中定义`modules`标签,可以将多个子项目包含进来。这样,当我们在顶层项目上执行命令时,Maven会递归地构建所有子...
Maven聚合(Aggregation)是用来管理多个相关项目的方式,这些项目可能共享一部分代码或者有共同的构建目标。在POM中,我们可以通过设置`<modules>`标签来指定一个父项目下的子项目。这样,当我们在父项目执行构建...
**二、Maven聚合** Maven的聚合功能则用于管理多个相关项目,把它们组合成一个整体。这主要通过`<modules>`标签来实现,它允许在一个POM中列出一系列子模块,使得我们可以一次性构建这些模块。聚合POM并不直接影响...
总结来说,这个"Maven聚合项目"是一个集成了聚合、继承、插件管理和私服使用的实例,展示了如何高效地管理和构建多模块的Java项目。通过这种方式,开发团队可以更有效地协同工作,保证项目的稳定性和一致性。
在本文中,我们将深入探讨 Maven 的聚合与继承特性,并结合前后端分离的实践,来创建一个高效的开发环境。Maven 是 Java 开发中广泛使用的构建工具,它通过配置管理依赖关系,简化项目的构建、测试和部署过程。让...
总结来说,"maven聚合工程demo"是一个利用 Maven 聚合和继承机制,结合 SSH 框架构建的多模块 Java Web 应用项目。通过聚合,我们可以高效地管理多个子项目,通过继承,我们保持了配置的一致性。同时,"META-INF" 和...
"maven聚合实例"正是讨论如何通过Maven的聚合(Aggregation)功能来组织这些子项目。 Maven聚合允许我们在一个父项目中管理多个子项目,这个父项目被称为"聚合模块"或"顶级模块",在本例中是`demo-top`。这种结构...
"maven聚合项目模板"是指使用Maven创建的一种特殊结构,用于组织多个相关但独立的子项目,使得这些子项目可以作为一个整体进行构建和管理。这种方式在大型项目或者有多个子模块的项目中非常常见。 1. **模块分组**...
10. Maven聚合与继承:Maven支持项目间的聚合和继承,聚合允许将多个项目组合在一起作为一个整体进行构建,而继承则允许共享部分POM配置,减少重复代码。 总的来说,这个预配置好的“apache-maven-3.9.2.zip”文件...
在"Maven 依赖,聚合,继承,插件运行应用"这个主题中,我们将深入探讨这四个核心概念。 1. **依赖管理**:Maven依赖是项目中各个模块之间共享代码的关键机制。当你在POM.xml文件中声明一个依赖,Maven会自动下载并...
Maven,作为Java开发中的构建工具,提供了强大的聚合(Aggregation)和继承(Inheritance)特性,使得多模块项目的管理变得高效且有序。本文将深入探讨如何利用这两个特性来创建一个复杂的多模块项目,并通过提供的...
6. Maven聚合与继承: - 聚合项目将多个模块组合在一起,方便一次性构建所有子模块。 - 继承项目提供了一种共享配置的方式,子项目可以从父项目继承部分配置。 7. Maven profile: - 用于定义不同环境(如开发、...
### Maven聚合与继承介绍 Maven支持项目聚合,意味着可以将多个模块打包为一个大项目进行管理,这对于大型项目非常有用。同时,Maven通过parent和modules元素支持项目继承,可以定义一个父POM来复用和管理子模块的...
### Maven安装配置教程及仓库、POM坐标系、Maven工程、继承与聚合 #### Maven安装与配置 在开始之前,我们首先需要了解Maven是什么。Maven是Apache的一个项目,是一个项目管理和综合工具,主要用来帮助Java项目...
8. Maven聚合与继承: - 聚合(Aggregation):将多个Maven项目组合在一起进行构建,便于管理大型项目。 - 继承(Inheritance):子项目继承父项目的POM,可以共享配置,减少重复代码。 9. 配置Maven: - `...
在Java开发中,Maven聚合项目(Aggregator Project)是一种管理多模块项目的方式,它允许开发者在一个父项目中集合并构建多个子项目。这样的结构有助于代码的组织和依赖管理,特别是当项目涉及到多个独立但相互关联...
6. **Maven聚合与继承** - **聚合项目**:一个POM可以包含多个模块,方便管理多模块项目。 - **继承关系**:子POM可以从父POM继承配置,减少重复代码。 7. **Maven的生命周期与构建过程** - **清理**:clean生命...