likes
comments
collection
share

03.maven聚合和继承

作者站长头像
站长
· 阅读数 7

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继承

如果有很多项目他们依赖相同的配置,那么能不能把这些相同的配置提取出来放到父项目中,这些子项目通过继承可以自动依赖这些功能配置,这就是继承

  1. 创建一个父maven构件,将依赖信息放在pom.xml中
<dependencies>   
        <dependency>依赖的构件的坐标信息</dependency>   
        <dependency>依赖的构件的坐标信息</dependency>    
        <dependency>依赖的构件的坐标信息</dependency>
</dependencies>
  1. 将父构件的package元素的值置为pom
<packaging>pom</packaging>
  1. 在子构件的pom.xml引入父构件的配置:
<parent>    
        <groupId>父构件groupId</groupId> 
        <artifactId>父构件artifactId</artifactId> 
        <version>父构件的版本号</version>  
        <relativePath>父构件pom.xml路径</relativePath>
</parent>

relativePath表示父构件pom.xml相对路径,默认是../pom.xml,所以一般情况下父子结构的maven构件在目录结构上一般也采用父子关系。

relativePath元素

如果父构件和子构件的目录不是父子关系,比如都位于同等级别的目录或者位于更复杂的目录的时候,此时我们需要在子pom.xmlparent元素中使用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,一般都是没有什么内容的。

实际使用是,我们经常将聚合和继承一起使用,能同时使用到两者的优点。

本文参考:www.itsoku.com/course/2/68