Maven学习笔记4-聚合与继承

情景引入

现在有一个hello-world项目,其由两个子模块构成,一个是hello-china模块,一个是hello-france模块,在构建这个多模块项目时,如何一次性构建其包含的两个子模块,而不是在两个子模块下分别运行mvn命令尼?当两个模块的pom文件中配置的依赖和插件有很多重复的时候,我们如何减少这种重复尼?为了解决以上问题,我们引入了聚合与继承的概念。

聚合

通过构建聚合模块,能够运行一条命令就能构建聚合模块所包含的所有模块。

配置聚合模块

根据前述情景可以创建出如下目录结构

- hello-world
    - hello-china
    - hello-france
    - pom.xml

其中hello-china与hello-france作为被聚合模块,都是单独的Maven项目,有自己的pom文件和代码。hello-world则作为一个聚合模块被创建出来,它本身作为一个Maven项目,必须有自己的pom文件,不过pom文件的内容用来配置被聚合的模块,如下:

<project>
...
    <groupId>com.maven.hello</groupId>
    <artifactId>hello-world</artifactId>
    <version>1.0-snapshot<version>
    <packaging>pom</packaging>
    <name>Hello World</name>
    <modules>
        <module>hello-china</module>
        <module>hello-france</module>
    </modules>
<project>
  • 其中groupId和version均来自被聚合模块(这些模块应该拥有相同的groupId和version),artifactId则表示聚合模块的名称,值得注意的是其package属性为pom如果是其他值,则无法构建。最重要的元素是module,它配置被聚合模块的目录,每个module的值都是一个当前pom的相对目录。如hello-world的pom文件存放在硬盘目录d:\Code\MavenProject\hello-world\pom.xml,则hello-china则代表目录d:\Code\MavenProject\hello-world\hello-china,hello-france代表目录d:\Code\MavenProject\hello-world\hello-france。这两个目录都自己包含了pom文件和代码,离开聚合模块也能够各自单独构建。

  • 通过观察可以发现,聚合模块仅仅是帮助聚合其他模块构建的工具,除了pom文件并没有其他实质的内容。此外,聚合模块与其他模块的目录关系也不一定是父子关系,也能是平行关系。如此例中

    • hello-world
      • pom.xml
    • hello-china
    • hello-france

    在这种平行目录的聚合关系中,module的值也需要相应更改为../hello-china../hello-france。 配置完成后,在hello-world目录下运行 mvn clean install命令即可一次性构建hello-china和hello-france。

继承

当hello-china与hello-france两个项目中的配置文件包含有大量的重复的时候,如groupId version 依赖与插件配置等,我们可以将这些重复的配置文件提取到一个父模块中,类似于java中的继承机制,以此来消除重复的配置

配置父模块

在上述聚合模块的基础目录结构上,创建如下目录:

- hello-world
    - hello-parent
        - pom.xml
    - hello-china
    - hello-france
    - pom.xml

hello-parent作为hello-china与hello-france的父模块,除了拥有pom文件外,没有其他实质性内容。其pom文件如下所示

<project>
...
    <groupId>com.maven.hello</groupId>
    <artifactId>hello-parent</artifactId>
    <version>1.0-snapshot<version>
    <packaging>pom</packaging>
    <name>Hello Parent</name>
...
<project>

作为父模块,其packaging必须为pom,并拥有自己定义的groupId和version。当hello-china模块继承该父模块时,只需更改目录下的pom文件,如下:

<project>
    ...
    <parent>
        <groupId>com.maven.hello</groupId>
        <artifactId>hello-parent</artifactId>
        <version>1.0-snapshot<version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>hello-china</artifactId>
    ...
</project>
  • 其中parent元素声明父模块,并通过groupId、artifactid、versioin指定父模块的坐标,元素relativePath则表示父模块pom的相对路径,默认为../pom.xml,表示当前目录的父目录(上述pom文件中的此项配置可省略不写)。当构建项目时,Maven会首先在指定的relativePath中查找,若找不到则去本地仓库中查找。

  • 子模块从父模块继承了groupId、artifactid、version等其他配置,如果子模块想使用与父模块中不同的配置,可以在pom文件中显示声明来覆盖父模块中的配置。

  • 将父模块配置完成后,还需将父模块hello-parent整合到聚合模块hello-world中,更改hello-world的pom文件如下:

    <project>
    ...
        <groupId>com.maven.hello</groupId>
        <artifactId>hello-world</artifactId>
        <version>1.0-snapshot<version>
        <packaging>pom</packaging>
        <name>Hello World</name>
    
        <modules>
            <module>hello-parent</module>
            <module>hello-china</module>
            <module>hello-france</module>
        </modules>
    ...
    <project>
    

可继承的pom元素

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

依赖管理

当配置完父模块后,子模块便可以继承父模块中关于依赖的配置,但是如果新添加的子模块中,没有使用到父模块中配置的依赖,难道还是要继承父模块中的依赖吗?这显然是不合理的,因此Maven提供了dependencyManagement元素,它既能让子模块继承到父模块的依赖配置,也能保持子模块的灵活性

dependencyManagement元素下的依赖声明不会引入实际的依赖,但是它能约束dependency下的依赖使用。例如在hello-parent的pom文件中加入如下dependencyManagement配置。

<project>
...
    <name>hello-parent</name>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.8</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
...
</project>

这里配置的依赖并不会给hello-parent引入实际的依赖,也不会给其子模块引入依赖,但是这段配置依然会被继承。现修改子模块hello-china的pom文件如下:

<project>
    ...
    <parent>
        <groupId>com.maven.hello</groupId>
        <artifactId>hello-parent</artifactId>
        <version>1.0-snapshot<version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>hello-china</artifactId>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
    ...
</project>
  • 子模块只需配置依赖的groupId和artifactId,就能引入正确的依赖,完整的依赖声明包含在父pom中。由于依赖的版本信息存储在父pom中,这样能保证所有子模块引用的依赖版本一致,减少冲突。

  • 子模块也可以不声明依赖的使用,这样即使父pom中已经配置了dependencyManagement,也不会对子模块产生实际效果。

  • 使用import导入依赖管理。若新建项目想使用与hello-parent相同的依赖管理配置,除了复制和继承外,还能够通过import元素来导入依赖管理。只需在新项目的pom文件中加入如下配置:

    <dependencyManagement>
     <dependencies>
        <dependency>
            <groupId>com.maven.hello</groupId>
            <artifactId>hello-parent</artifactId>
            <version>1.0-snapshot<version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
    </dependencyManagement>
    

插件管理

与依赖管理的思想相同,Maven通过pluginManagement元素在父pom中配置插件,配置部分如下:

<build>
<pluginManagement>
    <plugins>
        <plugin>...</plugin>
    </plugins>
</pluginManagement>
</build>

当子模块需要使用该插件配置时,只需在插件配置部分声明该插件的groupId和artifactId。

聚合与继承的关系

  • 聚合模块能够知道被聚合模块的存在,而被聚合模块不知道聚合模块的存在
  • 继承关系中的父模块不知道子模块的存在,子模块则都必须知道父模块的存在。
  • 两者的pom文件中packaging元素都必须是pom,且除了pom文件都没有其他实质性内容

通常,也可以将聚合模块与父模块合并。如本文中所述hello-world与hello-parent模块合并后,目录结构如下

- hello-world
    - hello-china
    - hello-france
    - pom.xml

其中pom文件合并为:

<project>
...
    <groupId>com.maven.hello</groupId>
    <artifactId>hello-world</artifactId>
    <version>1.0-snapshot<version>
    <packaging>pom</packaging>
    <name>Hello World</name>
    <modules>
        <module>hello-china</module>
        <module>hello-france</module>
    </modules>

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

<project>

小结

本文介绍了Maven项目中聚合的基本用法,详细介绍了继承关系中依赖和插件的配置,最后对聚合和继承的特点进行了简要的比较。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值