Apache Maven --- [Maven入門指南]

本指南的目的是爲初次使用Maven的人提供一個參考,但同時也做爲一個獨立參考和解決方案的食譜來爲常見用例提供服務.對於第一次使用的用戶來講,建議按順序依次瀏覽指南.而對於更加熟悉Maven的用戶來講,本指南盡力提供一個急需的快速解決方案.咱們假設你已經下載併成功安裝了Maven,若是沒有,請先查閱下載和安裝說明.html

好了,因此如今你已經安裝了Maven,準備出發.在咱們進入咱們的示例以前,咱們先來簡單的過一遍Maven是什麼,它如何幫助你的平常工做以及團隊之間的協做.固然Maven能夠爲小項目工做,可是它的亮點是可以經過容許團隊人員關注於項目利益者的需求來幫助團隊更有效率的運做.你能夠把構建基礎委託給Maven.java

什麼是Mavenweb

乍一看Maven能夠是不少東西,可是簡而言之,它是爲了促進理解和生產,經過提供一個清晰的最優使用實踐的步驟來視圖將模式應用到項目的構建當中.它是一個項目綜合管理工具,提供了一種方法來幫助管理:apache

構建緩存

文檔服務器

報告app

依賴eclipse

SCMs(供應鏈?)ssh

發佈webapp

分發

Maven如何讓個人開發過程受益

Maven經過採用標準規範和實踐來促進你的開發週期並同時幫助你取得更高的成功.

我如何設置Maven

Maven的默認配置一般是足夠使用的,可是若是你想要改變本地緩存或者綁定HTTP代理,你須要建立配置.具體查閱Maven配置指南.

我如何開始個人第一個Maven項目

咱們將使用Maven的原型機制來建立咱們的第一個Maven項目.一個原型被定義爲一個模式或者模型,表示全部東西都以一種相同的方式被建立.在Maven中,一個原型是一個根據用戶需求而定製的結合了一些用戶輸入來產生的Maven工做項目的模版.如今咱們將向你展現一個原型機制是如何工做的,但若是你想知道更多關於原型的介紹,請參考:http://maven.apache.org/guides/introduction/introduction-to-archetypes.html

建立你的第一個項目!爲了建立最簡單的Maven項目,在命令行執行下列語句:

mvn -B archetype:generate \
  -DarchetypeGroupId=org.apache.maven.archetypes \
  -DgroupId=com.mycompany.app \
  -DartifactId=my-app

一旦你執行了這個命令,你將會發現一些東西發生了改變.首先,你會發現Maven爲新項目建立了一個名爲my-app的目錄,而且這個目錄包含了一個叫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>
  <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包含了這個項目的項目對象模型(project object model-POM).在Maven中,POM是基礎工做單元.須要牢記這一點,由於Maven天生是項目式的,一切圍繞項目的概念.簡而言之,POM包含了你項目的全部重要信息片而且本質上是爲查找任何項目相關內容的優惠條件...理解POM的重要性,而且咱們鼓勵新用戶查閱完整的POM介紹:http://maven.apache.org/guides/introduction/introduction-to-the-pom.html

這是一個很是簡單的POM可是仍然展現了全部POM都包含的關鍵元素,因此讓咱們瀏覽每一個元素來使你熟悉POM的要點:

<project> 在全部pom.xml文件中,它都是頂級元素

<modelVersion> 這個元素代表了這個POM正在使用的對象模型的版本.模型自己的版本不多發生變化,可是它是強制性的以確保穩定的使用若是Maven開發人員認爲有必要改變模型.

<groupId> 這個元素代表了建立項目的組織或團體的惟一標識符.它是項目的一個關鍵標識符而且一般基於組織的徹底限定域名.例如:org.apache.maven.plugins 是全部Maven插件的指定groupId.

<artifactId> 這個元素代表由項目生成的主要工件的惟一基礎名稱.項目的主要工件一般是JAR文件.次要工件像代碼束也使用artifactId做爲它們最後名字的一部分.一個Maven產生的特定工件可能會是這樣的格式:<artifactId>-<version>.<extension> (如 myapp-1.0.jar).

<packaging> 這個元素代表工件用來打包的類型(如:JAR,WAR,EAR等).這不只僅意味着工件產生的是JAR,WAR,EAR...還代表了構建過程當中的一個特定的生命週期(生命週期是一個咱們將要討論的主題,如今,只須要記住一個項目的包裝能夠做爲定製構建生命週期的一部分).該元素的默認值是JAR,因此對於大多數項目來講你不必定要指明這個元素.

<version> 這個元素代表項目生成的工件版本號.Maven幫你進行長期的版本管理,並且你常常會看見SNAPSHOT版本標誌,這代表項目正處於一個開發狀態.咱們將在後續討論快照的用處和它們是如何工做的.

<name> 這個元素代表項目的展示名稱.這一般被Maven用來生成文檔.

<url> 這個元素代表項目站點的訪問路徑. 這一般被Maven用來生成文檔.

<description> 這個元素提供了項目的基礎描述. 這一般被Maven用來生成文檔.

若是想要查看完整的可用元素請查閱:https://maven.apache.org/ref/3.3.9/maven-model/maven.html

如今咱們回到項目,在你的第一個項目的原型生成後,你也會發現以下目錄結構被建立:

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

正如你所看見的,從原型建立的項目有一個POM,一個應用代碼的代碼樹和測試代碼的代碼樹.這是Maven項目的標準佈局(應用代碼被放置在${basedir}/src/main/java而測試代碼放置在${basedir}/src/test/java,其中${basedir}表明包含pom.xml的目錄).

若是你在手動建立Maven項目,這個目錄結構是咱們強烈建議的.這是Maven規範.想了解更多訪問:http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

如今,咱們有了一個POM,一些應用代碼,一些測試代碼,你也許會問...

我如何編譯個人應用代碼

切換目錄到${basedir}並執行命令:

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安裝,這可能會耗費至關一下子(在上述輸出中,它耗費了四分鐘).若是你再次執行這個命令,Maven就不會去下載並且能夠快速執行命令.

正如你在上述輸出中所看到的,編譯好的class文件放在${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] ----------------------------------------------------------------------------

請注意:

1.Maven如今下載了更多的依賴.這些都是測試所須要的插件和依賴.(它已經有了編譯所需的依賴因此不會再次下載)

2.在編譯和運行測試以前Maven編譯了main代碼(全部的代碼都是最新的由於咱們自從上次編譯後沒有作任何改變)

若是你只是想要簡單額編譯測試代碼(不運行測試),能夠執行以下命令:

mvn test-compile

如今你可以編譯你的應用代碼,測試代碼,並運行測試,你將要進行下一個邏輯步驟因此你會問...

我如何建立一個JAR並安裝到本地倉庫

建立JAR是至關直接的經過執行下列命令:

mvn package

若是你看下項目的POM文件你會發現packaging元素被設置爲jar.這就是Maven如何知道要經過上述命令來產生JAR文件的緣由.如今你能夠查看${basedir}/target 目錄而後你會看見生成的JAR文件.

如今你想要安裝你已經生成的工件(JAR包)到本地倉庫(默認地址是:${basedir}/.m2/repository).想要了解更多關於Respository請訪問:http://maven.apache.org/guides/introduction/introduction-to-repositories.html

如今執行安裝:

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] ----------------------------------------------------------------------------

注意surefire插件(執行測試的)以一個特定的命名慣例查找包含測試的文件.

默認狀況下包含:

**/*Test.java
**/Test*.java
**/*TestCase.java

不包含:

**/Abstract*Test.java
**/Abstract*TestCase.java

你已經經歷了設置,構建,測試,打包,安裝一個指定Maven項目的過程.你可能已經注意到這已是絕大多數Maven項目會作的事情.而你所作的這一切都是基於一個18行的文件(POM).若是你使用提供了相同功能的典型的Ant構建文件來達到咱們目前爲止所作的,你會發現僅僅剛開始它就將達到POM的兩倍大小.Maven還有更多的功能提供給你而不須要添加任何額外的內容到咱們如今的POM中.而想在Ant中提供相同的功能你不得不添加額外的內容,而這更容易致使出錯.

因此咱們還可以免費獲得些什麼?即便是像上述這麼簡單的POM這裏也有大量開箱即用的插件可使用.咱們會提到一個專用的Maven推崇的特性之一:不須要任何工做,POM已經有足夠的信息來爲你的項目生成一個Web站點.你可能想要定製你的Maven站點,可是若是你時間緊迫,那麼你僅僅須要提供項目的基本信息而後執行下面的命令:

mvn site

這裏還有大量獨立的目標能夠被執行,例如:

mvn clean

這個命令將會移除target目錄在開始構建數據以前以便它是新鮮的

也許你想生成一個Intellij IDEA描述的項目:

mvn idea:idea

這能夠運行在項目的前一個想法--它將更新設置而不是新的開始

若是你使用Eclipse IDE:

mvn eclipse:eclipse

注意:一些相似的目標從Maven1.0到如今一直存在,如jar:jar,可是它們的行爲並不像你所指望的.目前,jar:jar不會從新編譯源碼,它僅僅簡單建立一個JAR在target/classes目錄,它假設其餘一塊兒已經完成...

什麼是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版本要老.

在發佈期間,版本從x.y-SNAPSHOT變成x.y.發佈過程增長開發版到x.(y+1)-SNAPSHOT.例如:1.0-SNAPSHOT版發佈成1.0版,而且新的開發版的版本爲1.1-SNAPSHOT.

我如何使用插件

不管什麼時候你想要自定義Maven項目的構建過程,它都經過添加或者從新配置插件.

Maven1.0的用戶請注意:在Maven1.0中,你將添加一些preGoal到maven.xml,一些entries到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>將應用給定的參數到每一個編譯插件的目標.在上述狀況下,編譯插件已經被做爲構建過程當中的一部分在使用而這僅僅是改變了配置.還能夠添加新的目標到過程當中,配置指定的目標.想要了解構建過程,請訪問:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

想找出可配置的插件,你能夠查閱http://maven.apache.org/plugins/

想知道如何配置一個插件的可用參數,請查閱:http://maven.apache.org/guides/mini/guide-configuring-plugins.html

我如何添加資源到個人JAR

另外一個常見用例是能夠被知足的:不對咱們上述的POM作任何改變就能夠將資源打包進JAR.針對於這項任務,Maven仍然依靠標準目錄佈局,這意味着只要採用Maven標準慣例你就能夠僅經過將資源放在一個標準目錄結構就能夠簡單的將它們打包進JAR.

在咱們下面的例子中你能夠看見咱們添加了一個用來存聽任何咱們想要打包進JAR的資源的目錄${basedir}/src/main/resources.Maven採用的規則至關簡單:任何被放置在 ${basedir}/src/main/resources目錄下的目錄或文件將會被打包進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

因此你能夠看見在咱們的例子中咱們有個包含了application.properties文件的META-INF目錄被放置在了指定目錄 ${basedir}/src/main/resources下.若是你解壓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目錄下.你也會在那裏發現一些其餘的文件如:MANIFEST.MF,pom.xml,pom.properties等,這些是Maven中JAR包的標準生成.Maven會默認生成一個若是你沒有本身建立一個manifest.(你也能夠修改默認manifest中的項,稍後你會接觸到).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

爲你的單元測試添加資源到類路徑的作法和你添加資源進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中作到這點,咱們能夠經過使用語法${<property name>}將目標屬性的引用添加到資源文件中.這個屬性能夠是在pom.xml中定義的一個值,能夠是用戶setting.xml中定義的一個值,還能夠是一個外部屬性文件中的一個屬性甚至是系統屬性.

想在拷貝時過濾資源,只須要在你的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/resoures目錄.全部咱們以前提供的信息都和默認值相同,可是由於filtering的默認值是false,因此爲了覆蓋這個值咱們要添加它到pom.xml並設置爲true.

引用在pom.xml中定義的屬性,屬性名使用定義了相應值的XML元素名,由於根節點是project元素,因此${project.name}引用了項目的名稱,${project.version}引用了項目的版本,${project.build.finalName}引用了構建項目打包後產生的文件的最終名稱,等等.注意有些POM元素有默認值,因此不必在pom.xml中顯式聲明它們由於它們的值是可用的.相似的,用戶setting.xml中的值能夠經過以"settings"打頭的屬性名來引用(如:${settings.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
java.version=${java.version}
command.line.prop=${command.line.prop}

當咱們再次執行mvn process-resources(注意在命令中command.line.prop屬性的定義),application.properties文件將會包含來自系統屬性的值:

mvn process-resources "-Dcommand.line.prop=hello again"

我如何使用外部依賴

你可能已經發現咱們在上面的例子中已經使用了dependencies元素.事實上,你已是一直在使用外部依賴了,不過咱們這裏會對它的具體工做原理稍微討論些細節.想了解更多,請自行查閱:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

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>

對於每個外部依賴,你至少須要定義四項:groupId,artifactId,version,scope.前三項和pom.xml中用來構建項目的三個元素的含義相同.scope代表你的項目要怎麼使用這些依賴,它的值能夠是compile,test和runtime.要想了解全部你能夠爲依賴指定的詳細信息,請查閱:http://maven.apache.org/ref/current/maven-model/maven.html

想了解依賴原理的全部信息,請查閱:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

經過這個依賴的信息,Maven將在構建項目的時候引用依賴.Maven引用的依賴從哪裏來?Maven在你的本地倉庫查詢全部依賴.在前一章節,咱們從咱們的項目安裝了工件 (my-app-1.0-SNAPSHOT.jar) 到本地倉庫.一旦它安裝到了那裏,另外一個項目就能夠經過在pom.xml中添加依賴信息來簡單的引用這個jar:

<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會下載不少東西.(這些都是用來構建項目的插件所需的依賴).默認狀況下,Maven使用的遠程倉庫是在http://repo.maven.apache.org/maven2/.你也能夠設置本身的遠程倉庫(也許是大家公司的中央庫)經過替換或者添加默認遠程倉庫.更多關於倉庫的信息請查閱:http://maven.apache.org/guides/introduction/introduction-to-repositories.html

讓咱們添加另外一個依賴到咱們的項目中.讓咱們假設咱們已經添加了一些日誌代碼而且須要添加log4j做爲依賴.首先,咱們須要知道log4j的 groupId,artifactId,version .咱們能夠瀏覽ibiblio來查找它,或者使用Google搜索:"site:www.ibiblio.org maven2 log4j".搜索結果顯示一個目錄/maven2/log4j/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文件旁邊,咱們能夠看見一個目錄對應到各個版本的log4j庫.在每一個目錄中,咱們能夠找到實際的jar文件和pom文件和另外一個maven-matedata.xml文件.這裏還會有對應的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到遠程倉庫

爲了部署jars到一個外部倉庫,你必須在pom.xml中配置倉庫的URL並在settings.xml認證鏈接倉庫的信息.

這裏有個使用SCP,用戶名/密碼認證的例子:

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>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.xml:

<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服務器,而且它sshd_config文件中的參數"PasswordAuthentication"設置爲"no",那麼你每次鏈接都須要輸入用戶名密碼來進行驗證.(儘管你可使用另外一個ssh客戶機來輸入用戶名密碼進行登陸).因此可能想要切換成公鑰驗證.

若是在settings.xml中使用密碼咱們應該保持謹慎.更多信息查閱:http://maven.apache.org/guides/mini/guide-encryption.html

我該如何建立文檔

讓咱們開始Maven的文檔系統,你可使用原型機制來爲你的項目生成站點經過以下命令:

mvn archetype:generate \
  -DarchetypeGroupId=org.apache.maven.archetypes \
  -DarchetypeArtifactId=maven-archetype-site \
  -DgroupId=com.mycompany.app \
  -DartifactId=my-app-site

訪問如下連接來學習如何爲你的項目生成文檔:http://maven.apache.org/guides/mini/guide-site.html

我如何構建項目的其餘類型

注意:生命週期應用於任何項目類型.例如,返回基礎目錄咱們能夠建立一個簡單的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>

注意<packaging>元素,它告訴Maven把項目構建成WAR.切換到webapp項目目錄執行:

mvn clean 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.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>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文件中添加<parent>元素:

<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 clean install

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的<packaging>元素的值是"pom"而且定義了<modules>來羅列全部子模塊.這告訴Maven在全部子項目上執行全部操做而不是在當前項目上.(使用非遞歸選項--non--recursive來覆蓋命令的行爲).

而後,咱們告訴WAR它須要my-app的JAR.這作了一些事情:它讓WAR中的全部代碼在類路徑中均可用,它確保JAR包在WAR包以前被構建,它代表了JAR做爲插件添加到了WAR的類庫目錄.

你也許已經發現junit-4.11.jar是一個依賴,可是沒有出如今WAR包中.這是由於它的<scope>的值是"test",代表僅僅在測試時須要使用.因此他不會在編譯的時候添加進來.

最後一步是包含父級定義.這和你可能熟悉的Maven1.0中的extend元素不一樣:這確保經過在倉庫中查詢POM老是能夠被放置即便項目是分佈式的.

相關文章
相關標籤/搜索