本指南旨在第一次爲使用Maven的人員提供參考,但也打算做爲一本包含公共用例的獨立參考和解決方案的工具書。對於新用戶,建議您按順序瀏覽該材料。對於更熟悉Maven的用戶,本指南致力於爲手頭的需求提供一個快速解決方案。如今假設您已經在本地計算機上下載了Maven並安裝了Maven。若是您沒有這樣作,請參考下載和安裝說明( Download and Installation)。html
好的,如今安裝了Maven,咱們準備好了。在開始咱們的示例以前,咱們將很是簡單地介紹Maven是什麼,以及它如何幫助您完成平常工做和與團隊成員協做。固然,Maven將爲小型項目工做,可是Maven在幫助團隊更有效地操做方面表現出色,它容許團隊成員將精力集中在項目的涉衆須要什麼上。您能夠將構建基礎設施留給Maven!java
乍一看,Maven看起來可能有不少東西,但簡而言之,Maven是一種嘗試將模式應用於項目的構建基礎結構,以便經過在使用最佳實踐中提供清晰的路徑來促進理解和生產力。Maven本質上是一個項目管理和理解工具,所以提供了一種幫助管理的方法:程序員
若是您想了解更多關於Maven的背景信息,能夠查看Maven的哲學( The Philosophy of Maven)和Maven的歷史( The History of Maven)。如今,讓咱們繼續討論用戶如何從使用Maven中獲益。web
Maven能夠經過使用標準約定和實踐來加快開發週期,同時幫助您得到更高的效率,從而爲您的構建過程提供好處。apache
如今咱們已經介紹了一些Maven的歷史和目的,讓咱們進入一些實際的例子,讓您開始使用Maven!緩存
Maven的默認值一般是足夠的,可是若是您須要更改緩存位置或使用HTTP代理,則須要建立配置。有關更多信息,請參見配置Maven指南(Guide to Configuring Maven)。服務器
咱們將直接跳到建立您的第一個Maven項目!爲了建立咱們的第一個Maven項目,咱們將使用Maven的原型機制。原型(archetype )被定義爲一種原始的模式或模型,全部其餘同類的東西都是從這個模式或模型中製造出來的。在Maven中,原型是一個項目的模板,該模板與一些用戶輸入相結合,生成一個適合用戶需求的Maven項目。咱們如今將向您展現原型機制是如何工做的,可是若是您想了解更多關於原型的信息,請參考咱們對原型的介紹( Introduction to Archetypes)。app
繼續建立你的第一個項目!爲了建立最簡單的Maven項目,從命令行執行如下命令:框架
mvn -B archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DgroupId=com.mycompany.app \
-DartifactId=my-app複製代碼
執行此命令後,您將注意到發生了一些事情。首先,您將注意到已經爲新項目建立了一個名爲my-app的目錄,而且這個目錄包含一個名爲pom.xml
的文件,該文件應該以下所示:ssh
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>複製代碼
pom.xml
包含該項目的項目對象模型(POM)。POM是Maven中的基本工做單元。記住這一點很重要,由於Maven本質上是以項目爲中心的,由於一切都圍繞着項目的概念。簡而言之,POM包含關於您的項目的每個重要信息,本質上是一站式消費,用於查找與您的項目相關的任何內容。理解POM很重要,鼓勵新用戶參考POM簡介(Introduction to the POM)。
這是一個很是簡單的POM,但仍然顯示每一個POM包含的關鍵元素,所以讓咱們遍歷其中的每個元素,讓您熟悉POM要點:
org.apache.maven.plugins
是全部Maven插件的指定groupId。 myapp-1.0.jar
)。
packaging
的默認值是JAR,所以您沒必要爲大多數項目指定此值。 SNAPSHOT
指示符,這代表項目處於開發狀態。咱們將在本指南中討論 snapshots的使用以及它們是如何工做的。 有關在POM中可用的元素的完整參考,請參考咱們的POM指南(POM Reference)。如今讓咱們回到手頭的項目。
在生成第一個項目的原型以後,您還會注意到已經建立了如下目錄結構:
my-app
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- com
| `-- mycompany
| `-- app
| `-- App.java
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java複製代碼
如您所見,從原型(archetype)建立的項目有一個POM、一個用於應用程序源的源代碼樹和一個用於測試源的源代碼樹。這是Maven項目的標準佈局(應用程序源位於${basedir}/src/main/java
,測試源位於${basedir}/src/test/java
中,其中${basedir}表示包含pom.xml
的目錄)。
若是要手工建立Maven項目,咱們建議使用這個目錄結構。這是一個Maven約定,要了解更多有關它的信息,您能夠閱讀咱們對標準目錄佈局的介紹(Introduction to the Standard Directory Layout)。
如今咱們有了一個POM、一些應用程序源代碼和一些您可能須要的測試源代碼。
經過archetype:generate切換到被建立pom.xml的目錄並執行如下命令來編譯應用程序源代碼:
mvn compile複製代碼
在執行此命令時,您應該看到輸出以下所示:
[INFO] ----------------------------------------------------------------------------
[INFO] Building Maven Quick Start Archetype
[INFO] task-segment: [compile]
[INFO] ----------------------------------------------------------------------------
[INFO] artifact org.apache.maven.plugins:maven-resources-plugin: \
checking for updates from central
...
[INFO] artifact org.apache.maven.plugins:maven-compiler-plugin: \
checking for updates from central
...
[INFO] [resources:resources]
...
[INFO] [compiler:compile]
Compiling 1 source file to <dir>/my-app/target/classes
[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ----------------------------------------------------------------------------
[INFO] Total time: 3 minutes 54 seconds
[INFO] Finished at: Fri Sep 23 15:48:34 GMT-05:00 2005
[INFO] Final Memory: 2M/6M
[INFO] ----------------------------------------------------------------------------複製代碼
當您第一次執行此命令(或任何其餘命令)時,Maven將須要下載完成該命令所需的全部插件和相關依賴項。從Maven的乾淨安裝來看,這可能須要至關長的時間(在上面的輸出中,花費了將近4分鐘)。若是您再次執行該命令,Maven如今將獲得它所需的東西,所以它不須要下載任何新的內容,而且可以更快地執行該命令。
從輸出中能夠看到,編譯後的類被放置在${basedir}/target/classes
中,這是Maven使用的另外一個標準約定。所以,若是您是一個敏銳的觀察者,您會注意到經過使用標準約定,上面的POM很是小,而且您沒必要明確地告訴Maven您的源代碼在哪裏或輸出應該去哪裏。經過遵循標準的Maven約定,您能夠在很小的努力下完成不少事情!做爲一個偶然的比較,讓咱們來看看您在 Ant中可能須要作些什麼來完成一樣的 事情。
如今,這只是編譯一個應用程序源代碼樹,所顯示的Ant腳本與上面顯示的POM大小基本相同。可是,咱們將看到,咱們還能夠作更多的只是簡單的POM!
如今您正在成功地編譯您的應用程序的源代碼,如今您已經得到了一些您想要編譯和執行的單元測試(由於每一個程序員老是編寫和執行他們的單元測試輕推眨眼)。
執行如下命令:
mvn test複製代碼
在執行此命令時,您應該看到輸出以下所示:
[INFO] ----------------------------------------------------------------------------
[INFO] Building Maven Quick Start Archetype
[INFO] task-segment: [test]
[INFO] ----------------------------------------------------------------------------
[INFO] artifact org.apache.maven.plugins:maven-surefire-plugin: \
checking for updates from central
...
[INFO] [resources:resources]
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] [compiler:testCompile]
Compiling 1 source file to C:\Test\Maven2\test\my-app\target\test-classes
...
[INFO] [surefire:test]
[INFO] Setting reports dir: C:\Test\Maven2\test\my-app\target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
[surefire] Running com.mycompany.app.AppTest
[surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0 sec
Results :
[surefire] Tests run: 1, Failures: 0, Errors: 0
[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ----------------------------------------------------------------------------
[INFO] Total time: 15 seconds
[INFO] Finished at: Thu Oct 06 08:12:17 MDT 2005
[INFO] Final Memory: 2M/8M
[INFO] ----------------------------------------------------------------------------複製代碼
一些關於輸出的注意事項:
若是您只想編譯測試源代碼(但不想執行測試),能夠執行如下操做:
mvn test-compile複製代碼
既然您能夠編譯您的應用程序源代碼,編譯您的測試,並執行測試,那麼您將但願進入下一個邏輯步驟,所以您將詢問...
建立JAR文件是足夠直接的,能夠經過執行如下命令來完成:
mvn package複製代碼
若是您查看項目的POM,您將注意到packaging
元素設置爲jar
。Maven知道如何從上面的命令生成一個JAR文件(稍後咱們將更多地討論這一點)。如今您能夠在${basedir}/target
目錄中查看一下,您將看到生成的JAR文件。
如今,您須要在本地存儲庫中安裝您生成的項目(JAR文件)(${user.home}/.m2/repository
是默認位置)。有關存儲庫的更多信息,您能夠參考咱們對存儲庫的介紹(Introduction to Repositories),但讓咱們繼續安裝咱們的項目!爲此,請執行如下命令:
mvn install複製代碼
在執行此命令時,您將看到如下輸出:
[INFO] ----------------------------------------------------------------------------
[INFO] Building Maven Quick Start Archetype
[INFO] task-segment: [install]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] [compiler:compile]
Compiling 1 source file to <dir>/my-app/target/classes
[INFO] [resources:testResources]
[INFO] [compiler:testCompile]
Compiling 1 source file to <dir>/my-app/target/test-classes
[INFO] [surefire:test]
[INFO] Setting reports dir: <dir>/my-app/target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
[surefire] Running com.mycompany.app.AppTest
[surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.001 sec
Results :
[surefire] Tests run: 1, Failures: 0, Errors: 0
[INFO] [jar:jar]
[INFO] Building jar: <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO] [install:install]
[INFO] Installing <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar to \
<local-repository>/com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.jar
[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ----------------------------------------------------------------------------
[INFO] Total time: 5 seconds
[INFO] Finished at: Tue Oct 04 13:20:32 GMT-05:00 2005
[INFO] Final Memory: 3M/8M
[INFO] ----------------------------------------------------------------------------複製代碼
注意,強制插件(它執行測試)查找包含在具備特定命名約定的文件中的測試。默認狀況下,包括的測試以下:
**/*Test.java
**/Test*.java
**/*TestCase.java
默認狀況排除以下:
**/Abstract*Test.java
**/Abstract*TestCase.java
您已經完成了設置、構建、測試、打包和安裝典型Maven項目的過程。這多是項目使用Maven所作的絕大部分工做,若是您已經注意到,到目前爲止所能作的一切都是由一個18行文件驅動的,即項目的模型或POM。若是您查看一個典型的Ant構建文件,它提供了與咱們迄今爲止所實現的功能相同的功能,您會注意到它的大小已是POM的兩倍,並且咱們纔剛剛開始!您能夠從Maven得到更多的功能,而不須要對咱們目前的POM進行任何添加。要從咱們的示例Ant構建文件( build file )中得到更多的功能,您必須不斷地添加容易出錯的內容。
你還能免費獲得什麼?有大量的Maven插件,即便是像咱們上面這樣簡單的POM,也是能夠開箱即用的。咱們將在這裏特別提到一個,由於它是Maven的一個被高度重視的特性:在沒有任何工做的狀況下,這個POM有足夠的信息爲您的項目生成一個網站!您極可能但願自定義Maven站點,但若是時間緊迫,則只需執行如下命令便可提供有關項目的基本信息:
mvn site複製代碼
還有許多其餘獨立的目標也能夠執行,例如:
mvn clean複製代碼
這將在啓動前刪除包含全部生成數據的target
目錄,以使其是新的。
注意,下面顯示的pom.xml
文件中version標記的值有後綴:-SNAPSHOT
。
<project xmlns="http://maven.apache.org/POM/4.0.0"
...
<groupId>...</groupId>
<artifactId>my-app</artifactId>
...
<version>1.0-SNAPSHOT</version>
<name>Maven Quick Start Archetype</name>
...複製代碼
SNAPSHOT
是指開發分支的「最新」代碼,並不保證代碼是穩定的或不變的。相反,'release' 中的代碼(任何沒有後綴SNAPSHOT
的版本值)都是不變的。
換句話說,SNAPSHOT版本是最後的 'release' 版本以前的「開發」版本。SNAPSHOT比它的'release' 版「舊」。
在發佈過程當中,x.y-SNAPSHOT的版本更改成x.y。發佈過程當中還將開發版本增長到 x.(y+1)-SNAPSHOT。例如,1.0-SNAPSHOT做爲1.0版發佈,新的開發版本爲1.1-SNAPSHOT。
每當您想要自定義Maven項目的構建時,都是經過添加或從新配置插件來完成的。
注意,對於Maven 1.0用戶:在Maven 1.0中,您應該將一些preGoal
添加到maven.xml
中,並將一些條目添加到project.properties
中。在這裏,有點不一樣。對於本例,咱們將配置Java編譯器以容許JDK5.0源代碼。這就像將其添加到POM中同樣簡單:
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
...複製代碼
您會注意到,Maven中的全部插件看起來都很像一個依賴項-並且在某些方面它們是依賴的。這個插件將被自動下載和使用-若是你要求的話包括一個特定的版本(默認的是使用最新的可用版本)。
configuration
元素將給定的參數應用於編譯器插件中的每一個目標。在上面的例子中,編譯器插件已經被用做構建過程的一部分,這只是改變了配置。還能夠向流程中添加新的目標,並配置特定的目標。有關這方面的信息,請參閱構建生命週期介紹(Introduction to the Build Lifecycle)。
要了解插件的配置,您能夠看到插件列表(Plugins List)並導航到您正在使用的插件和目標。有關如何配置插件可用參數的通常信息,請參閱配置插件指南(Guide to Configuring Plugins)。
另外一個能夠知足的常見用例是將資源打包到JAR文件中,它不須要對上面的POM進行更改。對於這個常見的任務,Maven再次依賴於 Standard Directory Layout,這意味着經過使用標準Maven約定,您能夠將資源打包到JAR中,只需將這些資源放在標準目錄結構中便可。
您能夠在下面的示例中看到,咱們添加了目錄${basedir}/src/main/resources
,咱們但願將任何資源打包到JAR中。Maven使用的簡單規則是:${basedir}/src/main/resources
目錄中的任何目錄或文件都打包在JAR中,其結構與JAR底部的結構徹底相同。
my-app
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | `-- App.java
| `-- resources
| `-- META-INF
| `-- application.properties
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java複製代碼
所以,在咱們的示例中能夠看到,咱們在該目錄中有一個META-INF
目錄和一個application.properties
文件。若是您打開Maven爲您建立的JAR並查看它,您將看到如下內容:
|-- META-INF
| |-- MANIFEST.MF
| |-- application.properties
| `-- maven
| `-- com.mycompany.app
| `-- my-app
| |-- pom.properties
| `-- pom.xml
`-- com
`-- mycompany
`-- app
`-- App.class複製代碼
如您所見,${basedir}/src/main/resources
的內容能夠從JAR的裏邊找到,而application.properties
文件位於META-INF
目錄中。您還會注意到一些其餘文件,如META-INF/MANIFEST.MF
,以及pom.xml
和pom.properties
文件。這些都是標準的,在Maven中生成一個JAR。若是選擇,能夠建立本身的清單,但若是不選擇,Maven將默認生成清單。(還能夠修改默認清單中的條目。咱們稍後再談這個問題。) pom.xml
和pom.properties
文件打包在JAR中,這樣由Maven生成的每一個項目都是自描述的,並容許您在須要時在本身的應用程序中使用元數據。一個簡單的用途多是檢索應用程序的版本。對POM文件的操做將要求您使用一些Maven實用程序,可是可使用標準的Java API來使用這些屬性,以下所示:
#Generated by Maven
#Tue Oct 04 15:43:21 GMT-05:00 2005
version=1.0-SNAPSHOT
groupId=com.mycompany.app
artifactId=my-app複製代碼
要將資源(resources)添加到單元測試的類路徑中,您能夠遵循與將資源添加到JAR中相同的模式,但將資源放在其中的目錄是${basedir}/src/test/resources。此時,您將擁有一個相似於如下內容的項目目錄結構:
my-app
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | `-- App.java
| `-- resources
| `-- META-INF
| |-- application.properties
`-- test
|-- java
| `-- com
| `-- mycompany
| `-- app
| `-- AppTest.java
`-- resources
`-- test.properties複製代碼
在單元測試中,您可使用如下代碼片斷來訪問測試所需的資源:
...
// Retrieve resource
InputStream is = getClass().getResourceAsStream( "/test.properties" );
// Do something with the resource
...複製代碼
有時,資源文件須要包含只能在構建時提供的值。要在Maven中實現這一點,請使用語法${
將包含該值的屬性引用到您的資源文件中。該屬性能夠是在pom.xml中定義的值之1、在用戶的setings.xml中定義的值、在外部屬性文件中定義的屬性或系統屬性。
若要在複製時讓Maven篩選資源,只需在你的pom.xml
中將資源目錄的filtering
設置爲true:
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>複製代碼
您會注意到,咱們必須添加之前沒有的build
、resources
和resource
元素。此外,咱們還必須明確聲明資源位於src/main/resources目錄中。全部這些信息之前都是以默認值的形式提供的,可是因爲filtering
的默認值爲false,因此咱們必須將其添加到pom.xml中,以便覆蓋該默認值並將filtering
設置爲true。
要引用pom.xml中定義的屬性,屬性名稱使用定義值的XML元素的名稱,並容許「pom」做爲項目(Root)元素的別名。因此${project.name}
是指項目的名稱,${project.version}
是指項目的版本,${project.build.finalName}
是指在打包構建項目時建立的文件的最終名稱,等等。相似地,可使用以「settings」開頭的屬性名稱引用用戶Setings.xml
中的值(例如,${setings.localRepository}
引用用戶本地存儲庫的路徑)。
爲了繼續咱們的示例,讓咱們將兩個屬性添加到application.properties
文件(咱們將其放在src/main/resources
目錄中),當資源被過濾時,它的值將被提供:
# application.properties
application.name=${project.name}
application.version=${project.version}複製代碼
這樣,您就能夠執行如下命令(Process-Resources是複製和過濾資源的構建生命週期階段):
mvn process-resources複製代碼
target/classes下的application.properties
文件(最終將進入JAR)以下所示:
# application.properties
application.name=Maven Quick Start Archetype
application.version=1.0-SNAPSHOT複製代碼
若要引用在外部文件中定義的屬性,只需將對該外部文件的引用添加到pom.xml文件中便可。首先,讓咱們建立外部屬性文件,並將其命名爲src/main/filters/filter.properties
:
# filter.properties
my.filter.value=hello!複製代碼
接下來,咱們將在pom.xml中添加對這個新文件的引用:
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<filters>
<filter>src/main/filters/filter.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>複製代碼
而後,若是咱們在application.properties
文件中添加對此屬性的引用:
# application.properties
application.name=${project.name}
application.version=${project.version}
message=${my.filter.value}複製代碼
下次執行mvn process-resources
命令時,咱們將把新的屬性值放入application.properties
中。做爲在外部文件中定義my.filter.value屬性的一種替代方法,您也能夠在pom.xml
的properties
節點中定義它,並得到一樣的效果(請注意,我也不須要對src/main/filters/filter.properties
的引用):
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<properties>
<my.filter.value>hello</my.filter.value>
</properties>
</project>複製代碼
過濾資源也能夠從系統屬性中得到值;要麼是內置到Java中的系統屬性(好比java.version
或user.home
),要麼是使用標準Java-D參數在命令行上定義的屬性。爲了繼續這個示例,讓咱們將application.properties
文件更改成以下所示:
# application.properties
java.version=${java.version}
command.line.prop=${command.line.prop}複製代碼
如今,當您執行如下命令(請注意命令行上的command.line.prop屬性的定義)時,application.properties
文件將包含來自系統屬性的值。
mvn process-resources "-Dcommand.line.prop=hello again"複製代碼
您可能已經注意到咱們做爲示例使用的POM中的dependencies
元素。事實上,您一直在使用外部依賴項,可是這裏咱們將更詳細地討論這一點。關於更詳細的介紹,請參閱咱們對依賴機制的介紹( Introduction to Dependency Mechanism)。
pom.xml的dependencies
節點列出了咱們的項目構建所需的全部外部依賴項(不管是在編譯時、測試時、運行時仍是其餘何時都須要該依賴項)。如今,咱們的項目只依賴於JUnit(爲了清晰起見,我取出了全部的資源過濾工具):
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>複製代碼
對於每一個外部依賴項,您至少須要定義4件事情:groupId, artifactId, version 和 scope。groupId、artifactId和version與構建該依賴項的pom.xml
中提供的相同。scope元素指示項目如何使用該依賴項,而且能夠是像compile
, test
和 runtime
這樣的值。有關能夠爲依賴項指定的全部內容的詳細信息,請參閱項目描述符指南(Project Descriptor Reference)。
有關整個依賴機制的更多信息,請參見依賴機制介紹(Introduction to Dependency Mechanism)。
有了這些關於依賴項的信息,Maven將可以在構建項目時引用該依賴項。Maven從哪裏引用依賴項?Maven在本地存儲庫中查找全部依賴項(${user.home}/.m2/repository
是默認位置)。在上一節中,咱們將項目(My-app-1.0-SNAPSHOT.jar)安裝到本地存儲庫中。一旦安裝在那裏,另外一個項目就能夠將該jar引用爲依賴項,只需將依賴信息添加到它的pom.xml中:
<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">
<groupId>com.mycompany.app</groupId>
<artifactId>my-other-app</artifactId>
...
<dependencies>
...
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>複製代碼
其餘地方構建的依賴關係呢?他們怎麼進入個人本地存儲庫?每當項目引用本地存儲庫中不可用的依賴項時,Maven將依賴項從遠程存儲庫下載到本地存儲庫中。在構建第一個項目時,您可能注意到Maven下載了不少東西(這些下載是用於構建項目的各類插件的依賴項)。默認狀況下,能夠在http://repo.maven.apache.org/maven2/上找到(並瀏覽)Maven使用的遠程存儲庫。您還能夠設置本身的遠程存儲庫(多是您公司的中央存儲庫)來代替默認遠程存儲庫或除了默認遠程存儲庫以外使用。有關存儲庫的更多信息,請參閱存儲庫介紹(Introduction to Repositorie)。
讓咱們將另外一個依賴項添加到咱們的項目中。假設咱們在代碼中添加了一些日誌,而且須要將log4j做爲依賴項添加。首先,咱們須要知道log4j的groupId、artifactId和version是什麼。Maven Central上的適當目錄名爲/maven2/log4j/log4j。該目錄中有一個名爲maven-metadata.xml的文件。下面是log4j的maven-metadata.xml以下所示:
<metadata>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.1.3</version>
<versioning>
<versions>
<version>1.1.3</version>
<version>1.2.4</version>
<version>1.2.5</version>
<version>1.2.6</version>
<version>1.2.7</version>
<version>1.2.8</version>
<version>1.2.11</version>
<version>1.2.9</version>
<version>1.2.12</version>
</versions>
</versioning>
</metadata>複製代碼
從這個文件中,咱們能夠看到咱們想要的groupId是「log4j」,而artifactId是「log4j」。咱們看到許多不一樣的版本值可供選擇;目前,咱們只使用最新版本1.2.12(一些maven-metadata.xml文件也可能指定哪一個版本是當前版本)。在maven-metadata.xml文件旁邊,咱們能夠看到與log4j庫的每一個版本對應的目錄。在這些文件中,咱們將找到實際的JAR文件(例如log4j-1.2.12.jar)和一個pom文件(這是該依賴項的pom.xml,指示它可能擁有的任何進一步依賴項和其餘信息)和另外一個maven-metadata.xml文件。還有一個對應於這些文件的MD5文件,其中包含這些文件的MD5哈希值。您可使用它對庫進行身份驗證,或者肯定您可能已經使用的特定庫的哪一個版本。
既然咱們已經知道了咱們須要的信息,咱們就能夠將依賴項添加到pom.xml文件中了:
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>複製代碼
如今,當咱們編譯項目(mvn compile
)時,咱們將看到Maven爲咱們下載log4j依賴項。
要將JAR部署到外部存儲庫,您必須在pom.xml中配置存儲庫url,並在settings.xml中配置鏈接到存儲庫的身份驗證信息。
下面是一個使用scp和用戶名/密碼身份驗證的示例:
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
<build>
<filters>
<filter>src/main/filters/filters.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<!--
|
|
|
-->
<distributionManagement>
<repository>
<id>mycompany-repository</id>
<name>MyCompany Repository</name>
<url>scp://repository.mycompany.com/repository/maven2</url>
</repository>
</distributionManagement>
</project>複製代碼
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
...
<servers>
<server>
<id>mycompany-repository</id>
<username>jvanzyl</username>
<!-- Default value is ~/.ssh/id_dsa -->
<privateKey>/path/to/identity</privateKey> (default is ~/.ssh/id_dsa)
<passphrase>my_key_passphrase</passphrase>
</server>
</servers>
...
</settings>複製代碼
請注意,若是鏈接到openssh ssh服務器,該服務器的參數「PasswordAuthentication」在sshd_conf中設置爲「no」,則每次輸入用戶名/密碼身份驗證時都必須鍵入密碼(儘管您可使用另外一個ssh客戶機登陸,輸入用戶名和密碼)。在這種狀況下,您可能但願切換到公鑰身份驗證。
在settings.xml
中使用密碼時應該當心。有關更多信息,請參見密碼加密(Password Encryption)。
爲了讓您從Maven的文檔系統開始,您可使用原型機制爲現有項目生成一個站點,使用如下命令:
mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-site \
-DgroupId=com.mycompany.app \
-DartifactId=my-app-site複製代碼
如今轉到指南中去建立一個站點(Guide to creating a site),學習如何爲您的項目建立文檔。
注意,生命週期適用於任何項目類型。例如,回到基本目錄中,咱們能夠建立一個簡單的web應用程序:
mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-webapp \
-DgroupId=com.mycompany.app \
-DartifactId=my-webapp複製代碼
請注意,全部這些都必須在一行上。這將建立一個名爲my-webapp
的目錄,其中包含如下項目描述符:
<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.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
</build>
</project>複製代碼
注意
元素-這告訴Maven構建爲WAR。切換到webapp項目的目錄並嘗試:
mvn package複製代碼
您將看到構建了target/my-webapp.war
,而且執行了全部正常步驟。
Maven內置了處理多個模塊的概念。在本節中,咱們將展現如何構建上面的WAR,並在一個步驟中包含前面的JAR。
首先,咱們須要在其餘兩個目錄中添加一個父pom.xml
文件,所以它應該以下所示:
+- pom.xml
+- my-app
| +- pom.xml
| +- src
| +- main
| +- java
+- my-webapp
| +- pom.xml
| +- src
| +- main
| +- webapp複製代碼
您將要建立的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>
<groupId>com.mycompany.app</groupId>
<artifactId>app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>my-app</module>
<module>my-webapp</module>
</modules>
</project>複製代碼
咱們須要一個來自webapp的JAR依賴項,因此將其添加到my-webapp/pom.xml
中:
...
<dependencies>
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
...
</dependencies>複製代碼
最後,將如下
元素添加到子目錄中的兩個其餘pom.xml
文件中:
<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">
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>app</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
...複製代碼
如今試試.。在頂層目錄中,運行:
mvn verify複製代碼
WAR如今已經在my-webapp/target/my-webapp.war
中建立,而且JAR被包括在內:
$ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war
0 Fri Jun 24 10:59:56 EST 2005 META-INF/
222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/
3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml
0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/
215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml
123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.properties
52 Fri Jun 24 10:59:56 EST 2005 index.jsp
0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/
2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar複製代碼
這是怎麼回事?首先,建立的父POM(稱爲app
)具備POM
的打包和定義的模塊列表。這告訴Maven在項目集上運行全部操做,而不是隻運行當前的操做(要覆蓋這種行爲,可使用--non-recursive
命令行選項)。
接下來,咱們告訴WAR,它須要my-app
JAR。這作了幾件事:它使它能夠在類路徑上訪問WAR中的任何代碼(在本例中沒有),它確保JAR老是在WAR以前構建的,而且它指示WAR插件將JAR包含在其庫目錄中。
您可能已經注意到junit-4.11.jar
是一種依賴關係,但沒有在WAR中結束。緣由是
元素-它只是測試所必需的,所以不包括在web應用程序中,由於編譯時依賴於my-app
。
最後一步是包含父定義。這與您可能熟悉的Maven 1.0中的extend
元素不一樣:這能夠確保POM始終能夠被定位,即便經過在存儲庫中查找該項目,該項目也是獨立於其父項目的。