參考資料:
- http://ifeve.com/maven-1/
- http://ifeve.com/maven-2/
- 基本標簽內(nèi)容說明: http://www.cnblogs.com/zz0412/p/Maven_pom.html
Maven概覽-核心概念
Maven的中心思想是POM文件(項目對象模型)。POM文件是以XML文件的形式表述項目的資源,如源碼、測試代碼、依賴(用到的外部Jar包)等。POM文件應該位于項目的根目錄下。
下圖說明了Maven是如何使用POM文件的,以及POM文件的主要組成部分:

- POM文件
當你執(zhí)行一條Maven命令的時候,你會傳入一個pom文件。Maven會在該pom文件描述的資源上執(zhí)行該命令。
- 構(gòu)建生命周期、階段和目標
Maven的構(gòu)建過程被分解為構(gòu)建生命周期、階段和目標。一個構(gòu)建周期由一系列的構(gòu)建階段組成,每一個構(gòu)建階段由一系列的目標組成。當你運行Maven的時候,你會傳入一條命令。這條命令就是構(gòu)建生命周期、階段或目標的名字。如果執(zhí)行一個生命周期,該生命周期內(nèi)的所有構(gòu)建階段都會被執(zhí)行。如果執(zhí)行一個構(gòu)建階段,在預定義的構(gòu)建階段中,所有處于當前構(gòu)建階段之前的階段也都會被執(zhí)行。
- 依賴和倉庫
Maven執(zhí)行時,其中一個首要目標就是檢查項目的依賴。依賴是你的項目用到的jar文件(java庫)。如果在本地倉庫中不存在該依賴,則Maven會從中央倉庫下載并放到本地倉庫。本地倉庫只是你電腦硬盤上的一個目錄。你可以根據(jù)需要制定本地倉庫的位置。你也可以指定下載依賴的遠程倉庫的地址。這些將會在后續(xù)的小節(jié)中詳細介紹。
- 插件
構(gòu)建插件可以向構(gòu)建階段中增加額外的構(gòu)建目標。如果Maven標準的構(gòu)建階段和目標無法滿足項目構(gòu)建的需求,你可以在POM文件里增加插件。Maven有一些標準的插件供選用,如果需要你可以自己實現(xiàn)插件。
- 配置文件
配置文件用于以不同的方式構(gòu)建項目。比如,你可能需要在本地環(huán)境構(gòu)建,用于開發(fā)和測試,你也可能需要構(gòu)建后用于開發(fā)環(huán)境。這兩個構(gòu)建過程是不同的。在POM文件中增加不同的構(gòu)建配置,可以啟用不同的構(gòu)建過程。當運行Maven時,可以指定要使用的配置。
- 父pom
所有的Maven pom文件都繼承自一個父pom。如果沒有指定父pom,則該pom文件繼承自根pom。pom文件的繼承關(guān)系如下圖所示:

可以讓一個pom文件顯式地繼承另一個pom文件。這樣,可以通過修改公共父pom文件的設置來修改所有子pom文件的設置。在pom文件的起始處指定父pom,例如:
<project xmlns=”http://maven.apache.org/POM/4.0.0″
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<relativePath>../my-parent</relativePath>
</parent>
<artifactId>my-project</artifactId>
…
</project>
子pom文件的設置可以覆蓋父pom文件的設置,只需要在子pom文件里指定新的設置即可。
關(guān)于pom文件繼承更詳細的內(nèi)容可以參考Maven POM文檔。
- 有效pom
考慮到pom文件的繼承關(guān)系,當Maven執(zhí)行的時候可能很難確定最終的pom文件的內(nèi)容。總的pom文件(所有繼承關(guān)系生效后)被稱為有效pom(effective pom)。可以使用以下的命令讓Maven打印出當前的有效pom:
mvn help:effective-pom
執(zhí)行以上命令,Maven會將有效pom輸出到命令行。
Maven目錄結(jié)構(gòu)
Maven有一個標準的目錄結(jié)構(gòu)。如果你在項目中遵循Maven的目錄結(jié)構(gòu),就無需在pom文件中指定源代碼、測試代碼等目錄。
以下為最重要的目錄:
- src
- main
- java
- resources
- webapp
- test
- java
- resources
- target
src目錄是源代碼和測試代碼的根目錄。main目錄是應用的源代碼目錄。test目錄是測試代碼的目錄。main和test下的java目錄,分別表示應用的java源代碼和測試代碼。
resources目錄包含項目的資源文件,比如應用的國際化配置的屬性文件等。
如果是一個web項目,則webapp目錄為web項目的根目錄,其中包含如WEB-INF等子目錄。
target目錄是由Maven創(chuàng)建的,其中包含編譯后的類文件、jar文件等。當執(zhí)行maven的clean目標后,target目錄會被清空。
- 項目依賴
Maven內(nèi)嵌有依賴管理的功能。你只需要在pom文件里指定依賴jar包的名稱、版本號,Maven會自動下載并放到你的Maven本地倉庫中。如果這些外部jar包依賴了其它的庫,它們也會被下載到你的Maven本地倉庫。 - 外部依賴
Maven的外部依賴指的是不在Maven的倉庫(包括本地倉庫、中央倉庫和遠程倉庫)中的依賴(jar包)。它可能位于你本地硬盤的某個地方,比如web應用的lib目錄下。這里的“外部”是對Maven倉庫系統(tǒng)而言的,不僅僅是對項目而言的。大部分的外部依賴都是針對項目的,很少的外部依賴是針對倉庫系統(tǒng)的(即不在倉庫中)。
配置外部依賴的示例如下:
<dependency>
<groupId>mydependency</groupId>
<artifactId>mydependency</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${basedir}\war\WEB-INF\lib\mydependency.jar</systemPath>
</dependency>
- 快照依賴
快照依賴指的是那些還在開發(fā)中的依賴(jar包)。與其經(jīng)常地更新版本號來獲取最新版本,不如你直接依賴項目的快照版本??煺瞻姹镜拿恳粋€build版本都會被下載到本地倉庫,即使該快照版本已經(jīng)在本地倉庫了??偸窍螺d快照依賴可以確保本地倉庫中的每一個build版本都是最新的。
在pom文件的最開頭(設置groupId和artifactId的地方),在版本號后追加-SNAPSHOT,則告訴Maven你的項目是一個快照版本。如:
<version>1.0-SNAPSHOT</version>
可以看到加到版本號后的-SNAPSHOT。
Maven倉庫
Maven倉庫就是存儲jar包和一些元數(shù)據(jù)信息的目錄。其中的元數(shù)據(jù)即pom文件,描述了該jar包屬于哪個項目,以及jar包所需的外部依賴。該元數(shù)據(jù)信息使得Maven可以遞歸地下載所有的依賴,直到整個依賴樹都下載完畢并放到你的本地倉庫中。
Maven有三種類型的倉庫:
- 本地倉庫---本地倉庫就是開發(fā)者電腦上的一個目錄。該倉庫包含了Maven下載的所有依賴。一般來講,一個本地倉庫為多個不同的項目服務。因此,Maven只需下載一次,即使有多個項目都依賴它.通過mvn install命令可以將你自己的項目構(gòu)建并安裝到本地倉庫中。這樣,你的其它項目就可以通過在pom文件將該jar包作為外部依賴來使用。
- 中央倉庫---Maven的中央倉庫由Maven社區(qū)提供。默認情況下,所有不在本地倉庫中的依賴都會去這個中央倉庫查找。然后Maven會將這些依賴下載到你的本地倉庫。訪問中央倉庫不需要做額外的配置。
- 遠程倉庫---遠程倉庫是位于web服務器上的一個倉庫,Maven可以從該倉庫下載依賴,就像從中央倉庫下載依賴一樣。遠程倉庫可以位于Internet上的任何地方,也可以是位于本地網(wǎng)絡中。遠程倉庫一般用于放置組織內(nèi)部的項目,該項目由多個項目共享。比如,由多個內(nèi)部項目共用的安全項目。該安全項目不能被外部訪問,因此不能放在公開的中央倉庫下,而應該放到內(nèi)部的遠程倉庫中。遠程倉庫中的依賴也會被Maven下載到本地倉庫中??梢栽趐om文件里配置遠程倉庫。將以下的xml片段放到屬性之后:
<repositories>
<repository>
<id>jenkov.code</id>
<url>http://maven.jenkov.com/maven2/lib</url>
</repository>
</repositories>
Maven根據(jù)以上的順序去倉庫中搜索依賴。首先是本地倉庫,然后是中央倉庫,最后,如果pom文件中配置了遠程倉庫,則會去遠程倉庫中查找。
Maven的構(gòu)建生命周期、階段和目標
當使用Maven構(gòu)建項目時,會遵循一個構(gòu)建生命周期。該生命周期分為多個構(gòu)建階段,而構(gòu)建階段又分為多個構(gòu)建目標。
- 構(gòu)建生命周期
Maven有三個內(nèi)嵌的構(gòu)建生命周期: - default
- clean
- site
每一個構(gòu)建生命期關(guān)注項目構(gòu)建的不同方面。因此,它們是獨立地執(zhí)行的。Maven可以執(zhí)行多個生命期,但是它們是串行執(zhí)行的,相互獨立,就像你執(zhí)行了多條獨立的Maven命令。
default生命期關(guān)注的是項目的編譯和打包。clean生命期關(guān)注的是從輸出目錄中刪掉臨時文件,包括自動生成的源文件、編譯后的類文件,之前版本的jar文件等。site生命期關(guān)注的是為項目生成文檔。實際上,site可以使用文檔為項目生成一個完整的網(wǎng)站。
- 構(gòu)建階段
每一個構(gòu)建生命期被分為一系列的構(gòu)建階段,構(gòu)建階段又被分為構(gòu)建目標。因此,整個構(gòu)建過程由一系列的構(gòu)建生命期、構(gòu)建階段和構(gòu)建目標組成。
你可以執(zhí)行一個構(gòu)建生命期,如clean或site,一個構(gòu)建階段,如default生命期的install,或者一個構(gòu)建目標,如dependency:copy-dependencies。注意:你不能直接執(zhí)行default生命期,你需要指定default生命期中的一個構(gòu)建階段或者構(gòu)建目標。
當你執(zhí)行一個構(gòu)建階段時,所有在該構(gòu)建階段之前的構(gòu)建階段(根據(jù)標準構(gòu)建順序)都會被執(zhí)行。因此,執(zhí)行install階段,意味著所有位于install階段前的構(gòu)建階段都會被執(zhí)行,然后才執(zhí)行install階段。
default生命期更多的關(guān)注于構(gòu)建代碼。由于你不能直接執(zhí)行default生命期,你需要執(zhí)行其中一個構(gòu)建階段或者構(gòu)建目標。default生命期包含了相當多的構(gòu)建階段和目標,這里不會所有都介紹。最常用的構(gòu)建階段有:
構(gòu)建階段 描述
validate 驗證項目的正確性,以及所有必需的信息都是否都存在。同時也會確認項目的依賴是否都下載完畢。
compile 編譯項目的源代碼
test 選擇合適的單元測試框架,對編譯后的源碼執(zhí)行測試;這些測試不需要代碼被打包或者部署。
package 將編譯后的代碼以可分配的形式打包,如Jar包。
install 將項目打包后安裝到本地倉庫,可以作為其它項目的本地依賴。
deploy 將最終的包復制到遠程倉庫,與其它開發(fā)者和項目共享。
- 構(gòu)建目標
構(gòu)建目標是Maven構(gòu)建過程中最細化的步驟。一個目標可以與一個或多個構(gòu)建階段綁定,也可以不綁定。如果一個目標沒有與任何構(gòu)建階段綁定,你只能將該目標的名稱作為參數(shù)傳遞給mvn命令來執(zhí)行它。如果一個目標綁定到多個構(gòu)建階段,該目標在綁定的構(gòu)建階段執(zhí)行的同時被執(zhí)行。
Maven構(gòu)建配置
Maven構(gòu)建配置使你能使用不同的配置來構(gòu)建項目。不用創(chuàng)建兩個獨立的pom文件。你只需使用不同的構(gòu)建配置指定不同的配置文件,然后使用該配置文件構(gòu)建項目即可。
關(guān)于構(gòu)建配置的詳細信息可以參考Maven POM參考的Profile部分。這里是一個快速的介紹。
Maven的構(gòu)建配置在pom文件的profiles屬性中指定,例如:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jenkov.crawler</groupId>
<artifactId>java-web-crawler</artifactId>
<version>1.0.0</version>
<profiles>
<profile>
<id>test</id>
<activation>...</activation>
<build>...</build>
<modules>...</modules>
<repositories>...</repositories>
<pluginRepositories>...</pluginRepositories>
<dependencies>...</dependencies>
<reporting>...</reporting>
<dependencyManagement>...</dependencyManagement>
<distributionManagement>...</distributionManagement>
</profile>
</profiles>
</project>
構(gòu)建配置描述的是當使用該配置構(gòu)建項目時,對pom文件所做的修改,比如修改應用使用的配置文件等。profile屬性中的值將會覆蓋其上層的、位于pom文件中的配置。
在profile屬性中,有一個activation子屬性。該屬性指定了啟用該構(gòu)建配置的條件。選擇構(gòu)建配置的一種方式是在settings.xml文件中指定;另一種方式是在Maven命令行使用-P profile-name指定。更多細節(jié)參考構(gòu)建配置的文檔。
- build配置
可以使用build配置修改相關(guān)的plugins配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
- Maven插件
使用Maven插件,可以向構(gòu)建過程添加自定義的動作。創(chuàng)建一個簡單的Java類,該類繼承一個特殊的Maven類,然后為項目創(chuàng)建一個pom文件。該插件應該位于其項目下。
Maven本質(zhì)上是一個插件框架,它的核心并不執(zhí)行任何具體的構(gòu)建任務,所有這些任務都交給插件來完成,例如編譯源代碼是由maven-compiler-plugin完成的。進一步說,每個任務對應了一個插件目標(goal),每個插件會有一個或者多個目標,例如maven-compiler-plugin的compile目標用來編譯位于src/main/java/目錄下的主源碼,testCompile目標用來編譯位于src/test/java/目錄下的測試源碼。