?
Project Object Model,工程对象模型。是maven工作时的基本单元。它是一个工程信息和配置细节的xml文件,maven使用这些信息来构建整个工程。大多数工程包含了一些相同的缺省配置。
例如,构建目录target,源代码目录src/main/java,测试源代码目录src/test/java,等等。
POM在Maven1中的对应文件名为project.xml,而在maven2中改为pom.xml。执行目标或插件现在都在pom.xml中配置,而不是maven.xml文件。当执行一个任务或目标时,maven会搜索当前目录下的POM,读取POM,获取必需的配置信息,然后执行该目标。
一些配置信息会在POM中明确规定,如:dependencies, plugins, goals, build profiles等等。其他信息像project version, description, developers, mailing lists也会列出。
注意,一个工程应该只有一个POM文件。
一个POM的最低配置如下:
- project root (项目根元素 <project>)
- modelVersion - should be set to 4.0.0
- groupId - the id of the project's group. (工程组标识,在一个组织或项目中是唯一的)
- artifactId - the id of the artifact (project) (工程标识,通常是工程的名称。groupId与artifactId一起定义了artifact在仓库中的位置)
- version - the version of the artifact under the specified group(工程版本号,在artifact仓库中,用来区分不同的版本)
例子:
<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将会使用它们的缺省值。这些缺省值之一就有打包类型(packaging type)。任意一个maven工程都有一个packaging type。如果它没有在POM中指定,那就会使用缺省值JAR。
此外,就像在minimal POM中那样,repositories没有指定。如果你用minimal pom构建你的工程,它将会继承Super POM中的repositories配置。因此,当maven看到minimal pom中的依赖时,它会知道这个依赖可以从Super POM中指定的 下载。
Super POM是 maven 的缺省 POM。除了显式的设置以外,所有POM将扩展Super POM,这意味着Super POM中的配置将会被你为你的工程创建的POM继承。
MAVEN使用effective pom(Super pom + 自定义配置)来执行相关的目标,它帮助开发者在pom.xml中做尽可能少的配置,当然这些配置也可以被方便地重写 。
查看effective pom的命令: mvn help: effective-pom
工程继承.
POM中会被合并的元素如下:
- dependencies
- developers and contributors
- plugin lists (including reports)
- plugin executions with matching ids
- plugin configuration
- resources
父POM是工程继承的一个示例, 但你也可以通过在POM中指定父元素来引入你自己的父POM.
: 自定义parent POM
场景: 假设要将工程 com.mycompany.app:my-app:1 作为工程 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 section. 该section允许我们指定哪个工程作为我们的父POM. 我们在这里指定了父POM的全限定名.通过这样的设置,我们的module现在可以继承父POM的一些属性了.
或者,如果我们希望目标工程的groupId或者version和父工程一样, 就可以省略目标工程中的groupId或version标签~~~
: 自定义parent POM
场景: 例1的前提是父工程已经安装在我们的本地仓库中,或者在指定的目录结构中(父pom.xml是module的pom.xml的高一级目录)
如果父工程没有安装, 或者目录结构如下图所示:
为了定位到另一个目录结构,我们将需要添加<relativePath>元素到parent section中:
<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>
工程聚合,类似于工程继承.
但它是在父工程里指定module,而不是在module中指定父工程. 通过这样,父工程现在就知道了它的子模块, 如果对父工程调用 了一个maven命令, 该maven命令也会在父工程的module上执行.
为了实现 工程聚合, 你必须做以下2步:
- Change the parent POMs packaging to the value "pom" .
- Specify in the parent POM the directories of its modules (children POMs)
: 聚合module
场景: 将my-module工程聚合到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 section和module sections. 对于packaging, 它的值被设为 pom, 而对于 module section, 我们用了元素<module>来指定工程名, 它的全限定名为 com.mycompany.app:my-module:1.
现在, 当对 my-app 执行一个maven命令时,同样的命令将在 my-module上执行. 不过,有一些命令对于工程聚合的处理方式不一样.
: 聚合module
类似于例3, 不过要在<module>中指定路径.
工程继承 VS 工程聚合.
如果你有好几个maven工程,而且它们有着相似的配置, 你可以重构你的这些项目, 把相似的配置抽取出来, 作为一个父工程. 这样, 你需要做的就是让你的maven工程继承该父工程.
如果你有一组工程需要一起构建或处理, 你可以创建一个父工程, 然后把这些工程作为它的子模块. 通过这样, 你就只需要构建这个父工程.
当然, 你可以同时实现工程继承和工程聚合. 意思是,你可以让你的所有工程指定一个父工程, 同时, 那个父工程指定这些子工程为它的模块. 你只需要应用以下3条规则:
- Specify in every child POM who their parent POM is.
- Change the parent POMs packaging to the value "pom" .
- Specify in the parent POM the directories of its modules (children POMs)
and Variables
maven提倡的一条经验是,不要重复你自己. 然而,在很多情况下,你需要在好几个不同的位置使用同一个值. 为了确保这些值是特定的一个, maven允许你使用你自己的和预定义的变量.
例如, 为了获取变量project.version, 你需要这样引用它: <version>${project.version}</version>
如果一个父工程使用了一个变量, 那么在子工程中的定义将会是最终使用的那个.
Available Variable
1. 工程模型变量
模型中的任意域(单一值元素),可以作为一个变量被引用. 例如,${project.groupId}, ${project.version}, ${project.build.sourceDirectory}等等.
这些变量的引用的前缀都是"project."
2. 特殊变量
project.basedir
The directory that the current project resides in.project.baseUri
The directory that the current project resides in, represented as an URI. Since Maven 2.1.0maven.build.timestamp
The timestamp that denotes the start of the build. Since Maven 2.1.0-M13. 属性<properties>