通常来说,在Maven的多模块工程中,都存在一个pom类型的工程作为根模块,该工程只包含一个pom.xml文件,在该文件中以模块(module)的形式声明它所包含的子模块,即多模块工程。在子模块的pom.xml文件中,又以parent的形式声明其所属的父模块,即继承。然而,这两种声明并不必同时存在,我们将在下文中讲到这其中的区别。
(一)创建Maven多模块工程
多模块的好处是你只需在根模块中执行Maven命令,Maven会分别在各个子模块中执行该命令,执行顺序通过Maven的Reactor机制决定。先来看创建Maven多模块工程的常规方法。在我们的示例工程中,存在一个父工程,它包含了两个子工程(模块),一个core模块,一个webapp模块,webapp模块依赖于core模块。这是一种很常见的工程划分方式,即core模块中包含了某个领域的核心业务逻辑,webapp模块通过调用core模块中服务类来创建前端网站。这样将核心业务逻辑和前端展现分离开来,如果之后决定开发另一套桌面应用程序,那么core模块是可以重用在桌面程序中。
首先通过Maven的Archetype插件创建一个父工程,即一个pom类型的Maven工程,其中只包含一个pom.xml文件:
mvn archetype:generate -DgroupId=me.davenkin -DartifactId=maven-multi-module -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=pom-root -DinteractiveMode=false
以上命令在当前目录下创建了一个名为maven-multi-module的目录,该目录便表示这个pom类型的父工程,在该目录只有一个pom.xml文件:
<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>me.davenkin</groupId>
<artifactId>maven-multi-module</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>maven-multi-module</name>
</project>
这个pom.xml非常简单,最值得一看的是其中的“<packaging>pom</packaging>”,表示该工程为pom类型。其他的Maven工程类型还有jar、war、ear等。
此时,父工程便创建好了,接下来我们创建core模块,由于core模块属于maven-multi-module模块,我们将工作目录切换到maven-multi-module目录下(当然你也可以不用,只是需要一些额外的配置),创建core模块命令如下:
mvn archetype:generate -DgroupId=me.davenkin -DartifactId=core -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
这里我们使用了Archetype插件的maven-archetype-quickstart,它创建一个jar类型的模块。此时,如果我们在打开maven-multi-module模块的pom.xml会发现,其中多了以下内容:
<modules>
<module>core</module>
</modules>
这里的core即是我们刚才创建的core模块,再看看core模块中的pom.xml文件:
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>maven-multi-module</artifactId>
<groupId>me.davenkin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>me.davenkin</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
<name>core</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
请注意里面的 “<parent>... </parent>”,它将maven-multi-module模块做为了自己的父模块。这里我们看出,当创建core模块时,Maven将自动识别出已经存在的maven-multi-module父模块,然后分别创建两个方向的指引关系,即在maven-multi-module模块中将core作为自己的子模块,在core模块中将maven-multi-module作为自己的父模块。要使Maven有这样的自动识别功能,我们需要在maven-multi-module目录下创建core模块(请参考前文),不然,core模块将是一个独立的模块,但是我们可以通过手动修改两个模块中的pom.xml文件来创建他们之间的父子关系,从而达到同样的目的。
依然在maven-multi-module目录下,通过与core相同的方法创建webapp模块:
mvn archetype:generate -DgroupId=me.davenkin -DartifactId=webapp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
这里的maven-archetype-webapp表明Maven创建的是一个war类型的工程模块。此时再看maven-multi-module模块的pom.xml文件,其中的<modules>中多了一个webapp模块:
<modules>
<module>core</module>
<module>webapp</module>
</modules>
而在webapp模块的pom.xml文件中,也以 “<parent>... </parent>”的方式将maven-multi-module模块声明为自己的父模块,这些同样是得益于Maven自动识别的结果。
此时,在maven-multi-module目录下,我们执行以下命令完成整个工程的编译、打包和安装到本地Maven Repository的过程:
mvn clean install
(二)手动添加子模块之间的依赖关系
此时我们虽然创建了一个多模块的Maven工程,但是有两个问题我们依然没有解决:
(1)没有发挥Maven父模块的真正作用
(2)webapp模块对core模块的依赖关系尚未建立
针对(1),Maven父模块的作用本来是使子模块可以继承并覆盖父模块中的配置,比如dependency等,但是如果我们看看webapp和core模块中pom.xml文件,他们都声明了对Junit的依赖,而如果多个子模块都依赖于相同的类库,我们应该将这些依赖配置在父模块中,继承自父模块的子模块将自动获得这些依赖。所以接下来我们要做的便是:将webapp和core模块对junit的依赖删除,并将其迁移到父模块中。
对于(2),Maven在创建webapp模块时并不知道webapp依赖于core,所以这种依赖关系需要我们手动加入,在webapp模块的pom.xml中加入对core模块的依赖:
<dependency>
<groupId>me.davenkin</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
此时再在maven-multi-module目录下执行 “mvn clean install”,Maven将根据自己的Reactor机制决定哪个模块应该先执行,哪个模块应该后执行。比如,这里的webapp模块依赖于core模块,那么Maven会先在core模块上执行“mvn clean install”,再在webapp模块上执行相同的命令。在webapp上执行“mvn clean install”时,由于core模块已经被安装到了本地的Repository中,webapp便可以顺利地找到所依赖的core模块。
总的来看,此时命令的执行顺序为maven-multi-module -> core -> webapp,先在maven-multi-module上执行是因为其他两个模块都将它作为父模块,即对它存在依赖关系,又由于core被webapp依赖,所以接下来在core上执行命令,最后在webapp上执行。
这里又有一个问题:为什么非得在maven-multi-module目录下执行 “mvn clean install”?答案是,并不是非得如此,只是你需要搞清楚Maven的工作机制。在maven-multi-module目录下执行,即是在父工程中执行,此时Maven知道父模块所包含的所有子模块,并会自动按照模块依赖关系处理执行顺序。如果只在子模块中执行,那么Maven并不知道它对其他模块的依赖关系。举个例子,当在webapp中执行 “mvn clean install”,Maven发现webapp自己依赖于core,此时Maven只会在本地的Repository中去找core,如果存在,那么你很幸运,如果不存在,那么对不起,运行失败,说找不到core,因为Maven并不会先将core模块安装到本地Repository。此时你需要做的是,切换到core目录,执行“mvn clean install”将core模块安装到本地Repository,再切换回webapp目录,执行“mvn clean install”,万事才大吉。
多么繁琐的步骤,此时你应该能体会到在maven-multi-module下执行Maven命令的好处了吧。总结一下:在maven-multi-module下执行“mvn clean install”, Maven会在每个模块上执行该命令,然后又发现webapp依赖于core,此时他们之间有一个协调者(即父工程),它知道将core作为webapp的依赖,于是会先在core模块上执行“mvn clean install”,当在webapp上执行命令时,无论此时的core模块是否存在于本地Repository中,父工程都能够获取到core模块(如果不存在于本地Repository,它将现场编译core模块,再将其做为webapp的依赖,比如此时使用“mvn clean package”也是能够构建成功的),所以一切成功。
这里又牵扯到Maven如何查找依赖的问题,简单来说,Maven会先在本地Repository中查找依赖,如果依赖存在,则使用该依赖,如果不存在,则通过pom.xml中的Repository配置从远程下载依赖到本地Repository中。默认情况下,Maven将使用Maven Central Repository作为远端Repository。于是你又有问题了:“在pom.xml中为什么没有看到这样的配置信息啊?”原因在于,任何一个Maven工程都默认地继承自一个Super POM,Repository的配置信息便包含在其中。
(三)多模块 vs 继承
在文章一开始我们便提到,在Maven中,由多模块(由上到下)和继承(由下到上)关系并不必同时存在。
(1)如果保留webapp和core中对maven-multi-module的父关系声明,即保留 “<parent>... </parent>”,而删除maven-multi-module中的子模块声明,即“<modules>...<modules>”,会发生什么情况?此时,整个工程已经不是一个多模块工程,而只是具有父子关系的多个工程集合。如果我们在maven-multi-module目录下执行“mvn clean install”,Maven只会在maven-multi-module本身上执行该命令,继而只会将maven-multi-module安装到本地Repository中,而不会在webapp和core模块上执行该命令,因为Maven根本就不知道这两个子模块的存在。另外,如果我们在webapp目录下执行相同的命令,由于由子到父的关系还存在,Maven会在本地的Repository中找到maven-multi-module的pom.xml文件和对core的依赖(当然前提是他们存在于本地的Repository中),然后顺利执行该命令。
这时,如果我们要发布webapp,那么我们需要先在maven-multi-module目录下执行“mvn clean install”将最新的父pom安装在本地Repository中,再在core目录下执行相同的命令将最新的core模块安装在本地Repository中,最后在webapp目录下执行相同的命令完成最终war包的安装。麻烦。
(2)如果保留maven-multi-module中的子模块声明,而删除webapp和core中对maven-multi-module的父关系声明,又会出现什么情况呢?此时整个工程只是一个多模块工程,而没有父子关系。Maven会正确处理模块之间的依赖关系,即在webapp模块上执行Maven命令之前,会先在core模块上执行该命令,但是由于core和webapp模块不再继承自maven-multi-module,对于每一个依赖,他们都需要自己声明,比如我们需要分别在webapp和core的pom.xml文件中声明对Junit依赖。
综上,多模块和父子关系是不同的。如果core和webapp只是在逻辑上属于同一个总工程,那么我们完全可以只声明模块关系,而不用声明父子关系。如果core和webapp分别处理两个不同的领域,但是它们又共享了很多,比如依赖等,那么我们可以将core和webapp分别继承自同一个父pom工程,而不必属于同一个工程下的子模块。
相关推荐
使用`mvn clean install`命令,Maven会按照pom.xml中的配置,从上到下编译、测试、打包所有模块。最终,每个模块会产生相应的JAR或WAR文件,存放在本地仓库。 7. 插件配置: 多模块项目中,插件配置可以在父POM或...
在开发大型Java项目时,Maven多模块结构的使用非常常见,它可以帮助我们更好地管理和组织代码。然而,当项目变得庞大时,编译速度可能会成为一个显著的问题。以下是一些优化Maven多模块项目编译速度的策略: 1. **...
maven多模块工程打包部署的方法步骤 Maven多模块工程打包部署是一种常见的项目结构,在这种结构中,一个项目被分割成多个小模块,每个模块负责特定的功能。这种结构可以使项目变得更加灵活和易于维护。但是,多模块...
当我们面对大型的、由多个子项目组成的项目时,Maven的多模块功能显得尤为重要。本文将详细探讨"Maven多模块打包pom文件"的相关知识点。 首先,让我们理解什么是Maven的多模块项目。在Maven中,一个项目可以被组织...
而Maven的Archetype插件则可以帮助开发者快速创建新项目的模板,尤其对于有多个子模块的大型项目,能够大大提升开发效率。本篇文章将详细介绍如何使用Maven Archetype来创建一个多子模块的模板工程。 一、理解Maven...
在设置好模块关系后,Maven可以通过`mvn install`命令自底向上编译、测试和打包整个项目。每个模块都会生成相应的JAR或WAR文件,最终的Web应用模块会包含所有依赖的模块。 此外,Maven的多模块项目还支持模块间的...
集成测试是在各个模块被单独测试后进行的,旨在验证不同模块之间的交互是否按预期工作。 #### 20. `mvn verify` 验证之前阶段的成果是否达到预期目标。这是Maven生命周期中的一个重要步骤,它会在测试和打包之后...
在多模块项目中,通过执行`mvn install`命令,Maven会按照依赖关系从父到子依次构建所有模块。 6. **插件管理**:除了依赖,"xd-parent"还可能包含一些全局的插件配置,如`maven-jar-plugin`用于打包JAR,`maven-...
运行`mvn clean install`命令,Maven会自动按照模块间的依赖关系进行编译、打包和部署。父模块的`modules`标签用于指定子模块的相对路径,使得Maven能够正确地构建整个项目。 七、持续集成与发布 在持续集成环境中...
Maven多模块项目是一种高效组织大型Java项目的方式,它允许我们将一个复杂的系统分解为多个相互依赖的独立模块,每个模块专注于特定的功能或服务。这样做的好处包括代码复用、提高开发效率、简化构建过程以及便于...
此外,`mvn release`还支持一些重要的参数,例如`-DpushChanges=false`可以避免自动推送更改,`-DautoVersionSubmodules=true`会自动更新子模块的版本号。 在进行`mvn release`前,请确保项目符合以下最佳实践: 1...
本示例“maven多级子模块”旨在演示如何利用Maven的多模块特性来组织复杂的项目结构,使其更易于管理和维护。在大型项目中,通常会将不同功能或组件划分为独立的模块,以便于团队协作和代码复用。 首先,我们需要...
1. **多模块项目**:在大型项目中,通常会使用多个模块。使用`mvn install`在模块之间递归构建。 2. **自定义构建过程**:通过在pom.xml中配置插件和目标,可以定制化构建过程。 3. **版本控制**:`mvn versions`...
2. **多模块项目的意义**:在大型项目中,通过划分多个独立的模块,可以降低代码复杂度,便于团队协作,每个模块专注于特定的功能,易于测试和维护。 3. **创建新项目**:首先打开IDEA,选择"New Project",在项目...
例如,输出中提到的“黄色部分为命令输入之后自动输出模块”,这部分指的是Maven在构建过程中识别并处理了哪些模块。 #### 六、常见问题与解决办法 - **错误:找不到或无法加载主类**:检查项目配置文件pom.xml中...
4. **构建和运行**:通过Maven的命令行工具,如`mvn clean install`,编译和打包所有模块。最后,在web模块下运行SpringBoot应用,启动服务。 这样的多模块结构有利于代码的组织和团队协作,每个模块都有清晰的职责...
7. **构建项目**:通过Maven的构建命令(如`mvn install`),可以自动化编译、测试和打包所有子模块。 ### 进销存(PSS)项目的模块化 进销存(PSS)项目的模块化结构是典型的三层架构,其子模块分别对应不同层次...
本篇文章将详细探讨"Maven多模块项目构建过程",并结合提供的资源"搭建maven多工程模块步骤",来深入理解如何创建和管理一个包含多个子项目的Maven工程。 1. Maven多模块项目概述: Maven多模块项目是指由一个父...
在父模块的pom.xml文件中,我们还需要配置Sonarqube相关的信息,以便在执行`mvn sonar:sonar`命令时可以正确地向Sonarqube服务器上传数据。下面是一个示例配置: ```xml <id>sonar <activeByDefault>true ...
Maven作为Java领域广泛使用的构建工具,以其强大的依赖管理和项目生命周期管理能力,成为多模块项目管理的理想选择。本教程将详细介绍如何使用Maven来管理多模块项目,并指导如何进行项目的启动与调试。 首先,理解...