什麼是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>