第一次尝试翻译技术文档,希望不要被贻笑大方。
- 什么是POM?
- 超级 POM
- 最小化的 POM
- 项目继承规则
- Example 1
- Example 2
- 项目聚合规则
- Example 3
- Example 4
- 项目继承 vs 项目聚合
- Example 5
- 项目内插值和表达式
- 有效变量
What is a POM什么是POM?
target就是构建(build)目录; src/main/java就是源代码目录;src/main/test就是测试源代码目录,等等。
project.xml修给为pom.xml, 同时包含目标动作(goals,maven插件的执行目标动作)的maven.xml文件也被取消了, 现在目标动作或者插件也在pom.xml文件中配置了。 档执行一个任务(task)或目标动作(goal),Maven在当签名目录中查找POM, 读取POM, 获得配置关于这次执行任务的配置信息, 然后执行目标动作。
本项目的POM中可以明确一些配置信息、一些可执行的插件和目标动作、 构建配置属性, 等等,一些其他的信息,例如项目版本、描述开发者、邮件组也可以在这里面明确。
Super POM超级POM
除了明确设置,超级POM是Maven的默认POM,所有的POM都扩展至超级POM,这意味着你的项目继承了超级POM的配置信息,下面是Maven 2.0.x的超级POM的代码段:(译者注:Maven 3.0.3的超级POM是$M2_HOME/lib/maven-model-builder-3.0.3.jar中的org/apache/maven/model/pom-4.0.0.xml)
<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>
下面是Maven 2.1.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>${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>
Minimal POM最简配置的POM
最简配置的POM需要以下元素:
- project 根
- modelVersion - 应该配置为4.0.0
- groupId - 项目的groupID(译者注:这个和下面的两个构成了定位该项目的坐标的第一二三部分).
- 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会使用默认值。一个默认值是打包类型(packaging type),每一个Maven项目都有一个打包类型, 如果再POM没有被显式给出,那么默认值就是"jar"。
此外,正如你在最简配置的POM中看到的, repositories没有被显式给出, 如果你使用最简配置的POM, 它将继承超级POM中定义的repositories。因此在最简配置的POM中,Maven知道这里的依赖都将从超级POM中定义的http://repo1.maven.org/maven2这里下载.
Project Inheritance项目继承规则
POM中的下列元素会被合并:
- dependencies
- developers and contributors
- plugin lists (包括 reports)
- 相同ID的plugin executions
- plugin配置
- resources
超级POM就是项目继承的一个实例,然而你也可以在你的POM中使用parent元素显式指定继承关系,下面是一些范例。
Example 1范例1
作为一个例子,我们重用我们上面的部件: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:
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的权限定部件名。利用这些配置,我们的
模块my-module现在继承了父POM的一些属性.
此外,如果我们想让你的模块的groupId 和/或者 version和它的父POM一样,那么你可以在你的模块中移除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就继承了它的父POM。
Example 2范例2
场景
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的相对路径。
Project Aggregation项目聚合规则
项目聚合规则和项目继承规则非常相识,但是和在子模块中指定父POM不同的是,项目聚合规则是在目POM中显示指定子模块。在这个规则中父项目知道他包含哪些子模块,如果在父项目中执行Maven指令,那么这些Maven指令也在子模块中执行。为了实行项目聚合规则,你必须按如下方式来做:
- 修改父POM的packaging值为"pom"。(译者注:这个地方原文好像是少了一个',POM's写成了POMs,我理解maven同java一样是单继承的)
- 明确子模块的相对路径。
Example 3范例3
场景
仍然是用最初的部件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>
<module>my-module</module>, <module> 的值是相对com.mycompany.app:my-app:1的com.mycompany.app:my-module:1的POM的路径 (实践中,我们用部件的artifactId作为部件的路径名)。
现在, 只要Maven指令处理com.mycompany.app:my-app:1,那么同样的Maven指令也会处理com.mycompany.app:my-module:1。然而, 有些命令(goals中特别指出)能以不同的方式来处理聚合中的模块。
Example 4范例4
场景
如果我们把目录结构调整为如下方式:
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
那么父pom中怎么指定他的子模块呢?
解决方案
答案呢? - 和范例3一样,只要指示出子模块的相对路径就行了。
<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>
Project Inheritance vs Project Aggregation项目继承 vs 项目聚合
如果你有多个Maven项目,并且他们都是差不多的配置,你可以重构出一个父项目来放置相同的配置。这样,你只需要让你的Maven项目继承这个父项目就行了,这些配置就会自动应用到你所有的项目中。
如果你有一组项目一块构建或同时处理,你可以创建一个父项目,在这个父项目中显式声明这些项目作为其在模块。这样做了,你只需要构建父项目,子项目就会自动构建。
理所当然,你也可以同时使用继承和聚合规则。这意谓着你可以在你的模块中显式指定一个父项目,同时在父项目中显式指定你的模块作为他的子项目。你只需要遵循下面3个规则:
- 显式指定每一个子POM的父POM。
- 修改父POM的packaging值为"pom"。
- 在父POM中显示指定子POM的相对路径
Example 5范例5
场景
仍然再次使用最初的部件。
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
`-- parent
`-- pom.xml
解决方案
同时使用继承和聚合规则,你只需要使用者3个规则。
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>
注意: 个性参数配置(Profile)的继承规则和POM的继承策略是一致的。
Project Interpolation项目插入值和变量
Maven的实践方式鼓励我们:不要自我重复。 然而,有些条件下,你必须在多处使用同样的值,为确保同一个值只显示给定一次,Maven运行我们使用在POM中(当前所依赖的,help:effective-pom可以查看到的)自己定义的和系统预定义的变量。
project.version变量,你只需要应用如下:
<version>${project.version}</version>
一种因素需要考虑的就是这些变量是在继承之后被计算的,这意谓着如果父项目使用一个变量,这个变量在子项目中定义,那么父项目的变量的确也会应用这个子项目定义的变量。
Available Variables可用的变量
${project.groupId}, ${project.version}, ${project.build.sourceDirectory}等等。所有的取值可以参见POM说明。
project."作为前缀来引用。你也能看到一些是用pom作为前缀来引用的,或者完全省略前缀 - 这个格式现在不被推荐使用了,最好别用。
特殊的变量
basedir | 当前项目的目录 |
project.baseUri | 当前项目的目录,表现为URI。(从Maven 2.1.0以后) |
maven.build.timestamp | 开始构建的时点(timestamp)。(从Maven 2.1.0-M1以后) |
构建时间的格式被属性maven.build.timestamp.format来定制,例如:
<project>
...
<properties>
<maven.build.timestamp.format>yyyyMMdd-HHmm</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>