Part one

我们在开发过程中,创建了2个以上的模块,每个模块都是一个独立的maven project,在开始的时候我们可以独立的编译和测试运行每个模块,但是随着项目的不断变大和复杂化,我们期望能够使用简单的操作来完成编译等工作,这时Maven给出了聚合的配置方式。

所谓聚合,顾名思义,就是把多个模块或项目聚合到一起,我们可以建立一个专门负责聚合工作的Maven project ---  aggregator。

建立该project的时候,我们要注意以下几点:

1.该aggregator本身也做为一个Maven项目,它必须有自己的POM

2.它的打包方式必须为: pom

3.引入了新的元素:modules---module

4.版本:聚合模块的版本和被聚合模块版本一致

5.relative path:每个module的值都是一个当前POM的相对目录

6.目录名称:为了方便的快速定位内容,模块所处的目录应当与其artifactId一致(Maven约定而不是硬性要求),总之,模块所处的目录必须和<module>模块所处的目录</module>相一致。

7.习惯约定:为了方便构建,通常将聚合模块放在项目目录层的最顶层,其它聚合模块作为子目录存在。这样当我们打开项目的时候,第一个看到的就是聚合模块的POM

8.聚合模块减少的内容:聚合模块的内容仅仅是一个pom.xml文件,它不包含src/main/Java、src/test/java等目录,因为它只是用来帮助其它模块构建的工具,本身并没有实质的内容。

9.聚合模块和子模块的目录:他们可以是父子类,也可以是平行结构,当然如果使用平行结构,那么聚合模块的POM也需要做出相应的更改。

二、为什么要继承?

做面向对象编程的人都会觉得这是一个没意义的问题,是的,继承就是避免重复,maven的继承也是这样,它还有一个好处就是让项目更加安全

情景分析二:我们在项目开发的过程中,可能多个模块独立开发,但是多个模块可能依赖相同的元素,比如说每个模块都需要Junit,使用spring的时候,其核心jar也必须都被引入,在编译的时候,maven-compiler-plugin插件也要被引入

如何配置继承:

1.说到继承肯定是一个父子结构,那么我们在aggregator中来创建一个parent project

2.<packaging>: 作为父模块的POM,其打包类型也必须为POM

3.结构:父模块只是为了帮助我们消除重复,所以它也不需要src/main/java、src/test/java等目录

4.新的元素:<parent> , 它是被用在子模块中的

5.<parent>元素的属性:<relativePath>: 表示父模块POM的相对路径,在构建的时候,Maven会先根据relativePath检查父POM,如果找不到,再从本地仓库查找

6.relativePath的默认值: ../pom.xml

7.子模块省略groupId和version: 使用了继承的子模块中可以不声明groupId和version, 子模块将隐式的继承父模块的这两个元素

三、可被继承的POM元素

groupId:项目组ID,项目坐标的核心元素

version: 项目版本, 项目坐标的核心元素

description: 项目的描述信息

organization: 项目的组织信息

inceptionYear: 项目的创始年份

url: 项目的URL地址

developers: 项目开发者信息

contributors: 项目的贡献者信息

distributionManagement: 项目的部署配置

issueManagement: 项目的缺陷跟踪系统信息

ciManagement: 项目的持续集成系统信息

scm: 项目的版本控制系统信息

mailingLists: 项目的邮件列表信息

properties: 自定义的maven属性

dependencies: 项目的依赖配置

dependencyManagement: 项目的依赖管理配置

repositories: 项目的仓库配置

build: 包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等

reporting: 包括项目的报告输出目录配置、报告插件配置等

四、maven的依赖管理

我们知道dependencies是可以被继承的,这个时候我们就想到让我们的发生了共用的依赖元素转移到parent中,这样我们又进一步的优化了配置。可是问题也随之而来,如果有一天我创建了一个新的模块,但是这个模块不需要这些parent的依赖,这时候如何处理?

是的,maven的依赖管理就是来解决这个问题的

增加一个新的元素:dependencyManagement

从上面的列表中我们发现dependencyManagement也是可以被继承的,这恰恰满足了我们的需要,它既能够让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性

dependencyManagement的特性:在dependencyManagement中配置的元素既不会给parent引入依赖,也不会给它的子模块引入依赖,仅仅是它的配置是可继承的

最佳实践:

这时候我们就可以在父POM中声明这些依赖:

[html] view plaincopy
  1. <span style="white-space:pre">    </span><properties>
  2. <target.version>2.5.6</target.version>
  3. </properties>
  4. <dependencyManagement>
  5. <dependencies>
  6. <dependency>
  7. <groupId>your groupId</groupId>
  8. <artifactId>your artifactId</artifactId>
  9. <version>${target.version}</version>
  10. </dependency>
  11. </dependencies>
  12. </dependencyManagement>

子模块的POM继承这些配置:子模块继承这些配置的时候,仍然要声明groupId和artifactId,表示当前配置是继承于父POM的,从而直接使用父POM的版本对应的资源

[html] view plaincopy
  1. <span style="white-space:pre">        </span><dependencies>
  2. <dependency>
  3. <groupId>your groupId</groupId>
  4. <artifactId>your artifactId</artifactId>
  5. </dependency>
  6. </dependencies>

这个可以有效的避免多个子模块使用依赖版本不一致的情况,有助于降低依赖冲突的几率。注:只有子模块配置了继承的元素,才会真正的有效,否则maven是不会加载父模块中声明的元素。

五、Maven的插件管理

再增加一个新的元素:<pluginManagement>

这个元素和<dependencyManagement>相类似,它是用来进行插件管理的。

在我们项目开发的过程中,也会频繁的引入插件,所以解决这些复杂配置的方法就是使用插件管理

我们可以在父POM中做如下声明:

[html] view plaincopy
  1. <span style="white-space:pre">    </span><build>
  2. <pluginManagement>
  3. <plugins>
  4. <plugin>
  5. <groupId></groupId>
  6. <artifactId></artifactId>
  7. <version></version>
  8. <executions>
  9. <execution>
  10. <id></id>
  11. <goals>
  12. <goal></goal>
  13. </goals>
  14. <phase></phase>
  15. <configuration>
  16. <source></source>
  17. <target></target>
  18. </configuration>
  19. </execution>
  20. </executions>
  21. </plugin>
  22. </plugins>
  23. </pluginManagement>
  24. </build>

在子模块中,我们可以直接继承

[html] view plaincopy
  1. <span style="white-space:pre">    </span><build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.apache.maven.plugins</groupId>
  5. <artifactId>maven-compiler-plugin</artifactId>
  6. </plugin>
  7. </plugins>
[html] view plaincopy
  1. <pre name="code" class="html"><span style="white-space:pre">    </span></build>

我们会发现,继承的细节上和<dependencyManagement>几乎一样。

六、聚合与继承的总结

当我们明白聚合与继承的细节之后,我们会发现:

对于聚合模块来说,它知道有哪些被聚合的模块,而对于被聚合的模块来说,它们不知道被谁聚合了,也不知道它的存在

对于继承关系的父POM来说,它不知道自己被哪些子模块继承了,对于子POM来说,它必须知道自己的父POM是谁

在一些最佳实践中我们会发现:一个POM既是聚合POM,又是父POM,这么做主要是为了方便。

Part Two

Maven的聚合特性能够把项目的各个模块聚合在一起构件,而Maven的继承特性则能帮助抽取各模块相同的依赖和插件等配置。在简化POM的同时,还能促进各个模块配置的一致性。下面以具体项目来讲解:

1. 项目结构


以上有五个项目分别为user-parent, user-core, user-log, user-dao, user-service. 其中user-parent项目为其他项目的父项目,只是帮助其他模块构建的工具,它本身并无实质的内容,只有一个pom.xml文件。

2. user-parent的pom.xml详情如下(下文简称为父POM)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.liangbo.user</groupId><artifactId>user-parent</artifactId><version>0.0.1-SNAPSHOT</version><packaging>pom</packaging><modules><module>../user-core</module><module>../user-dao</module><module>../user-log</module><module>../user-service</module></modules><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><junit.version>4.10</junit.version><mysql.driver>com.mysql.jdbc.Driver</mysql.driver><mysql.url>jdbc:mysql://localhost:3306/mysql</mysql.url><mysql.username>root</mysql.username><mysql.password>password</mysql.password></properties><dependencyManagement><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency><dependency><groupId>com.liangbo.user</groupId><artifactId>user-core</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.liangbo.user</groupId><artifactId>user-log</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.liangbo.user</groupId><artifactId>user-dao</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.liangbo.user</groupId><artifactId>user-log</artifactId><version>0.0.1-SNAPSHOT</version><exclusions><exclusion><groupId>log4j</groupId><artifactId>log4j</artifactId></exclusion></exclusions></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.9</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1.1</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>3.6.10.Final</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.16</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.26</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.5</version></dependency><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.12.1.GA</version></dependency></dependencies></dependencyManagement><build><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><version>2.2.1</version><executions><execution><phase>package</phase><goals><goal>jar-no-fork</goal></goals></execution></executions></plugin><plugin><groupId>org.codehaus.mojo</groupId><artifactId>sql-maven-plugin</artifactId><version>1.5</version><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.26</version></dependency></dependencies><configuration><driver>${mysql.driver}</driver><url>${mysql.url}</url><username>${mysql.username}</username><password>${mysql.password}</password><sqlCommand>create database IF NOT EXISTS maven_test</sqlCommand></configuration>                <executions><execution><phase>package</phase><goals><goal>execute</goal></goals></execution>                </executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-rar-plugin</artifactId><version>2.3</version><executions><execution><phase>package</phase><goals><goal>rar</goal></goals></execution></executions></plugin></plugins></pluginManagement></build>
</project>

上面的pom.xml文件既有Maven的聚合特性又有继承特性。这样做是为了更加方便管理其他模块。其中元素modules,是实现聚合的最核心配置。多个子模块之间的pom有很多的相同的配置,这时候可以全部提取出来放到父项目中。重复往往就意味着更多的劳动和更多的潜在的问题。那么子模块如何来继承他的父项目呢?

3. 下面来看下user-core项目pom.xml的配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.liangbo.user</groupId><artifactId>user-parent</artifactId><version>0.0.1-SNAPSHOT</version><relativePath>../user-parent/pom.xml</relativePath></parent> <artifactId>user-core</artifactId><packaging>jar</packaging><name>user-core</name><url>http://maven.apache.org</url><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></dependency><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId></plugin><plugin><groupId>org.codehaus.mojo</groupId><artifactId>sql-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-rar-plugin</artifactId></plugin></plugins></build>
</project>

其中设置好relativePath非常重要,不然无法找到父POM。这时候子POM中只需要配置groupId和artifactId就可以了。

4. 依赖管理和插件管理

上述子POM配置简单了很多,是因为父POM引用了依赖管理和插件管理的概念。如果父POM没有配置依赖管理和插件管理的话,继承它的子模块会将父所有的依赖和插件都继承下来,显然这是不可行的。接下来讲下如何配置的:

Maven提供的dependencyManagement元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性(也就是说写在dependencyManagement中的jar包依赖不会自动被子模块继承,除非子模块中显示声明要使用到的jar包依赖,才会把该对应的jar包依赖从父模块那继承下来,当然在父模块中我们已经写了groupId,artifactId,version,所以子模块中只需要写groupId和artifactId就可以继承该依赖不必再写版本号)。在dependencyManagement元素下的依赖声明不会引入实际的依赖,不过它可以约束dependencies下的依赖使用。插件管理同上,需要在父POM中加入pluginManagement元素。

最后,说下聚合与继承的关系,多模块Maven中的聚合与继承其实是两个不同的概念,其目的是不同的。前者主要是为了方便快速构建项目(即方便将项目中多个模块进行管理,比如一起编译测试而不用挨个去执行命令),后者主要是为了消除重复配置。 当然聚合与继承的pom 一般写在同一个pom项目中主要是为了方便,  聚合一般写在pom.xml中最上边。

说明一下 版本号一般为 x.x.x-SNAPSHOT (snapshot即开发中的版本  开发快照) x.x.x-release 表示发布版本

Maven聚合和继承相关推荐

  1. Maven 聚合与继承

    Maven 聚合与继承 1. 背景 在这个技术发展飞速的时代,各类用户对软件的要求越来越高,软件本身也变得越 来越复杂.因此,软件设计人员往往会采用各种方式对软件划分模块,以得到更清晰的 设计及更高的 ...

  2. 6.Maven聚合和继承,相关案例配置

     1有时候一个项目中有很多个模块,要想各个模块之间影响较小,可以将每个模块拿出来作为一个项目模块,对每个项目模块进行独立的开发. 2在这些过程中会遇到关于聚合和继承的问题. 3何为聚合? A如果我 ...

  3. Maven学习总结(五)——聚合与继承

    2019独角兽企业重金招聘Python工程师标准>>> Maven学习总结(五)--聚合与继承 一.聚合 如果我们想一次构建多个项目模块,那我们就需要对多个项目模块进行聚合 1.1. ...

  4. Maven详解之聚合与继承

    Maven详解之聚合与继承 说到聚合与继承我们都很熟悉,maven同样也具备这样的设计原则,下面我们来看一下Maven的pom如何进行聚合与继承的配置实现. 一.为什么要聚合? 随着技术的飞速发展和各 ...

  5. Maven学习总结(5)——聚合与继承

    2019独角兽企业重金招聘Python工程师标准>>> Maven学习总结(五)--聚合与继承 一.聚合 如果我们想一次构建多个项目模块,那我们就需要对多个项目模块进行聚合 1.1. ...

  6. java继承eclipse_Java-Maven(七):Eclipse中Maven依赖、聚合、继承特性

    之前通过学习了解,maven集成到eclipse中的如何创建项目,以及maven命令插件在eclipse中安装后的用法.那么接下来我们将会学习一些maven在项目中的一些特性,及如何使用. Maven ...

  7. Maven(3)--聚合与继承

    目录 聚合 重点: 继承 注意: 聚合与继承的关系区别 : 共同点 : Maven可继承的POM 元素 依赖管理 import依赖范围 插件管理 约定由于配置 反应堆 反应堆的构建顺序 裁剪反应堆 聚 ...

  8. Maven精选系列--继承与聚合

    转载自 Maven精选系列--继承与聚合 继承 什么是继承,我们可以定义项目的父类项目,用于继承父项目的依赖.插件.属性等信息. <parent> <groupId>com.a ...

  9. maven的聚合和继承详解(2021版)

    前言:日常开发中,两处常见的项目开发场景:多模块项目或者Springboot项目,都会用到Maven的聚合和继承,本篇博客就针对maven这两个技术点进行总结整理,希望能对你有所帮助! 在进入正题之前 ...

最新文章

  1. 腾讯 AI Lab副主任俞栋:过去两年基于深度学习的声学模型进展
  2. POJ1149 PIGS(最大流)
  3. sdut 1479 数据结构实验之栈与队列九:行编辑器
  4. boost::fibers::shared_future的用法实例
  5. Postman接口调试神器
  6. 各种排序算法的C++实现
  7. Linux上的.NET框架Mono 2.0发布
  8. 5月第二周全球五大顶级域名总量新增10.5万个
  9. Linux内核学习篇三:中断处理 -- asm.s和traps.c
  10. 稳健性估计—— M 估计
  11. how-to-solve-the-specific-problem,learn-this,imitate-this
  12. 8086CPU有哪些寄存器组成?各有什么用途?标志寄存器的各标志位在什么情况下置位?
  13. java工具:通过文件头的魔数判断文件类型
  14. testflight怎么做版本更新_苹果更新 TestFlight 3.0 版本:能自动更新内测应用了
  15. zabbix批量自动监控新华三服务器
  16. 详细实现yolov5测试丶自己数据集训练测试丶Tensorrt加速优化(完 结 !)+ 跟踪(补充)
  17. 苹果内购IAP记录-1
  18. python中文模糊关键词提取 flashtext_python关键词匹配利器FlashText
  19. Intel OpenImageDenoise VS Nvidia Optix 降噪结果对比
  20. 《数据挖掘与数据化运营实战:思路、方法、技巧与应用》第一章 什么是数据化运营

热门文章

  1. 唇语识别!AI 领域的下一个万亿市场?
  2. go1.17+中的GOPATH
  3. 微信怎么查计算机成绩查询,如何用微信免费查询自己的成绩?——易查分快速帮您实现...
  4. vscode的中文支持
  5. dir-612b虚拟服务器,D-Link DIR 612B路由器设置上网教程
  6. 查看Linux的核数和内存等相关系统配置
  7. c#中文件路径出现非法字符怎么办?解决也容易
  8. 用python语言写小程序_小程序用什么语言开发?python语言开发可以开发吗?
  9. GNUradio与USRP折腾指南
  10. USRP B210同步采集