《Maven实战》学习总结(六)——多项目构建问题解决方案:聚合和继承

多项目构建问题

       随着软件的发展,软件本身变得越来越复杂,我们往往将一个大项目划分成几个模块来进行开发,如果我们使用Maven进行构建,划分出的各个模块其实也就是多个不同的Maven项目。

在这样的情况下,多模块项目的构建面临两个问题:

       1.划分模块较多时,我们需要分别对每个项目执行构建命令,这样无疑降低了构建的效率;

       2.多项目构建的配置中,有很多公共的配置,比如项目的groupId、version因为存在依赖关系,需要保持一致,很多项目会引入共同的依赖,不利于维护。


为了解决上述两个问题,Maven提供了聚合、继承两个特性。


聚合

       聚合的作用是我们可以通过执行一条命令构建两个或多个项目,该命令执行的项目也应是一个独立的额外项目,其聚合项目的POM配置如下:

    <artifactId>pro-test-aggregator</artifactId>
    <groupId>com.cic</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>pro-test1</module>
        <module>pro-test2</module>
    </modules>


       这样,我们在pro-test-aggregator项目下运行Maven构建命令时,Maven会解析这段配置,计算出反应堆构建顺序(Reactor Build Order):所有模块组成的一个构建结构,按声明顺序构建,遇到有依赖的模块,先构建其依赖的模块,注意要避免项目间的循环依赖,否则会构建出错。

       最后解析出一个有向非循环图的反应堆进行构建,当然我们也可以通过命令行控制构建哪些项目,不构建哪些项目,这个特性叫做裁剪反应堆。

      

继承

       类似于类之间的继承,Maven解决重复配置的特性也叫做继承,通过继承,我们可以实现一处声明,多处引用。现有parent项目定义如下:

    <groupId>com.cic</groupId>
    <artifactId>parent</artifactId>
    <packaging>pom</packaging>
    <name>parent</name>
    <version>1.0-SNAPSHOT</version>


        可见,父项目的生命和其他项目没有太大的不同,只是打包方式和聚合项目类似,同为“pom”。

        子项目如下配置则可实现继承

    <parent>
        <groupId>com.cic</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>pro-test1</artifactId>
    <name>pro-test1</name>

       parent节点配置父项目信息,有一<relativePath>子节点,可定位到父项目的pom.xml,如果没有配置此项,默认为<relativePath>../pom.xml</relativePath>,若没有找到对应文件,则会去本地仓库查找定位。子项目没有声明groupId、version,可默认从父项目继承,若子项目的元素和父项目不同,则完全可以显示声明。

        可继承的POM元素有很多,包含:groupId、version、properties(自定义Maven属性)、dependencies、dependencyManagement、repositories等其他项目信息。值得提及的是所有的项目Pom配置都继承自Maven提供的超级POM,这也更能解释Maven项目在很少的配置下,就能够进行构建。


依赖管理

       我们可以使用dependencies节点统一定义依赖项目,但这里存在一个问题:如果在父项目中通过dependencies定义了依赖后,子项目将继承父项目所有的依赖,也就是说可能引入子项目并不依赖的项目,反而出现了换乱,为解决此问题,我们可以使用<dependencyManagement>节点在父项目中统一定义依赖,子项目在继承父项目后不会直接引入依赖,而是需要再显示的指明一下它所需要继承的依赖。具体配置如下:

       parent项目

<dependencyManagement>
        <dependencies>
            <!-- Common libs -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.bom.version}</version>
                <exclusions>
                    <exclusion>
                        <artifactId>commons-logging</artifactId>
                        <groupId>commons-logging</groupId>
                    </exclusion>
                </exclusions>
            </dependency>

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>${spring.bom.version}</version>
                <type>pom</type>
                <scope>import</scope>
                <exclusions>
                    <exclusion>
                        <artifactId>commons-logging</artifactId>
                        <groupId>commons-logging</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
	</dependencies>
</dependencyManagement>
        子项目配置如下

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
    </dependencies>

       使用此种配置方式,虽然没有减少太多的配置,但可在父项目中统一管理依赖的版本,可在<properties>节点下统一定义各个依赖包的版本。

       细心的读者发现我们在parent项目中引入<spring-framework-bom>项目时的<scope>节点属性配置的是“import”值,其含义表示导入目标依赖中<dependencyManagement>节点的内容,合并到当前项目下,我们可以查看此依赖项目的Pom文件,其定义了Spring项目相关的一系列模块,也因此简化了当前项目的依赖配置。


同理,对应依赖,插件的管理也有类似的配置节点<pluginManagement>,其实现的效果与依赖管理类似,在这里不再赘述。


总结

        本篇文章介绍了Maven中应对多项目问题,提出的聚合与继承两个特性,相信有了这两点的学习,我们在多模块划分、配置的时候能够很好地利用上这两点配置,同时,我们也能侧面的了解到Maven核心设计理念“约定优于配置”的实现机理。

发布了159 篇原创文章 · 获赞 225 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/lyg673770712/article/details/51029719