Maven构建多模块工程

作者: 飞扬小初 | 来源:发表于2017-08-19 12:46 被阅读85次

    除非是简单的工程项目,实际工作中碰到的大部分Maven工程都是多模块的,各个项目模块可以独立开发,其中某些模块又可能会使用到其他的一些模块的功能,如何利用maven来构建一个多模块的工程呢?
    Maven提供了继承和聚合方式用以构建多模块工程,类似于Java中的继承和聚合的概念。

    项目继承结构

    项目继承可以实现在父工程中创建的pom文件内容的复用。子工程可以自动继承到父工程中的pom文件属性。
    比如在父工程的pom文件中定义以下属性:

    <groupId>com.packt.cookbook</groupId>
    <artifactId>project-with-inheritance</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    

    那么在子工程中添加parent定义:

    <parent>
        <groupId>com.packt.cookbook</groupId>
        <artifactId>project-with-inheritance</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>child</artifactId>
    <packaging>jar</packaging>
    <name>Child Project</name>
    

    有了以上的定义,我们就可以在子工程中使用父工程的pom文件中定义的properties和dependencies中的内容了。

    NOTE:

    1. 父工程必须是pom类型的(packaging)
    2. 父工程完全不知道存在子工程,只有子工程中定义的parent元素可以指定父工程

    一般而言父工程都在子工程的上一级目录中,如果父工程不在子工程的上一级目录中,子工程会继续往上在maven仓库中寻找是否有满足要求的父工程。如果需要自己指定父工程的位置,可以新增一个<relativePath>../parent/pom.xml</relativePath>的配置。

    模块聚合结构

    一个父工程可以拥有很多子工程,而父工程无法明确知道其子工程。使用模块聚合可以使得父工程明确管理其子工程,而子工程又可以成为一个个独立的存在,不必明确知道其父工程的存在。
    如何在父工程中定义模块呢?只需要在父工程的pom文件中定义modules元素,为每个子模块新建一个module配置即可。

        <modules>
            <module>admin</module>
        </modules>
    

    这种管理方式虽然简单,但是并不能继承父工程中定义好的properties和依赖,每个子模块都必须独立定义自己的依赖和属性,没有发挥maven项目管理的最大威力。

    继承与聚合结合使用

    如何让maven工程既有继承带来的便利性又有聚合带来的明确性呢?答案就是把这两种特性结合起来,即使用继承,又使用聚合。
    例如,这里让admin模块继承maven项目,同时maven项目又使用modules元素来明确管理admin模块。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>cc.adays</groupId>
        <artifactId>maven</artifactId>
        <packaging>pom</packaging>
        <version>1.0-SNAPSHOT</version>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>2.6</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <addClasspath>true</addClasspath>
                                <mainClass>cc.adays.Main</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
    
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <version>2.9</version>
                    <executions>
                        <execution>
                            <id>copy-dependency</id>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
        <modules>
            <module>admin</module>
        </modules>
    
    </project>
    

    在admin子模块的pom中定义parent元素。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>maven</artifactId>
            <groupId>cc.adays</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>admin</artifactId>
    
    </project>
    

    通过这种方式,admin子元素就可以直接使用父工程中定义的依赖和属性,而父工程maven又可以明确管理其子元素,一举两得。

    多模块工程的依赖管理

    最后一个问题,虽然继承真心很好用,但是有时候子工程并不想拥有父工程的全部依赖,怎么办?此时就必须仰仗dependencyManagement了。通过在父工程中定义dependencyManagement,然后在子模块中选择性地使用父工程中已经定义好的依赖,就非常方便了。
    举个栗子:

        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>4.3.10.RELEASE</version>
                </dependency>
    
                <!-- https://mvnrepository.com/artifact/junit/junit -->
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>4.11</version>
                    <scope>test</scope>
                </dependency>
    
            </dependencies>
        </dependencyManagement>
    

    这里在父工程中定义了两个依赖,一个是spring,一个是Junit,但是我们的子模块中只想使用junit,所以在子模块的pom文件中,定义:

        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </dependency>
        </dependencies>
    
    图片.png

    这里不需要定义version和scope,因为会自动从父工程中继承而来。
    相同的道理,可以使用这种方式管理maven的插件,只需要使用pluginManagement元素,具体的使用方式与依赖的管理方式是一模一样的。

    相关文章

      网友评论

        本文标题:Maven构建多模块工程

        本文链接:https://www.haomeiwen.com/subject/nydtdxtx.html