POM简介
项目对象模型(POM)是Maven处理的基本单位。它是Maven用来构建工程的一个xml文件,其中包含了工程相关的信息。它包含了大多数工程的默认值,例如build目录的名称是target、源文件的目录是src/main/java以及测试源目录是src/main/test等等。
POM文件的名称由Maven1中的project.xml变成了Maven2中的pom.xml。作为Maven1中包含执行目标的maven.xml文件,Maven2中目标和插件都配置在pom.xml文件中。当执行一个任务/目标时,Maven在当前目录寻找POM、读取POM、获取配置信息,然后执行目标。
可以在POM中指定的配置信息包括工程依赖、可执行的插件或者目标、构建概要文件等等。其他诸如项目版本、描述、开发者、邮件列表等也可以指定。
Super POM是Maven的默认POM。除非进行显示的设置,否则所有的POM扩展Super POM,这意味着Super POM中指定的配置将被其他的自定义工程的POM继承。下面的内容就是Super POM的内容:
<project>
<modelVersion>4.0.0</modelVersion>
<name>Maven Default Project</name>
<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Maven Plugin Repository</name>
<url>http://repo1.maven.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>
<build>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<finalName>${pom.artifactId}-${pom.version}</finalName>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
</build>
<reporting>
<outputDirectory>target/site</outputDirectory>
</reporting>
</project>
最简化的POM内容如下:
- 工程根节点
- modelVersion – 值为4.0.0
- groupId – 工程组的id
- artifactId – 工程的id
- version – 指定组下的工程id
例:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</project>
POM必须指定groupId、artifactId和version。这三个值是工程的全名,它的格式为<groupId>:<artifactId>:<version>。上面例子中的工程全名为"com.mycompany.app:my-app:1"。(译者注:在Maven中提到的artifact就是project的意思)
正如在第一部分所描述的,如果配置文件没有指定内容,Maven会使用默认的。package类型是其中张之一。所有的Maven工程都有一个打包(package)类型,如果在POM中没有指定,那么使用默认值jar。
正如你在所看到的,最简化POM中并没有指定repositories。如果使用最简化POM构建项目,它将继承Super POM文件中的repositories配置。因此,当Maven在最简化POM中遇到依赖的时候,它自动下载从http://repo1.maven.org/maven2下载依赖(这是在Super POM中指定的)。
POM被合并的元素有以下几个:
- 依赖
- 开发者和参与者
- 插件列表(包含报告)
- 匹配id的插件执行
- 插件配置
- 资源
Super POM 就是继承的一个例子,通过在POM中指定parent元素,你也可以描述自定义的父POMs。如下面例子中所述。
案例一
问题描述:
我们重新使用之前讨论的com.mycompany.app:my-app: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:my-module:1继承com.mycompany.app:my-app:1,我们需要在com.mycompany.app:my-module:1的POM 中做如下修改:
com.mycompany.app:my-module:1'的POM
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-module</artifactId>
<version>1</version>
</project>
注意,我们添加了一个parent元素。这个元素指定被当前POM继承的工程,然后指定被继承的工程的全名,通过这样,当前的模块可以继承父POM的一些属性。
如果自定义模块与父工程具有相同的groupId/version,可以通过移除groupId/version。
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
这允许模块继承groupId / version。
案例二
问题描述:
但是,只有在parent project已经安装在本地reposity或者在指定目录结构中时,这样的继承才起作用。(parent pom.xml的目录层次比模块的 pom.xml高)。
但是,如果父工程还没有安装,或者目录结构如下呢?
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
解决方案:
我们需要为parent元素添加relativePath标签来定位目录结构。
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<relativePath>.../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
如名称所示,是模块的pom.xml相对于父pom.xml的路径。
集成:
工程集成和工程继承类似。只是它通过在parent POM中指定模块,而不是在模块POM中指定parentPOM。这样父工程就可以知道它的模块,如果maven命令执行父工程的时候,maven命令也会执行模块。为了实现工程集成,需要做的工作如下:
- 修改parent POM的packaging的值,使其为"pom"
- 在parent POM中指定模块的目录
案例三
问题描述:
继续使用之前的工程poms和目录结构:
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
解决方案:
假设我们要将my-module集成到my-app中,我们只需要修改my-app。
<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:my-app:1中,添加了packaging和modules元素。Packaging的值被设置为"pom",modules元素的值为<module>my-module</module>。<module>元素的值是com.mycompany.app:my-module:1相对于com.mycompany.app:my-module:1's POM的路径 (通过实践,使用artifactId 作为目录名)。
此时,每当maven命令执行com.mycompany.app:my-app:1的时候,同样也会执行against com.mycompany.app:my-module:1。
案例四
问题描述:
当我们将目录结构修改为下面的情况,又会怎么样呢?
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
Parent pom如何指定它的模块呢?
解决方案:
案例三就是解决的方案---通过指定相对路径。
<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>
当多个maven工程具有相同的配置,通过抽出相同的配置来进行重构,建立一个父工程,这样,可以通过使所有的maven工程继承父工程,父工程的配置将适用于他们。
当一组工程需要同时构建或者处理时,通过创建一个父工程,并在父工程中声明它的所有模块,这样,只需要构建或者处理父工程,所有的子工程就会同时被构建。
当然,继承与集成可以同时进行。只需要遵循下面三个规则:
- 在每个子POM中指定父POM
- 修改父POM的packaging的值为"pom"
- 在父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>
and this directory structure
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
解决方案:
遵循三个规则来实现工程的继承与集成:
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>
<packaging>pom</packaging>
<modules>
<module>../my-module</module>
</modules>
</project>
com.mycompany.app:my-module:1's POM
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
注: Profile的继承和POM的继承策略一样。
发表于 @ 2008年06月04日 12:39:00|编辑