03.maven聚合和继承
Maven聚合
maven聚合需要创建一个新的maven项目, 用来管理其他的maven构件模块,新的maven项目中加入如下配置:
<modules>
<module>模块1</module>
<module>模块2</module>
<module>模块n</module>
</modules>
<package>pom</package>
新的项目中执行任何mvn
命令,都会modules
中包含的所有模块执行同样的命令,而被包含的模块不需要做任何特殊的配置,正常的maven项目就行。
注意上面的module
元素,这部分是被聚合的模块pom.xml
所在目录的相对路径。
package
的值必须为pom
pom.xml中的module
元素的值为被聚合的模块pom.xml所在的目录路径,只能是相对路径,比如下面这样:
<modules>
<module>zipkin-server-source-demo</module>
<module>../../../tmp/child-project</module>
<module>../../../tmp/child-project/pom.xml</module>
</modules>
聚合的功能中,聚合模块的pom.xml中通过modules->module
来引用被聚合的模块,被聚合的模块是不用感知自己被聚合了,所以被聚合的模块中pom.xml
中是不知道父模块的存在的。
maven继承
如果有很多项目他们依赖相同的配置,那么能不能把这些相同的配置提取出来放到父项目中,这些子项目通过继承可以自动依赖这些功能配置,这就是继承
。
- 创建一个父maven构件,将依赖信息放在pom.xml中
<dependencies>
<dependency>依赖的构件的坐标信息</dependency>
<dependency>依赖的构件的坐标信息</dependency>
<dependency>依赖的构件的坐标信息</dependency>
</dependencies>
- 将父构件的package元素的值置为pom
<packaging>pom</packaging>
- 在子构件的pom.xml引入父构件的配置:
<parent>
<groupId>父构件groupId</groupId>
<artifactId>父构件artifactId</artifactId>
<version>父构件的版本号</version>
<relativePath>父构件pom.xml路径</relativePath>
</parent>
relativePath
表示父构件pom.xml相对路径,默认是../pom.xml
,所以一般情况下父子结构的maven构件在目录结构上一般也采用父子关系。
relativePath元素
如果父构件和子构件的目录不是父子关系,比如都位于同等级别的目录或者位于更复杂的目录的时候,此时我们需要在子pom.xml
的parent
元素中使用relativePath
元素来指定父pom.xml
相对路径位置,这个值默认是../pom.xml
,表示父pom.xml位于子pom.xml的上一级目录。
正确的设置relativePath
是非常重要的,这个需要注意,子模块中执行mvn
命令的时候,会去找父pom.xml
的配置,会先通过relativePath
指定的路径去找,如果找不到,会尝试通过坐标在本地仓库进行查找,如果本地找不到,会去远程仓库找,如果远程仓库也没有,会报错。
可以通过继承的元素有以下这些
可以从父pom.xml
中继承过来的的元素:
- groupId:项目组ID,项目坐标的核心元素
- version:项目版本,项目坐标的核心元素
- description:项目的描述信息
- organization:项目的组织信息
- inceptionYear:项目的创始年份
- url:项目的url地址
- developers:项目的开发者信息
- contributors:项目的贡献者信息
- distributionManagement:项目的部署配置信息
- issueManagement:项目的缺陷跟踪系统信息
- ciManagement:项目的持续集成系统信息
- scm:项目的版本控制系统信息
- mailingLists:项目的邮件列表信息
- properties:自定义的maven属性配置信息
- dependencyManagement:项目的依赖管理配置
- repositories:项目的仓库配置
- build:包括项目的源码目录配置、输出目录配置、插件管理配置等信息
- reporting:包括项目的报告输出目录配置、报告插件配置等信息
依赖管理(dependencyManagement)
maven提供的dependencyManagement元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性,在dependencyManagement
元素下声明的依赖不会引入实际的依赖,他只是声明了这些依赖,不过它可以对dependencies
中使用的依赖起到一些约束作用。
子模块如果想用到父模块dependencyManagement
中的配置,可以dependencies
进行引用,引用之后,依赖才会真正的起效。我们可以使用mvn dependency:tree
验证
dependencyManagement不会引入实际的依赖,只有在子类中使用dependency
来引入父dependencyManagement
声明的依赖之后,依赖的构建才会被真正的引入。
使用dependencyManagement来解决继承的问题,子pom.xml中只用写groupId,artifactId
就可以了,其他信息都会从父dependencyManagement
中声明的依赖关系中传递过来,通常我们使用这种方式将所有依赖的构建在父pom.xml中定义好,子构件中只需要通过groupId,artifactId
就可以引入依赖的构建,而不需要写version
,可以很好的确保多个子项目中依赖构件的版本的一致性,对应依赖构件版本的升级也非常方便,只需要在父pom.xml中修改一下就可以了。
单继承问题解决
如果一个项目X的父项目是P,但是X又想使用另外一个项目Z中dependencyManagement
中声明的依赖,此时该咋办?这个就是单继承的问题
解决办法:在项目X中增加以下配置,然后项目X就可以使用项目Z中dependencyManagement
声明的依赖了。
<!-- 下面的配置相当于把项目Z的pom.xml中的dependencyManagement元素中声明的所有依赖导入到当前pom.xml的dependencyManagement中 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>项目Z</groupId>
<artifactId>项目Z</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- type的值必须是pom,scope元素的值必须是import -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
上的配置相当于把项目Z的pom.xml中的dependencyManagement元素中声明的所有依赖导入到当前pom.xml的dependencyManagement中
插件管理(pluginManagement)
maven中提供了解决插件继承问题的pluginManagement
元素,在父pom中可以在这个元素中声明插件的配置信息,但是子pom.xml中不会引入此插件的配置信息,只有在子pom.xml中使用plugins->plugin
元素正在引入这些声明的插件的时候,插件才会起效,子插件中只需要写groupId、artifactId
,其他信息都可以从父构件中传递过来。
比如我在父项目pom.xml中声明以下插件配置:
<build>
<pluginManagement>
<plugins>
<plugin>
<!--在default生命周期的verify阶段执行jar-no-fork目标-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-source</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
在子项目中使用如下:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<!--如果没有executions,那就会完全引用父插件中的配置,
如果有executions,那么就会合并父插件中的配置
可以使用mvn help:effective-pom验证最终的pom.xml
-->
<executions>
<execution>
<id>attach-source</id>
<goals>
<goal>help</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
我们可以通过mvn help:effective-pom
查看子项目生成的最终的pom.xml文件是咋样的来验证插件管理是否生效
聚合与继承的关系
- 聚合:主要是为了方便多模块快速构建。对于聚合来说,聚合模块是知道被聚合模块的存在的,而被聚合模块是感知不到聚合模块的存在。
- 继承:主要是为了重用相同的配置。对于继承来说,父构件是感知不到子构件的存在,而子构件需要使用
parent
来引用父构件。
两者的共同点是,聚合模块和继承中的父模块的package属性都必须是pom类型的,同时,聚合模块和父模块中的除了pom.xml,一般都是没有什么内容的。
实际使用是,我们经常将聚合和继承一起使用,能同时使用到两者的优点。
转载自:https://juejin.cn/post/7359083767564091407