什么是POMjava
项目对象模型即POM是Maven的基本工做单元.它是一个包含了项目信息和Maven用来构建项目的配置详情的XML文件.对大多数项目来讲它包含了默认值.例如默认的构建目录是target;默认的源码目录是src/main/java;默认的测试目录是src/test/java等等.apache
POM从Maven1.0中的project.xml从新命名成Maven2中的pom.xml.在Maven2中,取代了本来有个maven.xml文件来包含那些能被执行的目标,如今咱们直接将插件目标配置到pom.xml中.当执行任务或目标时,Maven会搜索当前目录下的POM.它读取POM,获取必要的配置信息,而后执行插件目标.api
能够被指定到POM文件中的配置有:项目依赖,能够被执行的插件目标,构建配置等等.其余诸如项目版本,描述,开发人员,邮件列表灯信息也同样能够被指定.bash
超级POMapp
超级POM是Maven的默认POM.全部的POM都继承它除非你显示的设置不那么作.这意味着在超级POM中指定的配置将会在你为你项目建立的POM中获得继承.下面是Maven2.0.x的超级POM的片断:maven
<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的片断:ide
<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至少须要包含以下信息:ui
<project>根节点this
<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>