POM 简介
- Maven是什么?
- 超级 POM
- 最小的 POM
- 项目继承
- 示例 1
- 示例 2
- 项目聚集
- 示例 3
- 示例 4
- 项目继承 vs 项目聚合
- 示例 5
- 项目插值和变量
- 可用变量
Maven是什么?
项目对象模型或 POM 是工作的 Maven 的基本单位。它是一个 XML 文件,其中包含有关 Maven 用于生成项目的项目和配置的详细信息。它包含大多数项目的默认值。这个例子是生成目录,是目标;源目录,是src/主/java;测试源目录中,这是src/测试/java;等等。
POM 从project.xml在 Maven 1 更名pom.xml Maven 2 中。而不是有标记的文件,其中包含可执行的目标,目标或插件现在已配置在pom.xml中。当执行一个任务或目标,Maven POM 当前目录中查找。它读取 POM,获取所需的配置信息,然后执行目标。
一些可以在 POM 中指定的配置是项目依赖项、 插件或目标可以执行,生成配置文件,等等。也可以指定其他信息,如项目版本、 描述、 开发商、 邮件列表等。
超级 POM
超级 POM 是 Maven 的默认 POM。所有 POMs 都延长超级 POM 除非显式集合,这意味着超级 POM 中指定的配置继承您为您的项目创建的锤炼。下面的代码片段是 Maven 超级 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>
下面的代码片段是超级 POM 的 Maven 2.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 的最低要求如下所示:
- 项目根
- modelVersion-应设置为 4.0.0
- groupId-该项目组的 id。
- artifactId-工件 (项目) 的 id
- 版本-指定组下工件的版本
下面是一个示例:
- <project>
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.mycompany.app</groupId>
- <artifactId>my-app</artifactId>
- <version>1</version>
- </project>
POM 需要配置其 groupId、 artifactId 和版本。这三个值形成项目的工件完全限定的名称。这是形式的 < groupId >: < artifactId >: < 版本 >。对于上面的例子中,其完全限定的项目名称是"com.mycompany.app:my-app:1"。
此外,在第一节中,提到如果未指定的配置详细信息,Maven 将使用它们的默认值。这些默认值中的一个是包装类型。每一个 Maven 项目的包装类型。如果它不在 POM 中指定,则将使用默认值"罐"。
此外,你可以看到,在最小的 POM 中,未指定存储库。如果您使用最小的 POM 的项目生成时,它会继承中超级 POM 的存储库配置。因此当 Maven 看到中最小的 POM 的依赖关系,它会知道,这些依赖项将从http://repo.maven.apache.org/maven2超级 POM 中指定的下载。
项目继承
在 POM 中合并的内容如下:
- 依赖项
- 开发者和贡献
- 插件列表 (包括报告)
- 具有匹配 id 的插件处决
- 插件配置
- 资源
超级 POM 是项目继承的一个例子,不过可以自己父 POMs 介绍通过在 POM 中指定的父元素,如下面的示例所示。
示例 1
场景
作为一个例子,让我们重复使用我们以前的神器,com.mycompany.app:my-app:1。让我们介绍另一个工件,com.mycompany.app:my-模块: 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
注:我模块/pom.xml是 com.mycompany.app:my POM-模块: 1 虽然pom.xml是 POM 的 com.mycompany.app:my-app:1
解决方案
现在,如果我们把 com.mycompany.app:my-app:1 到 com.mycompany.app:my 父项目-模块: 1,我们将不得不修改 com.mycompany.app:my-模块: 1 POM 对以下配置:
com.mycompany.app:my-模块: 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>
11. </project>
请注意,我们现在有添加的部分,父节。本节允许我们指定哪个工件是我们 POM 的父级。我们这样做是通过指定父 POM 的工件完全限定的名称。与此设置中,我们的模块现在可以继承的一些我们的父 POM 的属性。
或者,如果我们想要的 groupId 和/或您的模块要他们的父母一样的版本,你可以删除 groupId 和/或您的模块的版本标识在其 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>
这允许模块继承 groupId 及/或其父 POM 的版本。
[顶]
示例 2
场景
然而,如果父项目在我们本地资源库中已经安装了或在那个特定的目录结构,将工作 (父pom.xml是一个目录高于模块的pom.xml).
但如果尚未安装父,如果该目录结构是
- .
- |-- my-module
- | `-- pom.xml
- `-- parent
- `-- pom.xml
解决方案
要解决这种目录结构 (或任何其他的目录结构),我们将不得不将< 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>
10. </project>
顾名思义,它是从模块的pom.xml到父pom.xml的相对路径.
项目聚集
项目聚集是类似于项目继承。但是,而不是指定父 POM 从模块,它指定了从父 POM 模块。通过这样做,父项目现在知道其模块,如果对父项目调用 Maven 命令,然后将到父模块以及执行那 Maven 命令。做项目聚集,必须执行以下操作:
- 更改父 POMs 包装为"Maven"的值。
- 在父 POM 中指定的目录及其模块 (儿童 POMs)
[顶]
示例 3
场景
鉴于以前的原始工件 POMs 和目录结构
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-模块: 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
解决方案
如果我们到聚合成我 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>
- 10. </modules>
11. </project>
在修订后的 com.mycompany.app:my-app:1,包装部分和模块部分增加了。包装用,其值设置为"pom"和模块部分中,我们有了元素< > 我模块 < / 模块 >。< 模块 >的值是从 com.mycompany.app:my 的相对路径-app:1 到 com.mycompany.app:my-模块: 1 POM (通过实践,我们使用的模块 artifactId 作为模块目录的名称).
现在,每当一个 Maven 命令处理 com.mycompany.app:my-app:1,同一 Maven 命令会过一个反对 com.mycompany.app:my-以及模块: 1。此外,一些命令 (目标明确) 以不同的方式处理项目聚集。
示例 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>
11. </project>
项目继承 vs 项目聚合
如果你有几个 Maven 项目,并且他们都有类似的配置,您可以通过拔出这些类似的配置,使父项目重构您的项目。因此,所有你需要做是让你继承该父项目的 Maven 项目,这些配置然后将适用于所有人。
如果你有一组项目,兴建或一起处理,可以创建一个父项目和已申报这些项目作为其模块的父项目。通过这样做,你只会打造父和榜样的力量。
但当然,你可以有项目继承和项目聚集。含义,可以有您的模块指定的父项目,和在同一时间,有作为其模块指定那些 Maven 项目的父项目。只要你要应用所有的三个规则:
- 指定在每个孩子 POM POM 的父母是。
- 更改父 POMs 包装为"POM"的值。
- 在父 POM 中指定的目录及其模块 (儿童 POMs)
示例 5
场景
再次,鉴于以前的原始工件 POMs
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-模块: 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
解决方案
对两个项目继承和聚集,你只需要应用所有的三个规则。
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>
- 10. </modules>
11. </project>
com.mycompany.app:my-模块: 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>
10. </project>
注:配置文件继承相同的继承策略用于为 POM 本身。
项目插值和变量
Maven 鼓励的做法之一就是不要重复你自己。然而,有的情况下将需要在几个不同的位置使用相同的值。为了帮助确保只有一次指定的值,Maven 允许您使用两个你自己和预定义变量在 POM 中的。
例如,若要访问project.version变量,你会引用它像这样:
- <version>${project.version}</version>
要注意的一个因素是这些变量是加工后的继承,如上文所述。这意味着如果父项目中使用的变量,然后在孩子,不是父母,其定义将是最终使用。
可用变量
项目模型变量
任何领域的模式,是单个值元素可以作为一个变量引用。例如, ${project.groupId} ${project.version} ${project.build.sourceDirectory} 、 等等。请参阅 POM 参考看看的属性的完整列表。
这些变量都引用由前缀"项目。"。您还可能看到与pom。引用作为前缀或完全省略的前缀 — — 这些形式现已被否决,不应使用。
特殊的变量
project.basedir |
当前的项目所在的目录。 |
project.baseUri |
当前项目中,驻留的目录表示为一个 URI。因为 Maven 2.1.0 |
maven.build.timestamp |
表示开始生成的时间戳。因为 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>
格式模式一定要遵守有关SimpleDateFormat的 API 文档中给出的规则。如果不存在该属性,则格式默认为已经将本例中给定的值。
属性
你也是能够引用一个变量作为项目中定义的任何属性。请考虑下面的示例:
- <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>
- ...
19. </project>
maven多模块项目
maven多模块项目需要一个父工程来聚合各个子模块,不过其实就是需要一个父pom.xml,主要作用是声明子模块,代码如下:
<modules>
<module>modules1</module>
<module>modules2</module>
</modules>
然后在子模块中,声明父工程,子模块中代码如下:
<parent>
<groupId>com.iwooto</groupId>
<artifactId>root</artifactId>
<version>5.0</version>
<relativePath>../..</relativePath>
</parent>
关于多模块的文章,网上有很多,也都很详细,这里不再多说。
maven多web合并项目
多web项目合并,主要是我在网上找到的资料都不是我最终想要的效果,所以这里就介绍下我最终使用的方案,网上有很多方案都是介绍用caro插件,我到现在也不明白为什么要使用这个插件。
maven的多web模块maven-war-plugin插件的overlays属性来处理,最终主web项目pom.xml代码如下
<build>
<finalName>mywebapp</finalName>
<plugins>
<!-- 合并多个war -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
<overlays>
<overlay>
<groupId>com.iwooto</groupId>
<artifactId>mymodules2</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
</plugins>
</build>
这里使用到了maven-war-plugin,用overlay属性已经足够将多web合并了,只是用的过程中需要注意以下几点:
- 被合并的子web项目packaging属性必须是war
- 被合并的子web项目,必须在主项目中添加依赖关系。
- 被合并的子web项目中,如果没有web.xml,则需要在pom.xml中声明
- <build>
- <finalName>mymodules2</finalName>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <configuration>
- <failOnMissingWebXml>false</failOnMissingWebXml>
- </configuration>
- </plugin>
- </plugins>
</build>
做完以上几点,多web项目合并就基本上做完了,运行mvn install就会发现打出的war包中已经存在了其他子模块的项目。
多web项目在eclipse+tomcat环境下部署调试
在eclipse里面使用,其实更简单,只是网上的说法太复杂了而已,对于习惯了tomcat开发的用户来说。
对于maven项目,一个环境到另一个环境应该只有pom.xml文件和src文件夹就够了,其他都是用户根据自己的环境来做的。
- 打开eclipse,修改本地maven仓库地址,导入maven项目,等待构建结束。
- 创建server,打开window-prefrences-server-runTime Environment-new ....选择tomcat路径,jdk信息,这一步和原来完全一样。
- 打开server视图,new server,这里选中刚才创建的tomcat,点击next,这步只需要主web项目添加进来即可。
- 双击创建的server,选择将项目发布到tomcat的webapps目录下,点击pushlish,完成。
再去tomcat目录,发现已经将合并后的web发布到对应目录下了。 引用的其他Java项目已经被打包成jar发布到lib下了,不过你可以打个断点试试,依然可以调试,修改一段代码,发现热部署也是可以的,这样就和原来的开发习惯完全一样了。
细心的用户会发现,其实这完全和我们原来的构建,部署方式完全一样,是的,maven没有那么复杂,m2eclipse maven plugin已经帮我们做好了太多的事情,maven只会让我们项目之间的迁移更方便,更简洁,这也是我喜欢上maven的重要原因。
我是一个绝对的maven新手,上面的文章用的也只是maven的皮毛而已,maven更多的构建功能还需要深入去研究,上面文章只是想告诉那些想尝试maven的新手,其实maven不但对代码管理带来了很大的方便,而且完全可以不改变我们原有的开发习惯。所以,尽情的拥抱maven吧!
个人博客地址:http://www.iwooto.com