【maven】聚合和继承

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010900754/article/details/82193965

在实际使用maven构建项目的时候,可能会遇到下面的问题:

一个项目包含了很多的模块,这些模块每一个都是一个独立的mvn项目,那么一次构建必须分别为每一个模块运行mvn的命令,有没有办法只运行一个命令就把这些模块全部打包?

有,使用聚合maven。

我们需要新建一个聚合的maven项目,这个项目本身没有任何业务的逻辑,只是单纯负责打包其他模块的。下面是一个例子:

假设项目里现在有data模块和service模块。那么现在新建一个聚合的模块:app-aggregator

aggregator的pom与其他只有两个区别,一是package类型为pom,而是用modules标签包含了要打包的模块:

<?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>com.liyao</groupId>
    <artifactId>app-aggregator</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>data</module>
        <module>service</module>
    </modules>
</project>

这里的data和service模块就是普通的maven项目,就不贴了,目录在aggregator下。

这样我们只需要运行aggregator的mvn命令就可以打包里面的模块了。

运行:mvn clean install

可以看到,总共打包了三个jar文件,包括了aggregator项目。

在其他项目中想要引入子模块的jar包,还必须使用子模块的坐标,使用aggregator无法引入子模块的依赖。可以看到,这个aggragator的作用仅仅是为了打包子模块。

使用聚合可以新建一个项目来统一打包子模块,解决了开始提到的问题。

但是实际中还会有另一个问题,子模块之间往往会有很多共性的配置,比如spring相关的jar等,这些相同的配置如果要在每一个子模块里都配置一次,无疑很麻烦,而且新加入的模块也不利于扩展,有很多冗余配置。

这个问题可以通过继承解决。当然我们还是需要新建一个mvn项目作为父项目。

新建ap-parent项目,位于aggregator目录下,与子模块平级。

<?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>com.liyao</groupId>
    <artifactId>ap-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

</project>

其pom除了必须制定package为pom以外,没有不同。

现在的目录:

app-aggregator

      |-ap-parent

      |-data

      |-service

在aggregator里添加ap-parent项目。修改data和service子模块的pom:

<?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>
        <groupId>com.liyao</groupId>
        <artifactId>ap-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../ap-parent/pom.xml</relativePath>
    </parent>

    <artifactId>data</artifactId>
    <version>1.0</version>

    <modelVersion>4.0.0</modelVersion>

</project>

service类似。

这里使用parent标签指定了父pom的坐标。其中的relativePath制定了父pom的物理位置,默认是../pom.xml。但是这里因为是平级的,所以需要重新定义。然后再指定子模块的名字和版本。

这样子模块就可以继承父模块的配置了。

可以继承的配置有:

那么这里重点说下dependecyManagement相关的。以下简称dp。

我们当然会想把公共的依赖放入父pom中,这样我们可以使用dependences标签把公共依赖加入到父pom中。但是有一个问题,万一有一个子模块继承了父pom,但是想要继承里面一部分配置而不是全部呢?

这就需要使用dp标签了。dp与dependences的区别在于,父pom中的dependences定义的依赖,子模块是一定会引入的。但是dp的依赖则不会,除非在子模块中使用dependences定义相同的依赖。所以dp引不引入,并不是父pom说了算,还是需要在子模块定义dependences。这不是多此一举吗?所以这里的dp仅仅是提供配置的公共模板,比如版本,这样有利于管理子模块引入的公共依赖的版本。但是最后引不引入还是看子模块。如果子模块没有定义dependences,那么就不引入。如果定义了dependences没有定义version就是用父pom的dp里定义的version,如果指定了version,就是用子模块的version。

看例子:

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8</version>
        </dependency>
    </dependencies>

在父pom里加入了上述依赖,子模块没有定义,但是子模块中可以使用junit,说明确实是直接继承了父pom的dependences。

import org.junit.Before;

public class Dao {
    @Before
    public void read(){
        System.out.println("read");
    }

}

接着把pom中修改一下:
 

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.8</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

子模块不变,之前的junit就无法使用了:

然后再在子模块中加入dependences,且不指定version

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>

junit又可以使用了。且版本与父pom一致。

然后再指定一下版本:

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

可以看到子模块的junit就是新指定的4.12了。

所以,dp与dependences的区别就搞清楚了。dp只提供默认版本,不会引入。类似的还有pluginManagement。

实际中,通常会把聚合与继承的项目搞成一个,作为一个目录。

还有一个问题,对于聚合pom,有一个反应堆的概念。就是modules里的模块,如果有依赖关系,那么构建时必须按照依赖的顺序来构建,如果没有依赖则直接构建。maven会把所有的模块放入一个反应堆中,然后分析堆里的模块的依赖关系。所以最终的构建顺序是:按序扫描,如果没有依赖就直接构建,否则就递归先构建依赖。

猜你喜欢

转载自blog.csdn.net/u010900754/article/details/82193965