聚合

  为了要一次构建多个项目,而不是到每个模块目录下分别执行mvn命令。maven聚合这一特性就是为该需求服务的。为此我们需要创建一个额外的模块aggregator,

然后通过该模块构建整个项目的所有模块。aggregator本身作为一个maven项目,它必须要有自己的POM,不过,同时作为一个聚合项目,其POM有特殊的地方。

  

上述POM使用了共同的groupId,artifactId为独立的aggregator,packaging为POM. 对于聚合模块来说,其打包方式packaging必须为POM,否则就无法构建。

  POM的name字段是为了给项目提供一个更容易阅读的名字,modules是实现聚合的最核心的配置。用户可以通过在一个打包方式为pom的maven项目

中声明任意数量的module元素来实现模块的聚合。这里每个module的值都是一个当前POM的相对目录。

  一般来说为了方便快速定位内容,模块所处的目录名称应该与其artifactId一直,不过这不是maven的要求。

aggreagtor的内容仅仅是一个pom.xml文件,它不像其他模块那样有src/main/java、src/test/等目录。聚合模块仅仅是帮助聚合其他模块的构建工具,它本身无实质内容。

关于目录结构还需要注意的是,聚合模块与其他模块的目录结构并非一定要是父子关系还可以是平行的目录关系。

  

如果使用平行目录结构,聚合模块的POM也需要做相应的修改,以指向正确的模块目录:

  

Maven会首先解析聚合模块的POM、分析要构建的模块、并计算出一个反应堆构建顺序,然后根据这个顺序依次构建各个模块。反应堆是所有模块组成的一个构建结构。

继承

  可以穿件POM的父子结构,然后在父POM中声明一些配置子POM继承,以实现“一处声明,多处使用”的目的。创建一个名为parent的目录,然后在该子目录下建立一个父模块。在该子目录创建一个pom.xml文件,内容如下:

  

该pom使用了与其他模块一致的groupId和version,packaging为pom,与聚合模块一样,作为父模块的POM,其打包类型必须为PM

  父模块只是为了帮助消除配置的重复,将子类的依赖配置配置提取到父模块中。因此它本身不包含除POM之外的项目文件。有了父模块,就需要让其他模块来继承它。

  

  上述POM中使用parent元素声明父模块,parent下的子元素groupId、artifactId和version指定了父模块的坐标,这三个元素是必须的。

这三个元素是必须的。元素relativePath表示父模块POM的相对路径。当项目构建时,maven会首先根据relativePath检查父POM,如果找不到,

再从本地仓库查找。relativePath的默认值是../pom.xml.也就是说,父POM在上一层目录下。

  将parent加入到聚合模块aggregator:

  

  可继承的POM元素

  那些元素POM元素可以继承?

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

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

  description:项目描述信息;

  

依赖管理  

  Maven提供的dependencyManagement元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性。在dependencyManagement元素

下的依赖声明不会引入实际的依赖,不过它能够约束dependencies下的依赖灵活使用。parent中加入这样的dependencyManagement配置:

  

  这里使用dependencyManagement声明的依赖既不会给parent引入依赖,也不会给它的子模块引入依赖,不过这段配置是会被继承的

子模块的POM如下:

  

使用这种依赖管理机制似乎不能减少太多的POM配置,不过还是强烈推荐采用这种方法。其主要原因在于父POM使用dependencyManagement

声明依赖能够统一项目范围中依赖的版本,当依赖版本在父POM中声明之后,子模块在使用依赖的时候就无须声明版本,也就不会发生多个子模块使用依赖版本不一致的情况。

这可以帮助降低依赖冲突的几率。 如果子模块不声明依赖的使用,即使该依赖已经在父POM的dependencyManagement中声明了,也不会产生任何实际的效果。

import依赖范围,只在dependencyManagement元素下才有效果,使用该范围的依赖通常指向一个POM,作用是将目标POM中的dependencyManagement配置

导入并合并到当前的POM的dependencyManagement元素中。

  <dependencyManagement>

    <dependencies>

      <dependency>

        <groupId>com.juvenxu.mvnbook,account</groupId>

        <artifactId>account-parent</artifactId>

        <version>1.0-SNAPSHOT</version>

        <type>pom</type>

        <scope>import</scope>

       </dependency>

    </dependencies>

  </dependencyManagement>

  import依赖范围由于其特殊性,一般都是指向打包类型为pom的模块,如果有多个项目,他们使用的依赖版本都是一致的,则就可以定义一个使用dependencyManagement专门管理依赖的POM,

然后在各个项目中导入这些依赖管理配置。

插件管理

  Maven也提供了pluginManagement元素帮助管理插件。在该元素中配置的依赖不会造成实际的插件调用行为,当POM中配置了真正的plugin元素,并且其groupId和artifactId与

pluginManagement中配置的插件匹配时,pluginManagement的配置才会影响实际的插件行为。

  

  当子模块需要生成源码包的时候,只需要如下的简单配置

  <build>

    <plugins>

      <plugin>

        <groupId>org.apache.plugin</groupId>

        <artifactId>maven-source-plugin</artifactId>

      </plugin>

    </plugins>

  </build>

  子模块声明使用了maven-source-plugin插件,同时又继承了福模块的pluginManagement配置,两者基于groupIdhe artifactId匹配合并之后相当于完整的插件配置。

  如果子模块不需要使用福模块中的pluginManagement配置插件,可以尽管将其忽略。如果子模块需要不同的插件配置,则可以自行配置以覆盖父模块的pluginManagement配置。

  当项目中的多个模块有同样的插件配置时,应该将配置移到父POM的pluginManagement元素中。即使各个模块对于同一插件的具体配置不尽相同,也应当使用父POM的pluginManagement

元素同一声明插件的版本。甚至可以要求将所有用到的插件的版本在父POM的pluginManagement元素中声明,子模块使用插件时不配置版本信息,这么做可以同一项目的插件版本,

避免亲在的插件不一致或者稳定问题,也易于维护。

聚合与集成的关系

  多模块Maven项目中的聚合与继承其实是另两个概念,其目的完全是不同的,前者主要是为了方便快速构建项目,后者主要是为了消除重复配置。

  对于聚合模块来说,他不知道有哪些被聚合的模块,但哪些被聚合的模块不知道这个聚合模块的存在。

  对于继承关系的父POM来说,它不知道有哪些子模块继承于他,但哪些子模块都知道自己的父POM是什么。

  如果非要说这两个特性的共同点,那么可以看到,聚合POM与集成关系中的父POM的packaging都必须是pom,同时,聚合模块与继承关系中的父模块除了POM之外都没有实际的内容。融合使用继承和聚合也没有什么问题。

  

约定由于配置

  Maven提倡“约定优于配置”这是maven最核心的设计理念之一。使用约定可以大量减少配置。遵循约定虽然损失了一定的灵活性,用户不能随意安排目录结构,

但是却能减少配置,更重要的是,遵循约定能够帮助用户转手构建标准。Mavne在生命行暴露的用户接口是统一的想mvn clean install

这样的命令可以用来构建几乎任何的mavne项目。任何一个maven项目都隐式地继承自该POM,因此大量超级POM的配置会被所有maven项目集成,

这些配置也就成为了mavne所提倡的约定。

反应堆

  在多个模块的maven项目中,反应堆是指所有模块组成的一个构建结构。对于单模块的项目,反映堆就是该模块本身,但对于模块项目来说,

反应堆就包含了各模块之间继承与依赖的关系,从而能够自动计算出合理的模块构建顺序。

  反应堆的构建顺序:Maven按序读取pom,如果该POM没有依赖模块,那么久构建该模块,否则就先构建其依赖模块,如果该模块还依赖于其他模块,则进一步先构建依赖的模块。

模块间的依赖关系会讲反映堆构成一个有向非循环图,各个模块是该模块的节点,依赖关系构成有向边,这个图不允许出现循环。

  剪裁反应堆:一般来说,用户会选择构建整个项目或者选择构建单个模块,但有时候,用户会想要仅仅构建完整反应堆中的某些歌模块,换句话说,用户需要实时地剪裁反应堆。

  

  假设aggregator执行 mvn clean install会得完整的反应堆:

  

  使用-pl选项指定构建某几个模块:mvn clean install -pl account-email,account-persist得到反应堆为:

  

  使用-am选项可以同时构建所列模块的依赖模块,例如:mvn clean install -pl account-email -am:

  

  使用-amd选项可以同时构建依赖于所列模块的模块。mvn clean install -pl account-parent -amd

  

  使用-rf 选项可以在完整的反应堆构建顺序基础上制定从哪个模块开始构建,mvn clean install -rf account-email

  

Maven 学习总结(三) 之 依赖管理的更多相关文章

  1. (转)Maven学习总结(三)——使用Maven构建项目

    孤傲苍狼 只为成功找方法,不为失败找借口! Maven学习总结(三)——使用Maven构建项目 maven作为一个高度自动化构建工具,本身提供了构建项目的功能,下面就来体验一下使用maven构建项目的 ...

  2. 【系列教程1】Gradle入门系列三:依赖管理

    在现实生活中,要创造一个没有任何外部依赖的应用程序并非不可能,但也是极具挑战的.这也是为什么依赖管理对于每个软件项目都是至关重要的一部分. 这篇教程主要讲述如何使用Gradle管理我们项目的依赖,我们 ...

  3. Gradle for Android 第三篇( 依赖管理 )

    依赖管理 这会是一个系列,所以如果你还没有看我之前的几篇文章,请先查看以下文章: Gradle for Android 第一篇( 从 Gradle 和 AS 开始 ) Gradle for Andro ...

  4. 【转载】Gradle for Android 第三篇( 依赖管理 )

    依赖管理是Gradle最闪耀的地方,最好的情景是,你仅仅只需添加一行代码在你的build文件,Gradle会自动从远程仓库为你下载相关的jar包,并且保证你能够正确使用它们.Gradle甚至可以为你做 ...

  5. 【转载】Gradle学习 第八章:依赖管理基础

    转载地址:http://ask.android-studio.org/?/article/10 This chapter introduces some of the basics of depend ...

  6. Maven学习(三) -- 仓库

    标签(空格分隔): 学习笔记 坐标和依赖时任何一个构件在Maven世界中的逻辑表示方式:而构件的物理表示方式是文件,Maven通过仓库来同意管理这些文件. 任何一个构件都有其唯一的坐标,根据这个坐标可 ...

  7. Maven学习(三)

    maven相关概念 maven坐标 Maven世界拥有大量构建,当我们需要引用依赖包是,需要用一个用来唯一标识去确定唯一的一个构建.如果拥有了统一规范,就可以把查找工作交给机器. 类似于空间找点的坐标 ...

  8. Maven(六)之依赖管理

    前面讲了maven一些关于Maven的简单知识,今天我给大家分享一些Maven的依赖管理.我相信用过maven的人都知道,它很重要的功能就是通过依赖来添加jar包. 让我们领略一下Maven是怎么管理 ...

  9. Maven学习(三)maven原理概念详述

    maven相关概念 maven坐标 Maven世界拥有大量构建,当我们需要引用依赖包是,需要用一个用来唯一标识去确定唯一的一个构建.如果拥有了统一规范,就可以把查找工作交给机器. 类似于空间找点的坐标 ...

  10. Maven学习笔记—坐标和依赖

    Maven的坐标和依赖 1 Maven坐标 1.1 什么是Maven坐标 Maven坐标:世界上任何一组构件都可以使用Maven坐标来唯一标识,Maven坐标的元素包括groupId.artifact ...

随机推荐

  1. c/c++ linux 进程间通信系列3,使用socketpair,pipe

    linux 进程间通信系列3,使用socketpair,pipe 1,使用socketpair,实现进程间通信,是双向的. 2,使用pipe,实现进程间通信 使用pipe关键点:fd[0]只能用于接收 ...

  2. Serverless架构

    什么是Serverless架构 Servlerless 架构是新兴的架构体系,在Serverless 架构中,开发者无需考虑服务器的问题,计算资源作为服务而不是服务器的概念出现,这样,开发者只需要关注 ...

  3. iOS开发者学习Flutter

    Flutter for iOS 开发者 本文档适用那些希望将现有 iOS 经验应用于 Flutter 的开发者.如果你拥有 iOS 开发基础,那么你可以使用这篇文档开始学习 Flutter 的开发. ...

  4. OKR相关4本书,好书3本

    最近几年看过4本OKR相关的书,有3本是4星.其中第一本是最近看的,剩下3本是2017年看的. OKR源自德鲁克和格鲁夫,跟谷歌是天作之合:4星|<这就是OKR> 4星|<OKR实践 ...

  5. 如何使用U盘安装macOS high Sierra?

    当你不再只是想升级系统的时候,而是想把系统重装,你可能就会用到如标题所说的方式:使用U盘安装mac系统.所以我们需要做以下几件事情,就可以顺利地重装mac系统: 第一步.在App Store下载最新的 ...

  6. supervisor管理php-fpm

    /etc/php-fpm.conf,设置daemonize = no,默认是yes

  7. Vue SSR: 基本用法 (二)

    上一篇讲解了ssr的原理,这篇主要讲基本用法: 1.安装 npm install vue vue-server-renderer --save 我们将在整个指南中使用 NPM,但你也可以使用 Yarn ...

  8. identity server4 证书

    我们需要对token进行签名, 这意味着identity server需要一对public和private key. 幸运的是, 我们可以告诉identity server在程序的运行时候对这项工作进 ...

  9. (十一)Updating Documents

    In addition to being able to index and replace documents, we can also update documents. Note though ...

  10. java list map set array 转换

    1.list转set Set set = new HashSet(new ArrayList()); 2.set转list List list = new ArrayList(new HashSet( ...