maven07-----maven中的聚合与继承

Maven的聚合特性能够把项目的各个模块聚合在一起构建,而Maven的继承特性则能帮助抽取各模块相同的依赖和插件等配置。

一. 聚合

Maven聚合(或者称为多模块),是为了能够使用一条命令就构建多个模块,例如已经有两个模块,分别为account-email,account-persist,我们需要创建一个额外的模块(假设名字为account-aggregator,然后通过该模块,来构建整个项目的所有模块,accout-aggregator本身作为一个Maven项目,它必须有自己的POM,不过作为一个聚合项目,其POM又有特殊的地方,看下面的配置:

<project
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
        http://maven.apache.org/maven-v4_0_0.xsd>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.juvenxu.mvnbook.account</groupId>
        <artifact>account-aggregator</artifact>
        <version>1.0.0-SNAPSHOT</version>
        <packaging>pom</packaging>    //note:要使用聚合的话必须为pom
        <name>Account Aggregator</name>
        <modules>
            <module>account-email</module>
            <module>account-persist</module>
        </modules>
</project>

上面有一个特殊的地方就是packaging,其值为pom,如果没有声明的话,默认为jar,对于聚合模块来说,其打包方式必须为pom,否则无法构建。

modules里的每一个module都可以用来指定一个被聚合模块,这里每个module的值都是一个当前pom的相对位置,本例中account-email、account-persist位于account-aggregator目录下,当三个项目同级的时候,上面的两个module应该分别为../account-email和../account-persist

举例:

(1)创建一个父项目a

(2)创建一个子项目b

点击父项目的pom文件,为他添加model

 

一路next,最终finish

 刷新一下项目a,就可以看见下面有个子项目b

note: 项目a中的除pom.xml文件其它都可以事先删除掉。

同理,再建立一个子项目c

(3)到父模板下面执行mvn clean install

 Reactor Summary:
[INFO]
[INFO] a 0.0.1-SNAPSHOT ................................... SUCCESS [  0.303 s]
[INFO] b .................................................. SUCCESS [  1.893 s]
[INFO] c 0.0.1-SNAPSHOT ................................... SUCCESS [  0.757 s]
[INFO] ------------------------------------------------------------------------

说明:Maven会首先解析聚合模块的pom分析要构建的模块、并计算出一个反应堆构建顺序(Reactor Build Order),然后根据这个顺序依次构建各个模块。上面的红色名字部分正是pom种的name字段的值,因此,配置一个有意义的名字比较好。

二. 继承

2.1 使用说明

 maven中的继承类似于java项目中的继承。

maven中的继承的实现步骤:

  • 建立父工程:父工程的打包方式为pom
  • 在父工程的pom.xml中编写依赖:
<dependencyManagement>   //如果是父工程,需要写dependencyManagement,否则普通工程直接不用写这个
  <dependencies>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
      </dependency>
  </dependencies>
  </dependencyManagement>
  • 子类:在子类中添加parent的配置
<parent>
      <groupId>com.test</groupId>
      <artifactId>base</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <relativePath>../base/pom.xml</relativePath>  //代表的从子类pom.xml到父类pom.xml的相对路径
  </parent>
note: 找相对路径的办法:先找到当前的pom.xml,可以通过alt+enter快捷键定位到计算机中的存储位置(有一个黄色的link可以点击直接跳转到计算机的存储位置)。
然后子pom需要先跳出来,跳到本项目同级别的父项目的位置,假设是base,然后再进入到base里面寻找Pom,因此相对路径就是../base/pom.xml
  • 子类:需要声明,使用哪些父类的依赖

知道了大致的继承创建过程后,下面举一个例子来进一步理解。

2.2 举例

1. 创建父项目base

第一个勾选了允许在创建maven项目的时候就能够修改打包方式。并且,创建以后的东西还可以省去处理pom.xml文件之外的文件。

2. 在父类的pom.xml中添加依赖

<dependencyManagement>  
  <dependencies>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
      </dependency>
  </dependencies>
  </dependencyManagement>

3. 创建子工程,且配置Pom.xml

因为两者的groupId和version一样,因此,无需在子模块中继续声明了。

 <parent>
      <groupId>com.test</groupId>
      <artifactId>base</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <relativePath>../base/pom.xml</relativePath> 
  </parent>
  
  <artifactId>sub</artifactId>
  <packaging>jar</packaging>

  <name>sub</name>
  <url>http://maven.apache.org</url>
note:先保证子类没有junit 4.12版本

4. 刷新子类,发现Junit4.12并没有在maven depenciy下拉菜单中,是因为没有继承么?实际上这是正确的。倘若父类有很多子类没有的东西,那岂不是父类所有的jar包都需要展示在子类的依赖包的下拉菜单中了。那么如何证明继承成功呢?有两个办法:

(1)查看子类的effective pom.xml,其中就包含了从子类继承来的所有jar包。发现是有junit4.12的,只是pom.xml中没有而已。

(2)直接在子类的pom中显示的声明需要依赖junit 4.12的版本,只需要给出groupID和architeID就可以了,会自动从父类中继承4.12版本的。刷新后,就会在maven depency下来菜单中出现了。

2.3 可继承的pom元素

  • groupId:项目组ID,项目坐标的核心元素
  • version:项目版本,项目坐标的核心元素
  • description:项目的描述信息
  • organnization:项目的组织信息
  • inceptionYear:项目的创始年份
  • url:项目的URL地址
  • developers:项目的开发者信息
  • contributors:项目的贡献者信息
  • distributionManagement:项目的部署配置
  • issueManagement:项目的缺陷跟踪系统信息
  • ciManagement:项目的集成信息
  • scm:项目的版本控制系统信息
  • mailingLists:项目的邮件列表信息
  • properties:自定义的Maven属性
  • dependencies:项目的依赖配置
  • dependencyManagement:项目的依赖管理配置
  • repositories:项目的仓库配置
  • build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
  • reporting:包括项目的报告输出目录配置,报告插件配置等。

三. 聚合与继承的关系

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

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

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

在现有的实际项目中,往往会发现一个POM即是聚合POM,又是父POM,这么做主要是为了方便。一般来说,融合使用聚合与继承也没什么问题。

四. 约定优于配置

Maven默认的源码目录是:src/main/java但是用户也可以自己指定源码目录,如下:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.juvenxu.mvnbook<groupId>
    <artifactId>my-project</artifactId>
    <version>1.0</version>
    <build>
        <sourceDirectory>src/java</sourceDirectory>
    </build>
</project>

但是一般还是不要自定义了,不好管理。

五. 反应堆

反应堆的构建顺序

在一个多模块的Maven项目中,反应堆(Reactor)是指所有模块组成的一个构建结构。对于单模块的项目,反应堆就是该模块本身,对于多模块来说,反应堆就包含了各模块之间继承与依赖的关系,从而能够自动计算出合理的模块构建顺序。

例如:

<modules>
    <module>account-email</module>
    <module>account-persist</module>
    <module>account-parent</module>
</modules>

以上,构建顺序不一定是顺序去读取POM的顺序,当一个模块依赖于另外一个模块,Maven会先去构建被依赖模块,并且Maven中不允许出现循环依赖的情况,就是,当出现模块A依赖于B,而B又依赖于A的情况时,Maven就会报错。

裁剪反应堆

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

Maven提供很多命令行选项支持裁剪反应堆,输入mvn -h可以看到这些选项:

  • -am, --also-make:同时构建所列模块的依赖模块
  • -amd -also-make-dependents:同时构建依赖于所列模块的模块
  • -p,--project
  • -rf -resume-from

默认情况从account-aggregator执行mvn clean install会得到如下完整的反应堆:

[INFO]-----------------------------------------------------
[INFO]Reactor Build Order:
[INFO]
[INFO]Account Aggregator
[INFO]Account Parent
[INFO]Account Email
[INFO]Account Persist
[INFO]
[INFO]-----------------------------------------------------

可以使用-pl选项指定构建某几个模块,如运行如下命令:

$ mvn clean install -p account-email,account-persist

得到的反应堆为:

[INFO]-----------------------------------------------------
[INFO]Reactor Build Order:
[INFO]
[INFO]Account Email
[INFO]Account Persist
[INFO]
[INFO]-----------------------------------------------------

六. 补充

多模块的创建涉及到了聚合和继承。也可以通过新建一个maven(simple)工程作为父工程,删除src等东西,只留下Pom.xml,然后点击父项目,右键new-->maven module方式来创建子Module,这样继承和聚合关系就自动生成了。记得刷新一下。

参考文献

《Maven实战》

原文地址:https://www.cnblogs.com/Hermioner/p/10266832.html