【问题标题】:How to structure a multi-modules Maven project to compile it at once?如何构建一个多模块 Maven 项目以一次编译它?
【发布时间】:2016-01-27 10:18:08
【问题描述】:

我有一个包含多个模块和子模块的 Maven 项目,我想一次编译它,即只使用一次“mvn clean install”调用。

对于一个基本项目,以下结构可以工作:

.
├── modules
│   ├── moduleA
│   │   └── pom.xml <--- Module A POM
│   ├── moduleB
│   │   └── pom.xml <--- Module B POM
│   └── pom.xml     <--- Super POM (at the root of "modules" folder)
└── pom.xml         <--- Aggregator POM

聚合器是:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.test</groupId>
    <artifactId>aggregator</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0-SNAPSHOT</version>

    <modules>
        <module>modules</module>
        <module>modules/moduleA</module>
        <module>modules/moduleB</module>
    </modules>

</project>

超级 POM:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.test</groupId>
    <artifactId>super-pom</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0-SNAPSHOT</version>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

模块 A 的 POM:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>moduleA</artifactId>

    <parent>
        <groupId>org.test</groupId>
        <artifactId>super-pom</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

</project>

模块 B 类似。

在项目的根目录下,运行“mvn clean install”命令给出(清理 .m2/repository 文件夹后):

[...]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] super-pom .......................................... SUCCESS [  0.450 s]
[INFO] moduleA ............................................ SUCCESS [  1.746 s]
[INFO] moduleB ............................................ SUCCESS [  0.029 s]
[INFO] agregator .......................................... SUCCESS [  0.006 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

现在,如果我想要更复杂的东西(但仍然使用一个超级 POM),例如:

.
├── modules
│   ├── lib1
│   │   ├── moduleA1
│   │   │   └── pom.xml
│   │   ├── moduleB1
│   │   │   └── pom.xml
│   │   └── pom.xml      <--- lib1 aggregator POM
│   ├── lib2
│   │   ├── moduleA2
│   │   │   └── pom.xml
│   │   ├── moduleB2
│   │   │   └── pom.xml
│   │   └── pom.xml      <--- lib2 aggregator POM
│   └── pom.xml          <--- Super POM
└── pom.xml              <--- Aggregator POM

根 POM 为:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.test</groupId>
    <artifactId>agregator</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0-SNAPSHOT</version>

    <modules>
        <module>modules</module>
        <module>modules/lib1</module>
        <module>modules/lib2</module>
    </modules>

</project>

Lib1 POM:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.test</groupId>
    <artifactId>lib1-agregator</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0-SNAPSHOT</version>

    <modules>
        <module>moduleA1</module>
        <module>moduleB1</module>
    </modules>

</project>

并且,例如 moduleA1 POM:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>moduleA1</artifactId>

    <parent>
        <groupId>org.test</groupId>
        <artifactId>super-pom</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

</project>

Maven 无法解析 POM 文件(清理 .m2/repository 文件夹后):

[INFO] Scanning for projects...
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[WARNING] 'parent.relativePath' of POM org.test:moduleA1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleA1/pom.xml) points at org.test:lib1-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleA1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13
[WARNING] 'parent.relativePath' of POM org.test:moduleB1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleB1/pom.xml) points at org.test:lib1-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleB1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13
[WARNING] 'parent.relativePath' of POM org.test:moduleA2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleA2/pom.xml) points at org.test:lib2-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleA2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13
[WARNING] 'parent.relativePath' of POM org.test:moduleB2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleB2/pom.xml) points at org.test:lib2-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleB2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13
 @ 
[ERROR] The build could not read 4 projects -> [Help 1]
[ERROR]   
[ERROR]   The project org.test:moduleA1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleA1/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for org.test:moduleA1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]   
[ERROR]   The project org.test:moduleB1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleB1/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for org.test:moduleB1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]   
[ERROR]   The project org.test:moduleA2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleA2/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for org.test:moduleA2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]   
[ERROR]   The project org.test:moduleB2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleB2/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for org.test:moduleB2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException

我需要先构建超级pom:

cd modules/
mvn clean install

只有这样它才能编译:

[INFO] Reactor Summary:
[INFO] 
[INFO] super-pom .......................................... SUCCESS [  0.271 s]
[INFO] moduleA1 ........................................... SUCCESS [  1.202 s]
[INFO] moduleB1 ........................................... SUCCESS [  0.027 s]
[INFO] lib1-agregator ..................................... SUCCESS [  0.006 s]
[INFO] moduleA2 ........................................... SUCCESS [  0.027 s]
[INFO] moduleB2 ........................................... SUCCESS [  0.022 s]
[INFO] lib2-agregator ..................................... SUCCESS [  0.007 s]
[INFO] agregator .......................................... SUCCESS [  0.007 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

如果没有这个两步编译,您将如何构建项目以使其正常工作?

[编辑]:正如 cmets 中所讨论的,将 Super POM 的 relativePath 添加到模块 POM 将使代码使用一个命令行编译。

但是,如果我只想将 lib1 分发给一些开发人员,即使我的超级 POM 位于 Maven 存储库中,如果没有整个项目结构,lib1 也无法编译。这使得项目的模块化程度降低。

【问题讨论】:

  • Lib1 和 2 必须在您的 parent-pom 中定义为模块?!还是有理由不这样做? Maven 不会在 reactor-build 中包含传递依赖。
  • 这个想法是用一个命令行编译整个项目。这就是我将 lib1 和 lib2 添加到根聚合器的原因。在这个 POM 中直接添加最终模块(例如 modules/lib1/moduleA1)不会改变行为并且 Maven 也无法构建。
  • 您的问题不是关于 reactor build ,而是关于您的 parent-pom。 IMO 您必须编辑所有父 pom 定义以添加 元素。 See Example 2 here.
  • 添加 relativePath 确实有效。但是,当您添加新模块/子模块并且您的结构变得更加复杂时,我发现它很不方便。
  • 没错,但 Eclipse 和 IntelliJ 都有很好的工具来解决这种情况。你必须添加一个 Maven Module

标签: maven maven-3


【解决方案1】:

让我像你一样开始,但我的名字有点不同:

.
├── modules-root
│   ├── moduleA
│   │   └── pom.xml <--- Module A POM
│   ├── moduleB
│   │   └── pom.xml <--- Module B POM
│   └── pom.xml     <--- modules root
└── pom.xml         <--- project-root

让我们从project-root 开始,它看起来像这样:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.test</groupId>
    <artifactId>project-root</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0-SNAPSHOT</version>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <modules>
       <module>modules-root</module>
    </modules>

</project>

module-parent 将如下所示。我要强调的是,这仅包含对moduleAmoduleB 的引用,并且将从project-root继承

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

   <parent>
        <groupId>org.test</groupId>
        <artifactId>project-root</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <groupId>org.test.module</groupId>
    <artifactId>module-parent</artifactId>
    <packaging>pom</packaging>

    <modules>
        <module>moduleA</module>
        <module>moduleB</module>
    </modules>
</project>

moduleA 看起来像这样。请注意,这将继承来自module-parent(父级),这恰好比上一级...

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.test.module</groupId>
        <artifactId>module-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <artifactId>moduleA</artifactId>
    <packaging>..</packaging>

    <....other dependencies..>
</project>

如果您使用这种结构,您可以简单地转到project-root 级别并执行以下操作:

mvn clean install

然后你可以使用这样的东西:

mvn -pl moduleA ...

...只构建模块A(但保持在project-root 级别...)。

module-parent 在此示例中可能看起来像是浪费或多余的,但如果您获得更多模块,您可以通过 dependencyManagement 定义它们的补充依赖项,或者可以通过 pluginManagement 更改插件配置,这将仅用于此子区域(模块A,模块B,...)。如果您的项目变得更大,您将获得更多的module-parents 并行......其中包含应用程序的不同部分......以及可以通过这种结构实现的不同意图。

还有一点要提一下;我已将module-parent 中的groupIdorg.test 更改为org.test.module。如果您有大量模块,这有时会很有用,因为 groupId 代表您的存储库中的文件夹结构(就像 Java 包在 Java 项目中所做的那样)...这可以为您提供更好的概览...

project-root 是通过dependencyManagement 等定义整体可用依赖项的位置。使用的插件应通过pluginManagement... 定义或可能使用maven-enforcer-plugin 定义整体项目规则...

这种结构的典型场景是 Java EE 项目或其他大型项目(可能有 300...或 1000 个模块,是的,它们存在)...

如果您获得更多模块,您可以使用 maven 的多线程功能并通过以下方式构建您的项目:

mvn -T 4 clean install 

来自project-root,这大大减少了构建时间。

【讨论】:

  • 在您的示例中,您在 POM 文件中混合了继承和组合。我认为最好将它们分开在两个不同的 POM 文件中(这是我通常做的)。不是吗?
  • 我在哪里使用合成?我只使用继承......从父母到孩子......不是一次编译的问题吗?这将完全做到这一点......并具有其他优点......单发布点等......
  • 一个POM中的多模块定义是组合。但是您确实有一点:它在一个命令行中编译所有内容。
  • 只想说声谢谢,因为这帮助我轻松设置了我的第一个多模块项目.....
  • 但是为什么 中的 artifactIds 和实际的模块 artifactIds 不匹配呢?例如在你说module-parent 将继承自project-root 的文本中,但是在代码中你有modules-root 继承自super-pom 并且没有定义artifactId super-pom 的项目?!
猜你喜欢
  • 2014-03-03
  • 2014-05-22
  • 2012-07-05
  • 1970-01-01
  • 2016-06-21
  • 2017-09-20
  • 2016-09-24
  • 2012-05-26
  • 1970-01-01
相关资源
最近更新 更多