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命令也将对父项目的模块执行。要进行项目聚合,必须执行以下操作:
- 将父pom包装更改为值“pom”。
- 在父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运行。此外,有些命令(特别是目标)处理项目聚合的方式不同。