什么是POM
项目对象模型即POM是Maven的基本工作单元.它是一个包含了项目信息和Maven用来构建项目的配置详情的XML文件.对大多数项目来说它包含了默认值.例如默认的构建目录是target;默认的源码目录是src/main/java;默认的测试目录是src/test/java等等.
POM从Maven1.0中的project.xml重新命名成Maven2中的pom.xml.在Maven2中,取代了原本有个maven.xml文件来包含那些能被执行的目标,现在我们直接将插件目标配置到pom.xml中.当执行任务或目标时,Maven会搜索当前目录下的POM.它读取POM,获取必要的配置信息,然后执行插件目标.
可以被指定到POM文件中的配置有:项目依赖,可以被执行的插件目标,构建配置等等.其他诸如项目版本,描述,开发人员,邮件列表灯信息也一样可以被指定.
超级POM
超级POM是Maven的默认POM.所有的POM都继承它除非你显示的设置不那么做.这意味着在超级POM中指定的配置将会在你为你项目创建的POM中得到继承.下面是Maven2.0.x的超级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>${artifactId}-${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>
<profiles>
<profile>
<id>release-profile</id>
<activation>
<property>
<name>performRelease</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Maven2.1.x的片段:
<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>${project.basedir}/target</directory>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<!-- TODO: MNG-3731 maven-plugin-tools-api < 2.4.4 expect this to be relative... -->
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
</testResource>
</testResources>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.3.1</version>
</plugin>
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.1</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.4.3</version>
</plugin>
<plugin>
<artifactId>maven-rar-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0-beta-8</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.3</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>2.0-beta-7</version>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.0.4</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-alpha-2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<reporting>
<outputDirectory>${project.build.directory}/site</outputDirectory>
</reporting>
<profiles>
<profile>
<id>release-profile</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
最小的POM
一个POM至少需要包含如下信息:
<project>根节点
<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,version.这三个值形成项目的完全限定名,格式是<groupId>:<artifactId>:<version>.如上例所示,项目的完全限定名是:"com.mycompany.app:my-app:1".
而且,正如第一章提到的,如果配置明细没有被指定,Maven会使用默认值.其中之一是打包类型.每个Maven项目都有一个打包类型.如果没被显示指定,默认使用"jar".
另外,正如你在最小POM中看到的,仓库没有被指定.如果你用最小POM来构建你的项目,它会从超级POM中继承仓库配置.因此,当Maven在最小POM中查找依赖时,他会知道从超级POM中指定的URL:http://repo.maven.apache.org/maven2下载相关依赖.
项目继承
POM中合并的元素如下:
dependencies
developers和contributors
插件lists(包括reports)
被匹配ID的插件executions
插件configuration
resources
超级POM是项目继承的一个例子,然而你依然可以介绍自己的父POM通过在POM中指定parent元素,演示如下:
例一
场景:作为一个例子,让我们重用之前的工件(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-app:1 变成 com.mycompany.app:my-module: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元素.这部分内容允许我们指定该POM的父工件.而且我们通过指定父POM的完全限定符来实现这点.通过这一步骤,我们的模块可以从父POM中继承些属性了.
如果我们想使用和父POM相同的groupId和version,那么我们可以在当前的POM中省略它们:
<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>
这允许当前POM继承父POM的groupId和version.
例二
场景:不论如何,如果父项目已经被安装到我们的本地仓库或者在指定的目录结构这都能工作(父POM在子模块POM的上一级目录下)
但是如果父项目没有安装或者它们的目录结构像这样:
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
解决方案:对于这样的目录结构(或者任何其他的目录结构),我们不得不对parent元素作如下修改:
<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到父POM的相对路径.
项目聚合
项目聚合和项目继承类似.但是它在父POM中指定modules元素而不是在模块POM中指定parent元素.通过这个操作,父项目就知道了它的子模块,而且如果一个Maven命令行在父项目中被执行,它们也会在子模块中被执行.要实现项目聚合,你需要这样做:
改变父项目的打包类型为"pom"
在父POM中指定它的子模块
例三
场景:给出前一个例子中的原始POM和目录结构
com.mycompany.app:my-app:1 的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 的POM:
<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整合到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"来覆盖默认值"jar",在modules部分,我们有一个子元素module,它的值是从 com.mycompany.app:my-app:1 POM到 com.mycompany.app:my-module:1 POM的相对路径.(通过实践,我们使用模块的artifactId来作为模块目录的名称)
现在,无论什么时候一个Maven命令处理 com.mycompany.app:my-app:1 ,都会又同样的命令来处理 com.mycompany.app:my-module:1 .另外,一些命令(目标明确的)以不同的方式处理项目聚合.
例四
场景:如果我们改变目录结构成这样
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
父POM如何指定它的子模块
解决方案:答案很简单,和例三一样(了解module元素值的含义就很容易明白)
<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>
项目继承vs项目聚合
如果你有一些Maven项目,它们的配置都类似.那么你可以重构你的项目通过提取类似的配置来创建一个父项目.这样,你需要做的就是让你的Maven项目继承这个父项目,那些配置也将被继承.
而如果你有一堆项目它们被一起构建或处理,你可以创建一个父项目并在那里声明其他项目作为它的子模块.这样,你只需要构建父项目,子模块也会被构建.
但是理所应当的,你可以同时使用项目继承和项目聚合.这意味着你可以在你的子模块中指定parent元素,同时,在你的父项目中指定那些Maven项目做为它的子模块.你只需要遵循下面三条规则:
在每个子POM中指定它们的父POM
改变父POM的打包类型为"pom"
在父POM中指定它的子模块
例五
场景:再次给出之前例子使用的POM
com.mycompany.app:my-app:1 的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 的POM:
<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
解决方案:你只需要应用上诉三条规则来同时使用继承和聚合
com.mycompany.app:my-app:1 的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 的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>
请注意:配置文件的继承策略和POM一样
项目插入和变量
Maven鼓励的做法之一是不要重复做一件事.然而,有些情况下你需要在不同的地方使用相同的值.为了促进确保这个值只被指定一次,Maven允许你在POM中使用预定义或者你自己定义的变量.
例如,为了访问project.version变量.你可以这样引用它:
<version>${project.version}</version>
需要注意的一点是这些变量在继承之后处理.这意味着如果一个父项目使用了一个变量,它的定义在子项目,而不在父项目,它将最终被使用.
可用的变量
项目模型变量
模型的任何一个单值元素都可以被有效引用.如,${project.groupId},${project.version},${project.build,sourceDirectory}等等.
这些变量通过一个前缀"project."来引用.你也可能见过用前缀"pom."甚至完全省略前缀的引用方式,但是这些格式都已经过期了而且我们不该再使用它.
特殊变量
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.0 |
maven.build.timestamp | The timestamp that denotes the start of the build. Since Maven 2.1.0-M1 |
构建时间戳的格式可以通过声明属性maven.build.timestamp.format来自定义:
<project>
...
<properties>
<maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ss'Z'</maven.build.timestamp.format>
</properties>
...
</project>
格式化模式和JAVA API中的SimpleDateFormat一致.如果属性不存在,默认格式就是例子中显示的那样.
属性
你也可以引用任何在你项目中定义的属性作为一个变量,如下所示:
<project>
...
<properties>
<mavenVersion>2.1</mavenVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>${mavenVersion}</version>
</dependency>
</dependencies>
...
</project>
来源:oschina
链接:https://my.oschina.net/u/2329798/blog/678671