Maven 初学者完整教程
什么是 Apache Maven?
安装 Maven
在 IDE 中配置 Maven 安装
创建您的第一个 Maven 项目
探索 Maven 文件夹结构
Maven核心概念
这篇文章最初发表在programmingtechie.com
如果您是 Java 开发人员,那么您在 Java 项目上工作的日常活动包括编写代码、编译代码、测试、以 JAR、WAR 或 EAR 等工件的形式打包代码,然后将此工件部署到应用程序服务器。
Apache Maven通过最大限度地减少手动开销来自动执行上述所有任务。
在本教程中,我们将了解什么是 Apache Maven?并将涵盖在 Java 项目中开始使用 Maven 所需的所有概念
如果您和我一样是视觉学习者,请查看以下视频教程:
目录
- 什么是 Apache Maven
- 安装 Maven
- 在 IDE 中配置 Maven 安装
- 创建您的第一个 Maven 项目
- 探索 Maven 文件夹结构
- Maven核心概念
- Maven 构建生命周期
- 插件和目标
- Maven 多模块项目
- 使用配置文件
- 结论
什么是 Apache Maven?
Apache Maven是一个项目管理工具,用于管理使用 Java、Scala、Groovy 等 JVM 语言开发的项目。
项目管理工具的主要任务包括:
- 构建源代码
- 测试源代码
- 将源代码打包成工件(ZIP、JAR、WAR 或 EAR)
- 处理工件的版本控制和发布
- 从源代码生成 JavaDocs
- 管理项目依赖关系
Maven 也称为构建工具或依赖管理工具
安装 Maven
您可以从此处的网站下载 Maven 。在撰写本教程时,Maven 的最新版本是 3.6.3。
在“文件”部分下,您可以通过单击类似apache-maven-3.6.3-bin.zip的链接下载 Maven
下载并解压文件夹后,请确保添加 M2_HOME 环境变量并将该变量的值设置为解压文件夹的位置。
之后,确保设置另一个名为 M2 的环境变量,其包含值 M2_HOME/bin
之后,确保使用 M2 环境变量更新 Path 变量。
完成上述步骤后,打开一个新的终端窗口并输入mvn –version
,您应该会看到如下输出:
在 IDE 中配置 Maven 安装
下一步是在您最喜欢的 IDE 中配置 maven 安装,在本教程中我们将使用 IntelliJ IDEA 作为主要 IDE。
您可以在此处下载此 IDE 的社区版本
安装 IDE 后,在欢迎窗口上单击配置按钮并选择设置,在设置窗口内搜索 Maven,然后在Maven 主目录下选择 Maven 目录。
单击“应用”,然后单击“确定”
您已在 IDE 中成功配置 Maven。现在是时候创建我们的第一个 Maven 项目了。
创建您的第一个 Maven 项目
在 IntelliJ 中,单击“新建项目”,然后在窗口中选择左侧的“Maven” ,然后单击“下一步”。
然后输入您的项目名称,并展开Artifact Coordinates部分。
您将看到字段GroupId、ArtifactId和Version。
- GroupId 就像是项目的标识符,通常遵循 Java 包命名约定,因此在我们的示例中,IntelliJ 默认添加了值 org.example,但您可以添加任何您喜欢的值。
- ArtifactId 是您正在创建的项目的名称
- 版本是一个唯一的数字,用于标识我们项目的版本。
单击“完成”后,IntelliJ 将打开该项目,并且项目的文件夹结构将类似于下面的图片。
探索 Maven 文件夹结构
让我们看一下刚刚创建的 Maven 项目的文件夹结构。
src文件夹是我们应用程序源代码和测试的根目录。它包含以下子文件夹:
- 文件夹src/main/java包含 Java 源代码,我们应用程序的所有生产代码都驻留在此
- 在src/main/resources 文件夹中,我们将存储项目中使用的所有文件(例如:属性文件,以及应用程序中需要读取的任何文件,例如 XML、CSV 等)。如果您正在开发 Web 应用程序,我们通常会将所有静态资源放在此文件夹中。
- 在src/test/java文件夹中,我们将存储项目中的所有测试类。
- 还有一个名为target的文件夹(目前不可见),用于存储已编译的 Java 类文件。我们将在接下来的章节中讨论它。
- 最后,我们有pom.xml文件,其中包含项目依赖项的元数据。
Maven核心概念
项目对象模型
项目对象模型文件(也称为pom.xml)包含项目的元数据,还负责管理依赖项和配置插件,这有助于我们自动执行许多重复性任务。
基本pom.xml文件如下所示:
<?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>org.example</groupId>
<artifactId>maven-project</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
- project是我们pom.xml文件的顶级标签,它封装了与我们的 Maven 项目相关的所有信息。
- modelVersion表示您正在使用的 POM 版本。Maven 3 的 modelVersion 始终为 4.0。除非您使用其他 Maven 主要版本,否则此版本不会更改。
现在我们知道了什么是 POM 文件,接下来我们来看看不同类型的 POM 文件。POM 文件基本上分为 3 种类型:
- 简单的POM文件
- 超级POM文件
- 有效的POM文件
简单的POM文件
这是上一节生成的相同文件(pom.xml )。它仅包含与我们当前项目相关的信息。
超级POM文件
超级 POM 文件是所有简单 POM 文件的父文件,它包含一组由所有简单 POM文件共享的默认配置。
您可以在 Maven 安装目录下的M2_HOME/lib路径下以及 JAR 文件maven-model-builder-XXX.jar中找到超级 POM文件,其中 XXX 代表您正在使用的 maven 版本。
我们可以在包名org.apache.maven.model下的文件名pom-4.0.0.xml下找到它。
注意:您永远不应该尝试编辑 Super POM,因为它包含来自 Maven 的合理默认值。
有效的POM文件
有效的 POM 文件只不过是简单 POM和超级 POM文件的组合。
这只是在一个地方检查 pom.xml 文件的所有信息的一种方法。
我们将在接下来的部分中探讨这将如何有所帮助。
您可以通过输入以下命令来查看pom.xml文件的有效 POM
mvn help:effective-pom
在 IntelliJ 中,您只需右键单击pom.xml文件,选择Maven -> Show Effective POM
依赖项
如果您正在开发任何重要的 Java 项目,那么很有可能您在项目中使用了许多第三方 JAR 文件来开发应用程序。这些 JAR 文件可以是任何内容,例如框架或库。例如Junit、Spring Framework、Selenium等等。
这些外部库被称为依赖项。Maven 提供了一种在pom.xml文件中指定和管理依赖项的绝佳方法。
如果不使用 Maven,您必须手动从互联网上下载所需的 JAR 文件,并将它们逐个添加到项目的类路径中。
Maven 在 pom.xml 中提供了一个依赖项部分,您可以在其中指定项目所需的 JAR 信息(groupId、artifactId和version)。一旦您指定了所需的库,maven 就会自动将这些依赖项下载到我们的项目中,并将它们添加到项目的类路径中。
在依赖项部分中,您可以在pom.xml文件中定义每个单独的依赖项,如下所示。
<?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>org.example</groupId>
<artifactId>maven-project</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
</dependency>
</dependencies>
</project>
我们已在pom.xml文件中将Junit5定义为依赖项。
请注意,我提到了标签groupId、artifactId和version来唯一标识依赖项,通过提供这些值,Maven 可以自动将这些依赖项下载到我们的项目中。
在 IntelliJ 中,请务必点击右侧“Maven”选项卡下的“刷新”按钮,强制 IntelliJ 启动依赖项的下载。如下图所示:
这样,您可以在 pom.xml 中提供项目所需的所有依赖项,Maven 将自动下载它们。
传递依赖
在上面的例子中,你可以观察到junit-jupiter-engine确实依赖于其他 JAR 文件,如apiguardian-api、junit-platform-engine和junit-jupiter-api
这些 JAR 文件被称为传递依赖项
排除依赖项
在某些情况下,项目依赖项和传递依赖项之间会发生一些冲突,此时我们可以手动排除不需要的传递依赖项。
例如,如果您使用 Spring Boot 开发应用程序,则有一个名为spring-boot-starter-test的依赖项,它将提供测试 Spring Boot 应用程序所需的所有依赖项。
此spring-boot-starter-test依赖项包含Junit 4作为传递依赖项,由于我们已经在使用Junit 5,因此我们可以排除传递依赖项,如下所示:
<?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>org.example</groupId>
<artifactId>maven-project</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.6.RELEASE</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
注意:较新的 Spring Boot 版本带有 JUnit 5 依赖项,我特意使用旧版本2.1.6.RELEASE作为示例。
SNAPSHOT 和 RELEASE 依赖项
依赖关系可以分为两种:
- 快照
- 发布快照依赖项类似于项目版本正在开发中。
如果您在团队中从事 Java 项目,则很可能会遵循某种迭代过程,在该过程中您会经历开发阶段,然后在阶段结束时发布软件。
当项目处于开发阶段时,我们通常使用SNAPSHOT依赖项,它看起来像1.0-SNAPSHOT
<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>org.example</groupId>
<artifactId>maven-project</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
当软件准备好发布时,我们通常会创建一个类似于1.0.RELEASE的 RELEASE 版本(例如:Spring Boot Starter Test 依赖项)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.6.RELEASE</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
依赖范围
每个 Maven 依赖项可分为 6 种不同的范围。
以下是可用范围的列表:
- compile:如果未指定,则为默认范围。编译时依赖项可在项目的类路径中找到。
- provided:类似于编译范围,但表示 JDK 或底层容器将在运行时提供依赖项。依赖项将在编译时可用,但不会打包到构件中。javax.servlet -api依赖项就是一个用法示例。
- 运行时:使用此范围定义的依赖项仅在运行时可用,而在编译时不可用。以下是使用示例:假设您在项目中使用 MySQL 驱动程序,您可以添加范围为运行时的依赖项,以确保在实现过程中使用 JDBC API 抽象而不是 MySQL 驱动程序 API。如果源代码包含任何属于 MySQL JDBC API 的类,则代码将无法编译,因为依赖项在编译时不可用。
- test:依赖项仅在运行测试时可用,典型示例包括 Junit 和 TestNG
- system :它与提供的范围类似,但唯一的区别是我们需要使用systemPath标签明确提及在系统中可以找到依赖项的位置:
<systemPath>${basedir}/lib/some-dependency.jar</systemPath>
存储库
在上一节中,我们了解了 Maven 如何管理和自动下载依赖项。
这些依赖项存储在一个名为Repository的特殊目录中。基本上有两种存储库:
- 本地存储库本地存储库是运行 Maven 的机器上的目录。
本地存储库的默认位置是 /.m2
在 Windows 中,它看起来像:
C:\Users<user-name>.m2\repository
- 远程仓库远程仓库是一个可以下载 Maven 依赖项的网站。它可以是 Maven 提供的仓库(repo.maven.org),也可以是组织内部使用Artifactory或Nexus等软件设置的自定义仓库。了解了不同类型的仓库后,我们来看看 Maven 如何解析依赖项。
现在让我们看看 Maven 如何解决依赖关系。
- 当您在pom.xml文件中定义依赖项时,Maven 首先检查该依赖项是否已经存在于本地存储库中。
- 如果不是,那么它会尝试连接到远程存储库(例如:https ://repo.maven.org ) 并尝试下载依赖项,然后将它们存储在本地存储库中。我们可以在 pom.xml 中定义远程存储库,如下所示:
我的内部站点
http://myserver/repo
###Snapshot and Release Version Handling<a name="chapter-16"></a>
In the previous section, we learned that Maven first checks the **Local Repository** before downloading a dependency from **Remote Repository**.
When dealing with **SNAPSHOT** dependencies Maven **periodically** downloads the dependency from **Remote Repository** even though the dependency exists in **Local Repository**.
This is because **SNAPSHOT** dependencies are under heavy development, and are subjected to change frequently.
You can change this behavior by adding a **<snapshots>** section inside the **repositories** tag.
我的内部站点
http://myserver/repo
true
XXX
The value XXX inside the **updatePolicy** can be:
* **always**: Maven always checks for a latest version
* **daily**: This is the default value, as the name suggests it downloads the version once every day on the first run.
* **interval:XXX**: Checks every XXX minutes
* **never**: Never checks for the updates.
**RELEASE** versions on the other hand are more stable, and follow the usual dependency resolution.
# Maven Build Lifecycle<a name="chapter-17"></a>
Till now we learned about the Core Concepts of Maven, now it’s time to dive deep and understand how Maven builds our Java Project.
Maven follows a **Build Lifecycle** to well… build our project.
This Lifecycle is divided into 3 parts:
* default
* clean
* site
Each Lifecycle is independent of each other and they can be executed together.
The default life cycle is divided into different phases like below:
* **validate** – verifies whether the pom.xml file is valid or not
* **compile** – compiles the source code inside the project
* **test** – runs unit-tests inside the project
* **package** – packages the source code into an artifact (ZIP, JAR, WAR or EAR)
* **integration-test**– executes tests marked as Integration Tests
* **verify** – checks whether the created package is valid or not.
* **install** – installs the created package into our Local Repository
* **deploy** – deploys the created package to the Remote Repository
The **clean** lifecycle is mainly responsible to clean the .class and meta-data generated by the above build phases.
The **site** lifecycle phase is responsible to generate Java Documentation.
All 3 lifecycles also contains some additional phases, which I am not going to cover in this tutorial, if you are interested you can refer to the [Maven Documentation](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#lifecycle-reference)
# Plugins and Goals<a name="chapter-18"></a>
To be able to execute these Lifecycle Phases, Maven provides us with **Plugins** to perform each task.
Each plugin is associated with a particular **Goal**
Let’s have a look at different Plugins and the associated Goals:
##Maven Compile Plugin<a name="chapter-19"></a>
The Maven Compile Plugin is responsible to compile our Java files into the .class files. It’s equivalent of running **javac <java-class-name>**
This plugin enables the **compile** phase of the default lifecycle.
You can add this plugin to your project by adding the below section to your **pom.xml** file under the **dependencies**
section.
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
At the time of writing this tutorial, **Maven Compiler Plugin** is at version **3.8.1**
After adding the plugin to the project, you can activate the **compile** phase, by typing the below command:
$ mvn 编译器:编译
[INFO] 正在扫描项目...
[INFO]
[INFO] ---------------------< org.example:maven-project >-------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-cli) @ maven-project ---
[INFO] 无需编译 - 所有类都是最新的
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总时间:0.729 秒
[INFO] 完成时间:2020-12-04T20:16:23+01:00
[INFO] ------------------------------------------------------------------------
In the above command the **compiler** is the name of the plugin and **compile** is the goal which triggers the lifecycle phase – compile
You can already see the message – **“Nothing to compile – all classes are up to date”**
As there are no Java Files in our project, there is nothing to compile, so let’s create a simple **HelloWorld.java** file
公共类 HelloWorld {
公共静态 void main(String[] args) {
System.out.println("Hello World");
}
}
If you try to compile again, you can see the following output:
$ mvn 编译器:编译
[INFO] 正在扫描项目...
[INFO]
[INFO] ---------------------< org.example:maven-project >-------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-cli) @ maven-project ---
[INFO] 检测到更改 - 正在重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在编译 1 个源文件到 F:\maven-project\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总用时:1.123 秒
[INFO] 完成时间:2020-12-04T20:14:55+01:00
[INFO] ------------------------------------------------------------------------
We can see the generated class files under the target folder which resides just under the project root folder.

If you have some Test files, those are also compiled using the **Compiler Plugin**.
To demonstrate that let’s create the below Test class under the src/test/java folder
公共类 HelloWorldTest {
公共静态 void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
System.out.println(helloWorld.say("Hi"));
}
}
And here is how you can compile the test classes:
$ mvn compiler:testCompile
[INFO] 正在扫描项目...
[INFO]
[INFO] ---------------------< org.example:maven-project >----------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-cli) @ maven-project ---
[INFO] 检测到更改 - 正在重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在编译 1 个源文件到 F:\maven-project\target\test-classes
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总用时:1.319 秒
[INFO] 完成时间:2020-12-04T20:23:59+01:00
[INFO] ------------------------------------------------------------------------
As you can see that a change has been detected by the **Maven Compiler Plugin** and it has compiled our Test classes to the **target/test-classes** folder

As we are using IntelliJ, we can also use it to run the compilation, by clicking on the **compile** button under the **LifeCycle** dropdown as you see in the below image:

If you run the **compile** option you may see the below error:
[INFO] 正在将 1 个源文件编译到 F:\maven-project\target\classes
[INFO] -------------------------------------------------------------------------
[ERROR] 编译错误:
[INFO] -------------------------------------------------------------------------
[ERROR] 源选项 6 不再受支持。请使用 7 或更高版本。
[ERROR] 目标选项 6 不再受支持。请使用 7 或更高版本。
This is because, by default the **Source** and **Target** Compiler Version is set to 1.5 in IntelliJ Configuration. You can add the below **configuration** to the compiler plugin to override this settings:
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
15
You can pass many customized option to the Maven Compiler Plugin based on your needs, you can find the examples of the configuration in the [Apache Maven Compiler Plugin](https://maven.apache.org/plugins/maven-compiler-plugin/index.html) website
##Maven Surefire Plugin<a name="chapter-20"></a>
Using **Surefire Plugin**, we can run the tests inside our project by using the following command:
$ mvn test
[INFO] 正在扫描项目...
[INFO]
[INFO] ---------------------< org.example:maven-project >----------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-project ---
[WARNING] 使用平台编码 (实际上是 Cp1252) 复制筛选后的资源,即构建依赖于平台!
[INFO] 正在复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ maven-project ---
[INFO] 检测到更改 - 正在重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在将 1 个源文件编译到 F:\maven-project\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-project ---
[WARNING] 使用平台编码(实际上是 Cp1252)复制筛选后的资源,即构建依赖于平台!
[INFO] 跳过不存在的资源目录 F:\maven-project\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ maven-project ---
[INFO] 检测到更改 - 正在重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在将 1 个源文件编译到 F:\maven-project\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ maven-project --- [
INFO]
[INFO] -------------------------------------------------------------------
[INFO] 测试
[INFO] -------------------------------------------------------------------
[INFO] 运行 HelloWorldTest
Hi
[INFO] 测试运行:1,失败:0,错误:0,已跳过:0,耗时:0.014 秒 - 在 HelloWorldTest 中
[INFO]
[INFO] 结果:
[INFO]
[INFO] 测试运行:1,失败:0,错误:0,已跳过:0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总时间:4.797 秒
[INFO] 完成于: 2020-12-04T20:54:49 + 01:00
[信息] ------------------------------------------------------------------------
You can see that the HelloWorldTest.java file was executed successfully, and the you can also see how many Tests are executed successfully.
The Surefire Plugin generates Text and XML reports under the **target/surefire-reports** folder.

Similar to **Compiler Plugin**, you can also configure Surefire Plugin based on your needs.
Surefire Plugin by default includes all tests, if you have a bunch of tests, you can manually exclude some tests to be executed using below configuration:
org.apache.maven.plugins
maven-surefire-plugin
2.22.2
HelloWorldTest.java
And if you run the **mvn test** command now, you can see that no tests are executed.
$ mvn test
[INFO] 正在扫描项目...
[INFO]
[INFO] ---------------------< org.example:maven-project >----------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-project ---
[警告] 使用平台编码(实际上是 Cp1252)复制过滤后的资源,即构建依赖于平台!
[INFO] 复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ maven-project ---
[INFO] 无需编译 - 所有类都是最新的
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-project ---
[WARNING] 使用平台编码(实际上是 Cp1252)复制已过滤的资源,即构建依赖于平台!
[INFO] 跳过不存在的资源目录 F:\maven-project\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ maven-project ---
[INFO] 无需编译 - 所有类都是最新的
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ maven-project ---
[INFO] ------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------
[INFO] 总用时:1.043 秒
[INFO] 完成时间:2020-12-04T21:00:09+01:00
[INFO] ------------------------------------------------------------
##Maven Install Plugin<a name="chapter-21"></a>
This is used to package our source code into an artifact of our choice like a JAR and install it to our **Local Repository** which is **<USER_HOME>/.m2/repository** folder.
You can configure Maven Install Plugin by adding the below code:
org.apache.maven.plugins
maven-install-plugin
2.5.2
You can run the **install** phase of the lifecycle by typing the below command:
$ mvn install
[INFO] 正在扫描项目...
[INFO]
[INFO] ---------------------< org.example:maven-project >----------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-project ---
[警告] 使用平台编码(实际上是 Cp1252)复制过滤后的资源,即构建依赖于平台!
[INFO] 复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ maven-project ---
[INFO] 无需编译 - 所有类都是最新的
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-project ---
[WARNING] 使用平台编码(实际上是 Cp1252)复制已过滤的资源,即构建依赖于平台!
[INFO] 跳过不存在的资源目录 F:\maven-project\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ maven-project ---
[INFO] 无需编译 - 所有类都是最新的
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ maven-project ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-project ---
[INFO] 构建 jar:F:\maven-project\target\maven-project-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ maven-project ---
[INFO] 正在将 F:\maven-project\target\maven-project-1.0-SNAPSHOT.jar 安装到C:\Users\sai.m2\repository\org\example\maven-project\1.0-SNAPSHOT\maven-project-1.0-SNAPSHOT.jar
[INFO] 正在将 F:\maven-project\pom.xml 安装到 C:\Users\sai.m2\repository\org\example\maven-project\1.0-SNAPSHOT\maven-project-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总用时:1.236 秒
[INFO] 完成时间:2020-12-04T21:10:49+01:00
[INFO] ------------------------------------------------------------------------
By checking the above output, you can see that the install phase includes also the previous phases in the lifecycle, so as part of this phase maven:
* validates our pom.xml (**validate**)
* compiles our source code (**compile**)
* executes our tests (**test**)
* packages our source code into JAR (**package**)
* installs the JAR into our local repository (**install**)
You can see the JAR file in the below screenshot under the **target** folder.

##Maven Deploy Plugin<a name="chapter-22"></a>
The Maven Deploy Plugin will deploy the artifact into a remote repository. The deploy goal of the plugin is associated with the **deploy** phase of the build lifecycle.
The plugin can be configured like below:
org.apache.maven.plugins
maven-deploy-plugin
2.8.2
Before running the **deploy** phase of the lifecycle, we have to make sure that the remote repository details are configured inside our project.
We can configure this details inside the **distributionManagement** section:
测试发行版发行
版名称
http://distrourl.com
To be able to connect to the remote repository, maven needs access to the credentials, which can be configured inside a special file called as **settings.xml** file.
This file is usually configured inside the **<USER_HOME>/.m2/** folder, which looks like something below:
xsi:schemaLocation =“http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd”>
测试分发
my_username
my_password
Maven also provides us a way to encrypt the credentials inside the **settings.xml** file, you can read about this here
You can run the **deploy** goal using the following command:
`$ mvn deploy`
Once you run this command, you will notice that it will run all the lifecycle phases up until deploy.
Although if you run this command in the example project, it will fail because the Remote Repository Details are invalid.
##Maven Clean Plugin<a name="chapter-23"></a>
Another important plugin in Maven is the **Maven Clean Plugin**, you saw that when running the above lifecycle phases, the generated files are stored under a folder called **target**.
Usually when building our source code we need to start of as a clean slate so that there are no inconsistencies in the generated class files or JAR.
For this reason we have the **clean** phase where we will delete all the contents inside the **target** folder. You can execute this phase by typing the below commands:
$ mvn clean
[INFO] 正在扫描项目...
[INFO]
[INFO] ---------------------< org.example:maven-project >-------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-project ---
[INFO] 正在删除 F:\maven-project\target
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总用时:0.204 秒
[INFO] 完成时间:2020-12-04T21:19:12+01:00
[INFO] ------------------------------------------------------------------------
You can see that the target folder under our project is deleted successfully.
## Other Maven Plugins<a name="chapter-24"></a>
There are many other plugins in Maven world, to execute other phases in the Maven Build Lifecycle, you can check them out [here](https://maven.apache.org/plugins/index.html)
#Maven Multi Module Projects<a name="chapter-25"></a>
Till now we saw the Core Concepts of Maven, now it’s time to dive deep into some advanced concepts.
In the real world where we are building some non-trivial projects, the source code is going to be modularized (hopefully) and is divided into different sub projects.
To manage this effectively, Maven provides us Multi Module Projects where you can have nest different projects inside each other. We are basically creating a parent-child relationship between different Maven projects.
Basically, we have a **Parent Project** (Parent POM) which contains different **sub-projects** (**sub-modules**), each of which is again a normal Maven Project.

The **Parent POM** usually encapsulates other child’s and that’s why its packaged as a **POM** instead of usual packaing format’s like **JAR**.
If you recall the section **Project Object Model** , we discussed about **Super POM** which is basically a kind of **Parent POM** which encapsulates default settings configured by Maven for us.
##Creating Multi Module Project using IntelliJ<a name="chapter-26"></a>
We will see how to generate Multi Module Projects using our IntelliJ IDE.
To create the project, first right click on the project root folder and select **New** -> **Module** and click on **Next**.

Give a name to the child project and click on **Finish**.

You can see the new project structure in the above picture after we created the **child project**.
Now if you open the **pom.xml** under the root folder, you can observe the following tags which are added by creating the maven module.
<modules>
<module>child-project-1</module>
</modules>
We can create multiple projects in the same way and you can see all the modules will be listed one-by-one under the **modules** tag.
<modules>
<module>child-project-1</module>
<module>child-project-2</module>
<module>child-project-3</module>
</modules>
As we create these 3 modules, having the **src** folder under the root project folder doesn’t make much sense, so let’s copy and paste this folder onto other child-projects, so that we have some code configured inside these modules.
This is how our project structure now looks like:

And if you check the **pom.xml** of **child-project-1**,**child-project-2** and **child-project-3**. You can see that the root project is configured as a parent project.
<?xml version="1.0" encoding="UTF-8"?>
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">
maven-project
org.example
1.0-SNAPSHOT
4.0.0
<artifactId>child-project-1</artifactId>
Now you can build all the projects at once by running the **mvn install** under the Parent Project, and Maven scans through all the POMS and builds all of them one-by-one
$ mvn install
[INFO] 正在扫描项目...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor 构建顺序:
[INFO]
[INFO] maven-project [pom]
[INFO] child-project-1 [jar]
[INFO] child-project-2 [jar]
[INFO] child-project-3 [jar]
[INFO]
[INFO] ---------------------< org.example:maven-project >----------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ maven-project ---
[INFO] 将 F:\maven-project\pom.xml 安装到 C:\Users\subra.m2\repository\org\example\maven-project\1.0-SNAPSHOT\maven-project-1.0-SNAPSHOT.pom
[INFO]
[INFO] --------------------< org.example:child-project-1 >---------------------
[INFO] 正在构建 child-project-1 1.0-SNAPSHOT [2/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ child-project-1 ---
[WARNING] 使用平台编码 (实际上是 Cp1252) 复制筛选后的资源,即构建依赖于平台!
[INFO] 正在复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ child-project-1 ---
[INFO] 检测到更改 - 正在重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在编译 1 个源文件到 F:\maven-project\child-project-1\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ child-project-1 ---
[WARNING] 使用平台编码(实际上是 Cp1252)复制筛选后的资源,即构建依赖于平台!
[INFO] 跳过不存在的资源目录 F:\maven-project\child-project-1\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ child-project-1 ---
[INFO] 检测到更改 - 正在重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在编译 1 个源文件到 F:\maven-project\child-project-1\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ child-project-1 ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar(default-jar)@ child-project-1 ---
[INFO] 构建 jar:F:\ maven-project \child-project-1 \target \child-project-1-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install(default-install)@ child-project-1 ---
[INFO] 将 F:\ maven-project \child-project-1 \target \child-project-1-1.0-SNAPSHOT.jar 安装到 C:\ Users \subra.m2 \repository \org \example \child-project-1 \1.0-SNAPSHOT \child-project-1-1.0-SNAPSHOT.jar
[INFO] 将 F:\ maven-project \child-project-1 \pom.xml 安装到C:\Users\subra.m2\repository\org\example\child-project-1\1.0-SNAPSHOT\child-project-1-1.0-SNAPSHOT.pom
[INFO]
[INFO] --------------------< org.example:child-project-2 >---------------------
[INFO] 正在构建 child-project-2 1.0-SNAPSHOT [3/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ child-project-2 ---
[警告] 使用平台编码(实际上是 Cp1252)复制已筛选的资源,即构建依赖于平台!
[INFO] 正在复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ child-project-2 ---
[INFO] 检测到更改 - 正在重新编译模块!
[警告] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[信息] 正在编译 1 个源文件到 F:\maven-project\child-project-2\target\classes
[信息]
[信息] --- maven-resources-plugin:2.6:testResources (default-testResources) @ child-project-2 ---
[警告] 正在使用平台编码(实际上是 Cp1252)复制筛选后的资源,即构建依赖于平台!
[信息] 跳过不存在的资源目录 F:\maven-project\child-project-2\src\test\resources
[信息]
[信息] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ child-project-2 ---
[信息] 检测到更改 - 正在重新编译模块!
[警告] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在编译 1 个源文件到 F:\maven-project\child-project-2\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ child-project-2 ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ child-project-2 ---
[INFO] 正在构建 jar:F:\maven-project\child-project-2\target\child-project-2-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ child-project-2 ---
[INFO] 将 F:\maven-project\child-project-2\target\child-project-2-1.0-SNAPSHOT.jar 安装到 C:\Users\subra.m2\repository\org\example\child-project-2\1.0-SNAPSHOT\child-project-2-1.0-SNAPSHOT.jar
[INFO] 将 F:\maven-project\child-project-2\pom.xml 安装到 C:\Users\subra.m2\repository\org\example\child-project-2\1.0-SNAPSHOT\child-project-2-1.0-SNAPSHOT.pom
[INFO]
[INFO] --------------------< org.example:child-project-3 >---------------------
[INFO] 构建 child-project-3 1.0-SNAPSHOT [4/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ child-project-3 ---
[警告] 使用平台编码(实际上是 Cp1252)复制筛选后的资源,即构建依赖于平台!
[INFO] 复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ child-project-3 ---
[INFO] 检测到更改 - 重新编译模块!
[警告] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在编译 1 个源文件到 F:\maven-project\child-project-3\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ child-project-3 ---
[WARNING] 使用平台编码 (实际上是 Cp1252) 复制已筛选的资源,即构建依赖于平台!
[INFO] 跳过不存在的资源目录 F:\maven-project\child-project-3\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ child-project-3 ---
[INFO] 检测到更改 - 正在重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在编译 1 个源文件到 F:\maven-project\child-project-3\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ child-project-3 ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ child-project-3 ---
[INFO] 构建 jar:F:\maven-project\child-project-3\target\child-project-3-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ child-project-3 ---
[INFO] 将 F:\maven-project\child-project-3\target\child-project-3-1.0-SNAPSHOT.jar 安装到 C:\Users\subra.m2\repository\org\example\child-project-3\1.0-SNAPSHOT\child-project-3-1.0-SNAPSHOT.jar
[INFO] 将 F:\maven-project\child-project-3\pom.xml 安装到 C:\Users\subra.m2\repository\org\example\child-project-3\1.0-SNAPSHOT\child-project-3-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] maven-project 1.0-SNAPSHOT 的反应堆摘要:
[INFO]
[INFO] maven-project ...................................... 成功 [ 0.252 秒]
[INFO] child-project-1 .................................... 成功 [ 1.534 s]
[INFO] child-project-2 .................................... 成功 [ 0.430 s]
[INFO] child-project-3 .................................... 成功 [ 0.351 s]
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总时间:2.699 s
[INFO] 完成时间:2020-12-04T21:58:10 + 01:00
[INFO] ------------------------------------------------------------------------
You can see that Maven built all the projects and provided us a nice report of the **Build Status** of each project.
Maven uses something called as a **Reactor** which is responsible to scan the whole project and identify the parent and child maven projects. If there are any dependencies, then Reactor makes sure to execute the projects in the required order.
For example, if **child-project-2** is dependent on **child-project-3** , then Maven Reactor makes sure to first build **child-project-3** and then **child-project-2**.
##Managing Dependencies inside Maven Multi Module Project<a name="chapter-27"></a>
When you are working with Multiple Maven Modules, you may be working with different dependencies in different modules, and chances are that you may be using similar dependencies in multiple modules.
Maven provides us a way to effectively manage the dependencies in your project by allowing us to define the dependencies in centralized location (**parent project**) and use those dependencies across the different child projects.
This minimizes the dependency version mismatch across multiple projects, as we have a single place we can manage all the dependencies and its versions.
Let’s see how to do that in our example project.
I am going to move all the dependencies which are defined inside the parent project into the **dependencyManagement** section, like below:
<?xml version="1.0" encoding="UTF-8"?>
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">
4.0.0
<groupId>org.example</groupId>
<artifactId>maven-project</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>child-project-1</module>
<module>child-project-2</module>
<module>child-project-3</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.6.RELEASE</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<excludes>HelloWorldTest.java</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
</plugins>
</build>
The change in the pom.xml is minor, we just moved the dependencies under the **dependencyManagement** tag.
Now if you analyze the dependencies under the **child-project-1** you can see that it’s empty.
mvn dependency:tree
[INFO] 正在扫描项目...
[INFO]
[INFO] --------------------< org.example:child-project-1 >---------------------
[INFO] 正在构建 child-project-1 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ child-project-1 ---
[INFO] org.example:child-project-1:jar:1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总用时:0.871 秒
[INFO] 完成时间:2020-12-05T20:23:59+01:00
[INFO] ------------------------------------------------------------------------
This is because we moved all the dependencies inside the Parent POM into **dependencyManagement** section, now to access any dependencies the **Child Projects** should define them manually inside their **pom.xml**.
In this way, the child projects can have only the dependencies they need inside the **pom.xml**.
Now, let’s go ahead and add the **junit-jupiter** dependencies inside the **child-project-1** and see what happens.
<?xml version="1.0" encoding="UTF-8"?>
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">
maven-project
org.example
1.0-SNAPSHOT
4.0.0
<artifactId>child-project-1</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
</dependencies>
$ mvn dependency:tree
[INFO] 正在扫描项目...
[INFO]
[INFO] --------------------< org.example:child-project-1 >---------------------
[INFO] 正在构建 child-project-1 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ child-project-1 ---
[INFO] org.example:child-project-1:jar:1.0-SNAPSHOT
[INFO] - org.junit.jupiter:junit-jupiter-engine:jar:5.5.2:compile
[INFO] +- org.apiguardian:apiguardian-api:jar:1.1.0:compile
[INFO] +- org.junit.platform:junit-platform-engine:jar:1.5.2:compile
[INFO] | +- org.opentest4j:opentest4j:jar:1.2.0:compile
[INFO] | - org.junit.platform:junit-platform-commons:jar:1.5.2:compile
[INFO] - org.junit.jupiter:junit-jupiter-api:jar:5.5.2:compile
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总时间:0.930 秒
[INFO] 完成时间:2020-12-05T20:27:26+01:00
[INFO] ------------------------------------------------------------------------
You can now see that the **junit-jupiter** dependency is available inside the **child-project-1**.
##Managing Plugins inside Maven Multi Module Project<a name="chapter-28"></a>
We can also manage Plugins inside our Maven Multi Module project, similar to the dependencies.
To Manage Plugins, we have the **pluginManagement** section inside the **pom.xml** and each child project can chose the plugin it needs.
This is how our parent **pom.xml** looks like after introducing the **pluginManagement**.
<?xml version="1.0" encoding="UTF-8"?>
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">
4.0.0
<groupId>org.example</groupId>
<artifactId>maven-project</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>child-project-1</module>
<module>child-project-2</module>
<module>child-project-3</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.6.RELEASE</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<excludes>HelloWorldTest.java</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
#Using Profiles<a name="chapter-29"></a>
Profiles can be used in Maven to created customized build configurations. This means customizing the behavior of our builds based on specific conditions.
For example: Sometimes we need to test whether the source code packaging is working correctly or not, in that case we can skip the test execution by activating the **skip.tests** property like below:
跳过测试
true
Now we can try to run the build by specifying which profile to activate using the **-P** flag.
$ mvn -Pskip-tests clean install
[INFO] 正在扫描项目...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor 构建顺序:
[INFO]
[INFO] maven-project [pom]
[INFO] child-project-1 [jar]
[INFO] child-project-2 [jar]
[INFO] child-project-3 [jar]
[INFO]
[INFO] ---------------------< org.example:maven-project >----------------------
[INFO] 正在构建 maven-project 1.0-SNAPSHOT [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-project ---
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ maven-project ---
[INFO] 正在将 F:\maven-project\pom.xml 安装到C:\Users\subra.m2\repository\org\example\maven-project\1.0-SNAPSHOT\maven-project-1.0-SNAPSHOT.pom
[INFO]
[INFO] --------------------< org.example:child-project-1 >---------------------
[INFO] 正在构建 child-project-1 1.0-SNAPSHOT [2/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ child-project-1 ---
[INFO] 正在删除 F:\maven-project\child-project-1\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ child-project-1 ---
[警告] 使用平台编码(实际上是 Cp1252)复制过滤后的资源,即构建依赖于平台!
[INFO] 复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ child-project-1 ---
[INFO] 检测到更改 - 重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在编译 1 个源文件到 F:\maven-project\child-project-1\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ child-project-1 ---
[INFO] 未复制测试资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ child-project-1 ---
[INFO] 未编译测试源
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ child-project-1 ---
[INFO] 测试被跳过。
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ child-project-1 ---
[INFO] 构建 jar:F:\maven-project\child-project-1\target\child-project-1-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install(default-install)@child-project-1 ---
[INFO] 将 F:\maven-project\child-project-1\target\child-project-1-1.0-SNAPSHOT.jar 安装到 C:\Users\subra.m2\repository\org\example\child-project-1\1.0-SNAPSHOT\child-project-1-1.0-SNAPSHOT.jar
[INFO] 将 F:\maven-project\child-project-1\pom.xml 安装到 C:\Users\subra.m2\repository\org\example\child-project-1\1.0-SNAPSHOT\child-project-1-1.0-SNAPSHOT.pom
[INFO]
[INFO] --------------------< org.example:child-project-2 >---------------------
[INFO] 正在构建 child-project-2 1.0-SNAPSHOT [3/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ child-project-2 ---
[INFO] 正在删除 F:\maven-project\child-project-2\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ child-project-2 ---
[WARNING] 使用平台编码 (实际上是 Cp1252) 复制已筛选的资源,即构建依赖于平台!
[INFO] 正在复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ child-project-2 ---
[INFO] 检测到更改 - 正在重新编译模块!
[警告] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[信息] 正在将 1 个源文件编译到 F:\maven-project\child-project-2\target\classes
[信息]
[信息] --- maven-resources-plugin:2.6:testResources (default-testResources) @ child-project-2 ---
[信息] 未复制测试资源
[信息]
[信息] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ child-project-2 ---
[信息] 未编译测试源
[信息]
[信息] --- maven-surefire-plugin:2.22.2:test (default-test) @ child-project-2 ---
[信息] 跳过测试。
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar(default-jar)@child-project-2 ---
[INFO] 构建 jar:F:\ maven-project \child-project-2 \target \child-project-2-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install(default-install)@child-project-2 ---
[INFO] 将 F:\ maven-project \child-project-2 \target \child-project-2-1.0-SNAPSHOT.jar 安装到 C:\ Users \subra.m2 \repository \org \example \child-project-2 \1.0-SNAPSHOT \child-project-2-1.0-SNAPSHOT.jar
[INFO] 将 F:\maven-project\child-project-2\pom.xml 安装到 C:\Users\subra.m2\repository\org\example\child-project-2\1.0-SNAPSHOT\child-project-2-1.0-SNAPSHOT.pom
[INFO]
[INFO] --------------------< org.example:child-project-3 >---------------------
[INFO] 构建 child-project-3 1.0-SNAPSHOT [4/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ child-project-3 ---
[INFO] 删除 F:\maven-project\child-project-3\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ child-project-3 ---
[WARNING] 使用平台编码(实际上是 Cp1252)复制已筛选的资源,即构建依赖于平台!
[INFO] 复制 0 个资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ child-project-3 ---
[INFO] 检测到更改 - 重新编译模块!
[WARNING] 尚未设置文件编码,使用平台编码 Cp1252,即构建依赖于平台!
[INFO] 正在将 1 个源文件编译到 F:\maven-project\child-project-3\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ child-project-3 ---
[INFO] 未复制测试资源
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ child-project-3 ---
[INFO] 未编译测试源
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ child-project-3 ---
[INFO] 跳过测试。
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar(default-jar)@ child-project-3 ---
[INFO] 构建 jar:F:\ maven-project \child-project-3 \target \child-project-3-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install(default-install)@ child-project-3 ---
[INFO] 将 F:\ maven-project \child-project-3 \target \child-project-3-1.0-SNAPSHOT.jar 安装到 C:\ Users \subra.m2 \repository \org \example \child-project-3 \1.0-SNAPSHOT \child-project-3-1.0-SNAPSHOT.jar
[INFO] 将 F:\ maven-project \child-project-3 \pom.xml 安装到C:\Users\subra.m2\repository\org\example\child-project-3\1.0-SNAPSHOT\child-project-3-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] maven-project 1.0-SNAPSHOT 的反应堆摘要:
[INFO]
[INFO] maven-project ...................................... 成功 [ 0.327 秒]
[INFO] child-project-1 .................................... 成功 [ 1.208 秒]
[INFO] child-project-2 .................................... 成功 [ 0.205 秒]
[INFO] child-project-3 .................................... 成功 [ 0.167 秒]
[INFO] ------------------------------------------------------------------------
[INFO] 构建成功
[INFO] ------------------------------------------------------------------------
[INFO] 总时间:2.055 秒
[INFO] 完成时间:2020-12-05T23:00:13 + 01:00
[INFO] ------------------------------------------------------------------------
If you observe the logs carefully, you can see that the test-execution is skipped:
[INFO] 未编译测试源
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ child-project-3 ---
[INFO] 测试被跳过。
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ child-project-3 ---
[INFO] 正在构建 jar:F:\maven-project\child-project-3\target\child-project-3-1.0-SNAPSHOT.jar
This is just a simple usage of the profiles, you can configure multiple profiles in our project to customize the build behavior.
# Conclusion<a name="chapter-30"></a>
So we came to the end of this tutorial, I hope this tutorial improved your understanding of Maven.
#### If you like this article please make sure to share it with your friends and colleagues who wants to learn about Apache Maven. You can follow me through my [blog](https://https://programmingtechie.com/), [Youtube Channel](https://www.youtube.com/channel/UCD20RZV_WHQImisCW2QZwDw) and [Twitter](https://twitter.com/sai90_u)