Maven入門指南

Maven入門指南

本指南旨在第一次爲使用Maven的人員提供參考,但也打算做爲一本包含公共用例的獨立參考和解決方案的工具書。對於新用戶,建議您按順序瀏覽該材料。對於更熟悉Maven的用戶,本指南致力於爲手頭的需求提供一個快速解決方案。如今假設您已經在本地計算機上下載了Maven並安裝了Maven。若是您沒有這樣作,請參考下載和安裝說明( Download and Installation)。html

好的,如今安裝了Maven,咱們準備好了。在開始咱們的示例以前,咱們將很是簡單地介紹Maven是什麼,以及它如何幫助您完成平常工做和與團隊成員協做。固然,Maven將爲小型項目工做,可是Maven在幫助團隊更有效地操做方面表現出色,它容許團隊成員將精力集中在項目的涉衆須要什麼上。您能夠將構建基礎設施留給Maven!java

Maven是什麼?

乍一看,Maven看起來可能有不少東西,但簡而言之,Maven是一種嘗試將模式應用於項目的構建基礎結構,以便經過在使用最佳實踐中提供清晰的路徑來促進理解和生產力。Maven本質上是一個項目管理和理解工具,所以提供了一種幫助管理的方法:程序員

  • 構建
  • 文檔
  • 報告
  • 依賴
  • SCMs
  • 版本
  • 發佈

若是您想了解更多關於Maven的背景信息,能夠查看Maven的哲學( The Philosophy of Maven)和Maven的歷史( The History of Maven)。如今,讓咱們繼續討論用戶如何從使用Maven中獲益。web

Maven如何使個人開發過程受益?

Maven能夠經過使用標準約定和實踐來加快開發週期,同時幫助您得到更高的效率,從而爲您的構建過程提供好處。apache

如今咱們已經介紹了一些Maven的歷史和目的,讓咱們進入一些實際的例子,讓您開始使用Maven!緩存

如何配置Maven?

Maven的默認值一般是足夠的,可是若是您須要更改緩存位置或使用HTTP代理,則須要建立配置。有關更多信息,請參見配置Maven指南(Guide to Configuring Maven)。服務器

如何進行個人第一個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要點:

  • project 這是全部Maven pom.xml文件中的頂級元素。
  • modelVersion 此元素指示POM使用的對象模型的版本。模型自己的版本變化很是少,但若是Maven開發人員認爲有必要更改模型,則必須這樣作,以確保使用的穩定性。
  • groupId 此元素指示建立項目的組織或組的惟一標識符。groupId是項目的關鍵標識符之一,一般基於組織的徹底限定域名。例如,org.apache.maven.plugins是全部Maven插件的指定groupId。
  • artifactId 此元素指示由此項目生成的項目的惟一名稱。項目的主要框架一般是JAR文件。像源包這樣的次要構件也使用artifactId做爲其最終名稱的一部分。Maven生成的典型框架將具備 - . 表單(例如 myapp-1.0.jar)。
  • packaging 此元素指示此項目將使用的包類型(例如JAR、WAR、EAR等)。這不只意味着產生的項目是JAR、WAR或EAR,並且還能夠指示要做爲構建過程的一部分使用的特定生命週期。(生命週期是咱們將在指南中進一步討論的一個主題。如今,請記住,項目的指定打包能夠在定製構建生命週期中發揮做用。)packaging的默認值是JAR,所以您沒必要爲大多數項目指定此值。
  • version 此元素指示項目生成的版本。Maven對幫助您進行版本管理有很大幫助,您常常會看到版本中的SNAPSHOT指示符,這代表項目處於開發狀態。咱們將在本指南中討論 snapshots的使用以及它們是如何工做的。
  • name 此元素指示用於項目的顯示名稱。這常常用於Maven生成的文檔中。
  • url 此元素指示在何處能夠找到項目的站點。這常常用於Maven生成的文檔中。
  • description 此元素提供了項目的基本說明。這常常用於Maven生成的文檔中。

有關在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] ----------------------------------------------------------------------------複製代碼

一些關於輸出的注意事項:

  • Maven此次下載更多的依賴項。這些是執行測試所必需的依賴項和插件(它已經擁有編譯所需的依賴項,不會再下載它們)。
  • 在編譯和執行測試以前,Maven編譯主代碼(全部這些類都是最新的,由於咱們自上次編譯以來什麼都沒有改變)。

若是您只想編譯測試源代碼(但不想執行測試),能夠執行如下操做:

mvn test-compile複製代碼

既然您能夠編譯您的應用程序源代碼,編譯您的測試,並執行測試,那麼您將但願進入下一個邏輯步驟,所以您將詢問...

如何建立JAR並將其安裝在本地存儲庫中?

建立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目錄,以使其是新的。

什麼是SNAPSHOT版本?

注意,下面顯示的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中?

另外一個能夠知足的常見用例是將資源打包到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.xmlpom.properties文件。這些都是標準的,在Maven中生成一個JAR。若是選擇,能夠建立本身的清單,但若是不選擇,Maven將默認生成清單。(還能夠修改默認清單中的條目。咱們稍後再談這個問題。) pom.xmlpom.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>複製代碼

您會注意到,咱們必須添加之前沒有的buildresourcesresource元素。此外,咱們還必須明確聲明資源位於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.xmlproperties節點中定義它,並得到一樣的效果(請注意,我也不須要對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.versionuser.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, testruntime這樣的值。有關能夠爲依賴項指定的全部內容的詳細信息,請參閱項目描述符指南(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?

要將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中結束。緣由是 test 元素-它只是測試所必需的,所以不包括在web應用程序中,由於編譯時依賴於my-app

最後一步是包含父定義。這與您可能熟悉的Maven 1.0中的extend元素不一樣:這能夠確保POM始終能夠被定位,即便經過在存儲庫中查找該項目,該項目也是獨立於其父項目的。

相關文章
相關標籤/搜索