首页 > 其他分享 >Maven:聚合与继承

Maven:聚合与继承

时间:2022-10-17 21:59:52浏览次数:73  
标签:聚合 项目 继承 Maven manager POM 构建 模块

转自:https://zhuanlan.zhihu.com/p/139793065

Maven不仅支持单模块项目同时还支持多模块项目,这里将介绍在多模块Maven项目中广泛应用的聚合、继承等概念,并就如何通过裁剪反应堆来加快构建过程进行介绍

聚合

对于复杂的Maven项目,一般建议采用多模块的方式来设计开发,便于后期维护管理。但是构建项目时,如果每次都需要按模块一个一个进行构建会十分麻烦,而Maven的聚合功能就可以很好的解决这个问题,当用户对聚合模块执行构建任务时,会对所有被其聚合的模块自动地依次进行构建任务

这里通过一个实例进行介绍,在manager模块中有 manager-mapper、manager-service、manager-controller、manager-pojo 四个模块,为了避免依次构建这四个模块,我们这里添加了一个新的模块manager用于将这四个模块聚合在一起,通常我们称manager为聚合模块。从下图实例我们可以看出,聚合模块不包含任何源码,其只有一个POM文件。因为该模块的作用只是为了聚合其他模块方便我们一次性构建其下的所有模块,所以其POM文件的内容与一般的POM文件有所差别。首先,将打包方式packaging元素设置为pom,然后通过modules下的module子元素来添加该聚合模块需要聚合的模块的目录路径

 

现在,我们在聚合模块manager下执行构建任务,即可看到其所聚合的四个聚合将会全部执行,大大方便我们构建项目

实例中,聚合模块和被聚合模块之间的目录结构是父子目录结构,实际上其还可以是平行目录结构,如下图所示

但如果使用平行目录结构下,聚合模块的POM文件中的被聚合模块的目录路径需要进行修改,因为module元素的值是基于当前POM文件的相对目录

    <modules>
        <module>../manager-mapper</module>
        <module>../manager-service</module>
        <module>../manager-controller</module>
        <module>../manager-pojo</module>
    </modules>

继承

概述

在一个多模块的项目中,对于同一个依赖的依赖声明要在多个模块的POM都进行声明,会导致有大量重复的依赖声明。所以Maven在设计之时,借鉴了面向对象中的继承思想,可在父模块的POM中声明依赖,子模块的POM文件可通过继承父模块的POM来获得对相关依赖的声明。对于父模块而言,其目的是为了消除子模块的POM文件的重复配置,其不含有任何实际的项目代码,所以父模块POM文件的packaging元素同样需要设置为pom,如下所示

而在子模块的POM文件中,通过parent元素声明对父模块的POM文件的继承,parent元素中的relativePath子元素用来指明父模块POM的路径,该值默认值为../pom.xml。其值同样是一个是基于当前POM文件的相对路径。所以对于使用父子目录结构的实例的api模块而言,该元素值可省略不用显式指定,使用默认值即可

而如果使用平行目录结构,则在api模块的POM中的relativePath元素应配置为../springBoot2-root/pom.xml

Maven可通过继承获得POM元素,列表如下:

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

Note :

在子模块POM文件的parent元素中声明父模块的版本时,建议引用父模块的属性,而不要直接在各个子模块写父模块的版本号。以避免父模块版本号变动后,在对各个子模块的POM进行更新时因遗漏而出现错误。有时候,在IntelliJ IDEA中会报错: parent元素中不可引用属性,只需在父模块中用revision属性名定义其版本号即可消除报错

    ...
    <properties>
        ...
        <revision>1.0</revision>
        ...
    </properties>
    ...

dependency Management 依赖管理

由上文可知,子模块可通过继承获得父模块中声明的dependencies元素——即全部依赖,这样虽然避免了在各个子模块POM中重复写依赖声明,但是这样也会造成另外一个问题——会导致子模块中引入了不必要的依赖。显然这个也不是我们期望的,为此Maven引入了dependencyManagement来对依赖进行管理。该元素下的依赖声明不会实际引入到模块中,只有在dependencies元素下同样声明了该依赖,才会引入到当前模块中。dependencies声明的依赖若未指定版本号,将使用dependencyManagement中该依赖指定的版本;否则,将覆盖dependencyManagement中该依赖指定的版本

所以较好的实践是,我们在父模块POM中通过dependencyManagement元素声明子模块需要使用的依赖及其版本。由于dependencyManagement元素同样可被继承。故我们在各个子模块POM的dependencies元素下声明实际需要用到的依赖。这样看上去虽然不能减少子模块的POM配置。但是其一方面可以在父模块的POM中统一管理子模块用到的依赖的版本(更进一步地,dependencyManagement中元素的版本亦支持引用属性),另一方面也不至于将不必要的依赖引入到模块中

plugin Management 插件管理

对于插件而言,如果在每个子模块中分别声明插件版本及插件配置,会显得十分繁琐。为此Maven针对插件的管理提供了pluginManagement元素,其和dependencyManagement元素基本原理一致,在pluginManagement元素声明的插件及插件配置不会发生实际效果,只有当继承该POM的子模块声明了相应插件才会被实际引入,同时默认使用pluginManagement中该插件的版本及插件配置。如果某个子模块需要不同的版本及配置,则可在该子模块中显式指定以覆盖父模块POM的pluginManagement配置

下图实例中,在父POM的pluginManagement元素中声明maven-source-plugin插件并配置对模块源码进行打包的任务,子模块manager-service需要对其源码进行打包,则直接在其POM中声明该插件即可

 

聚合与继承的关系

从上文我们知道,Maven的聚合和继承是两个完全不同的概念。前者是为了快速方便地构建项目中的多个模块;后者则是为了消除POM中的重复配置。对于聚合模块来说,它知道有哪些模块被聚合,但那些被聚合的模块则不知道这个聚合模块的存在;对于父模块来说,它不知道有哪些子模块继承它,但那些子模块则必须知道其继承是哪个模块

当然,从形式上来说,聚合模块、父模块也是有一些共同点的,首先,这两种模块POM的打包类型(packaging)均为pom;其次,这种模块中除了POM文件外,均不含项目任何的实际源码。鉴于此,项目开发中,为了方便起见,一个模块是父模块的同时也可是聚合模块。但是作为开发人员,我们应该清楚这两者之间其实并无任何实际内在联系

import 依赖范围

我们在一个新的项目/模块中,如果期望复用其他POM中dependencyManagement元素的配置,我们可以通过继承或拷贝该配置实现,实际上,还有第三种办法,通过 import 将目标POM的dependencyManagement配置导入、合并到当前POM的dependencyManagement元素中,因为maven只支持单继承,如果当前项目已经继承了一个父模块,此时即可通过import导入的方式来复用其他POM中的dependencyManagement配置。需要注意的是,由于import依赖范围的特殊性,其一般指向的是打包类型为pom的模块。故其type只能为pom

    <dependencyManagement>
        <dependencies>
            ...
            <dependency>
                <groupId>com.tony</groupId>
                <artifactId>json</artifactId>
                <version>1.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            ...
        </dependencies>
    </dependencyManagement>

Reactor 反应堆

概述

在一个多模块的Maven项目中,反应堆Reactor是指所有模块组成的一个构建结构。对于单模块的项目来说,反应堆就是该模块本身;而对于多模块的项目来说,反应堆可以反映各模块之间的继承与依赖关系,从而能够计算出合理的模块构建顺序。下图是本文实例的组织架构图与依赖关系图

可以看到该项目是一个基于多模块的Maven项目,其中SpringBoot2模块为父模块(同时也是聚合模块),其下有2个模块,分别是api模块(项目启动入口)和manager模块;而对于manager模块而言,其一方面是SpringBoot2的子模块,另一方面又是 manager-mapper、manager-service、manager-controller、manager-pojo 四个模块的父模块、聚合模块。该项目中模块的依赖关系如上图左侧所示

当我们构建该项目时,从命令行的结果输出可以看到,其首先会根据模块的相互之间的关系计算出项目的Reactor Build Order反应堆构建顺序,然后按反应堆的构建顺序依次构建相关模块。观察反应堆可以看到,其可以保证如果模块B依赖于模块A,则模块A肯定先于模块B完成构建

裁剪反应堆

大多数时候,用户都是一次性构建整个项目,但有些时候用户可能仅仅需要构建某个模块,即用户需要裁剪反应堆来实现构建指定模块的目的。在Maven命令行中可通过相关选项参数实现反应堆的裁剪

1. 构建指定模块

mvn -pl, --projects <arg> # 构建指定模块,多个模块用逗号进行分隔

2. 同时构建所列模块的依赖模块

mvn -am, --also-make # 同时构建所列模块的依赖模块

3. 同时构建依赖于所列模块的模块

mvn -amd, -also-make-dependents # 同时构建依赖于所列模块的模块

4. 从指定模块开始构建

mvn -rf, -resume-from <arg> # 从指定模块开始构建

还可在-pl -am、-pl -amd 的基础上,进一步使用-rf参数,来对裁剪后的反应堆再次裁剪

 

标签:聚合,项目,继承,Maven,manager,POM,构建,模块
From: https://www.cnblogs.com/fnlingnzb-learner/p/16800828.html

相关文章

  • 在python中如何实现类的继承,方法重载及重写?(原来继承这么简单-附完整代码详解)
    ......
  • maven搭建多模块springboot项目微服务
    maven搭建多模块springboot项目微服务目录1.模块化概念2.搭建模块2.1创建父项目2.1.1创建新项目2.2添加子模块2.3修改父项目pom依赖2.3.1 父项目pom依赖说......
  • Flink-基于Table的窗口、聚合操作
    我们知道,窗口可以将无界流切割成大小有限的“桶”(bucket)来做计算,通过截取有限数据集来处理无限的流数据。在DataStream API中提供了对不同类型的窗口进行定义和处理的接......
  • [idea中配置maven]
    前言:加入项目中,采用idea环境开发,在这个过程中,对maven项目的了解又深入了很多,学习是一个不断深入的过程,在这个过程中,不断成长,本篇博客记录idea配置maven,从环境变量......
  • 07.聚合函数
    聚合函数sql中主要聚合函数有count求数量max求最大值min求最小值sum求和avg求平均值--求员工总人数selectcount(*)总人数fromPeople--求......
  • maven 无法下载插件
    起因本次文章记录一下前段时间来公司按照Jenkins遇到的一个坑。maven安装完成后无法下载插件。解决这次的问题百度之后,都说是插件下载的链接是不对的,都是重复的解决方式,实在......
  • Eclipse插件开发MavenArchetype
    介绍用过Maven的童鞋,可能会听说过archetype(骨架)。而在Eclipse中利用m2e插件提供的骨架来新建Maven工程的话,是需要手动来配置的。而如果每次手动添加骨架会很麻烦,如果能像Ecl......
  • maven——依赖范围scope
    依赖范围scope:依赖范围,使用scope值表示:scope的值有:compile,test,providedscope表示依赖使用的范围:就是在maven构建项目的那些阶段起作用;maven构建项目的生命周期:清理,编译......
  • maven——在idea中导入依赖(dependency)无法识别!
    在idea中导入一个已经存在的maven项目,在打开pom.xml文件,输入依赖时报错:导入denpendency时idea没有及时识别出来,爆红!   解决办法:鼠标选中pom文件——右击选择maven......
  • maven resource 覆盖配置使用
    mavenresource插件可以对于resource进行处理,比如合并,copy,有一种比较常见的用法是进行覆盖比如我们基于配置插件,在resource阶段将依赖其他配置中心或者repo的配置文件......