POM简介

一、什么是POM?

项目对象模型(POM)是Maven中的基本工作单元。它是一个XML文件,包含有关项目的信息以及Maven用于构建项目的配置详细信息。它包含大多数项目的默认值。例如构建目录,它是目标;源目录,它是src/main/java;测试源目录,为src/test/java;等等。当执行任务或目标时,Maven会在当前目录中查找POM。它读取POM,获得所需的配置信息,然后执行目标。
POM中可以指定的一些配置包括项目依赖项、可以执行的插件或目标、构建配置文件等。还可以指定其他信息,如项目版本、描述、开发人员、邮件列表等。

二、超级POM

超级POM是Maven的默认POM。除非明确设置,否则所有POM都会扩展超级POM,这意味着超级POM中指定的配置将由您为项目创建的POM继承。

三、最小POM

POM的最低要求如下:

  • project root
  • modelVersion-应设置为4.0.0
  • groupId-项目组的id。
  • artifactId-工件(项目)的id
  • version-指定组下工件的版本

示例:

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

 POM要求配置其groupId、artifactId和版本。这三个值构成了项目的完全限定工件名称。其形式为<groupId>:<artifactId>:<版本>。对于上面的例子,其完全限定的工件名称是“com.mycompany.app:myApp:1”。
此外,正如第一节中提到的,如果没有指定配置细节,Maven将使用它们的默认值。其中一个默认值是打包类型。每个Maven项目都有一种打包类型。如果在POM中没有指定,那么将使用默认值“jar”。
此外,您可以看到在最小POM中没有指定存储库。如果您使用最小POM构建项目,它将继承Super POM中的存储库配置。因此,当Maven在最小POM中看到依赖项时,它就会知道这些依赖项将从https://repo.maven.apache.org/maven2其在Super POM中规定。

四、项目继承

合并的POM中的元素如下:

  • dependencies
  • developers and contributors
  • plugin lists (including reports)
  • plugin executions with matching ids
  • plugin configuration
  • resources

Super POM是项目继承的一个示例,但是您也可以通过在POM中指定父元素来引入自己的父POM,如以下示例所示。 

1、Example 1

场景

举个例子,让我们重用我们以前的工件com.mycompany.app:myApp:1。让我们介绍另一个工件,com.mycompany.app:my-module:1.

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-module</artifactId>
  <version>1</version>
</project>

让我们指定它们的目录结构如下:

.
 |-- my-module
 |   `-- pom.xml
 `-- pom.xml

注:my-module/pom.xml是com.mycompany.app:my-module:1的pom,pom.xml是com.mycompany.app:my-app:1的pom

解决方案

现在,如果我们要将com.mycompany.app:myApp:1变成com.mycompany.app:my-module:1的父工件,我们必须将com.mycompany.app:my-moduler:1的POM修改为以下配置:

com.mycompany.app:my-module:1's POM

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
  </parent>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-module</artifactId>
  <version>1</version>
</project>

请注意,我们现在添加了一个部分,即父部分。本节允许我们指定哪个工件是POM的父工件。我们通过指定父POM的完全限定工件名称来实现这一点。有了这个设置,我们的模块现在可以继承父POM的一些属性。
或者,如果您希望模块的groupId或版本与其父模块相同,则可以在其POM中删除模块的groupId或版本标识。

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
  </parent>
 
  <artifactId>my-module</artifactId>
</project>

 2、Example 2

场景

然而,如果父项目已经安装在我们的本地存储库中,或者位于特定的目录结构中(父pom.xml比模块的pom.xml高一个目录),那么这将起作用。
但是,如果父目录尚未安装,并且目录结构如以下示例所示,该怎么办?

.
 |-- my-module
 |   `-- pom.xml
 `-- parent
     `-- pom.xml

解决方案 

为了解决这个目录结构(或任何其他目录结构),我们必须将<relativePath>元素添加到父节中。

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
    <relativePath>../parent/pom.xml</relativePath>
  </parent>
 
  <artifactId>my-module</artifactId>
</project>

顾名思义,它是从模块的pom.xml到父级pom.xml的相对路径。

五、项目聚合

项目聚合类似于项目继承。但是,它不是从模块中指定父POM,而是从父POM中指定模块。通过这样做,父项目现在知道了它的模块,如果对父项目调用Maven命令,那么该Maven命令也将对父项目的模块执行。要进行项目聚合,必须执行以下操作: 

  1. 将父pom包装更改为值“pom”。
  2. 在父POM中指定其模块(子POM)的目录。

 Example 3

场景

给定先前的原始工件POM和目录结构:

com.mycompany.app:my-app:1's POM

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

com.mycompany.app:my-module:1's POM

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-module</artifactId>
  <version>1</version>
</project>

 directory structure

.
 |-- my-module
 |   `-- pom.xml
 `-- pom.xml

解决方案 

如果我们要将我的模块聚合到我的应用程序中,我们只需要修改我的应用。

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  <packaging>pom</packaging>
 
  <modules>
    <module>my-module</module>
  </modules>
</project>

在修订后的com.mycompany.app:myApp:1中,添加了包装部分和模块部分。对于包装,它的值被设置为“pom”,对于模块部分,我们有元素<module>my-module</module>。<module>的值是从com.mycompany.app:myApp:1到com.mycompany.app:my-module:1的POM的相对路径(在实践中,我们使用模块的artifactId作为模块目录的名称)。
现在,每当Maven命令处理com.mycompany.app:myApp:1时,同样的Maven命令也会针对com.mycompany.app:my-module:1运行。此外,有些命令(特别是目标)处理项目聚合的方式不同。