Apache Maven 入門篇(下)
做者:George Ma html
第一篇文章大概的介紹了一下Apache Maven以及它的下載和安裝,而且運行了一個簡單的示例。那麼在對maven有了一點接觸後,接下去的一步是要了解maven的核心概念,這樣才能在使用maven的時候遊刃有餘。 java
接下來咱們介紹下面這幾個核心概念: web
- POM (Project Object Model)
- Maven 插件
- Maven 生命週期
- Maven 依賴管理
- Maven 庫
POM (Project Object Model)
一個項目全部的配置都放置在 POM 文件中:定義項目的類型、名字,管理依賴關係,定製插件的行爲等等。好比說,你能夠配置 compiler 插件讓它使用 java 1.5 來編譯。 apache
如今看一下第一篇文章中示例的 POM 服務器
Xml 代碼 oracle
<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.helloworld</groupId>
<artifactId>helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>helloworld</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
在 POM 中,groupId, artifactId, packaging, version 叫做 maven 座標,它能惟一的肯定一個項目。有了 maven 座標,咱們就能夠用它來指定咱們的項目所依賴的其餘項目,插件,或者父項目。通常 maven 座標寫成以下的格式: maven
groupId:artifactId:packaging:version
像咱們的例子就會寫成: ide
com.mycompany.helloworld: helloworld: jar: 1.0-SNAPSHOT
咱們的 helloworld 示例很簡單,可是大項目通常會分紅幾個子項目。在這種狀況下,每一個子項目就會有本身的 POM 文件,而後它們會有一個共同的父項目。這樣只要構建父項目就可以構建全部的子項目了。子項目的 POM 會繼承父項目的 POM。另外,全部的 POM都繼承了一個 Super-POM。Super-POM 設置了一些默認值,好比在第一篇文章中提到的默認的目錄結構,默認的插件等等,它遵循了慣例優於配置的原則。因此儘管咱們的這個 POM 很簡單,可是這只是你看得見的一部分。運行時候的 POM 要複雜的多。 若是你想看到運行時候的 POM 的所有內容的話,能夠運行下面的命令: 單元測試
$mvn help:effective-pom
Maven 插件
在第一篇文章中,咱們用了 mvn archetype:generate 命令來生成一個項目。那麼這裏的 archetype:generate 是什麼意思呢?archetype 是一個插件的名字,generate是目標(goal)的名字。這個命令的意思是告訴 maven 執行 archetype 插件的 generate 目標。插件目標一般會寫成pluginId:goalId 測試
一個目標是一個工做單元,而插件則是一個或者多個目標的集合。好比說Jar插件,Compiler插件,Surefire插件等。從看名字就能知道,Jar 插件包含創建Jar文件的目標, Compiler 插件包含編譯源代碼和單元測試代碼的目標。Surefire 插件的話,則是運行單元測試。
看到這裏,估計你能明白了,mvn 自己不會作太多的事情,它不知道怎麼樣編譯或者怎麼樣打包。它把構建的任務交給插件去作。插件定義了經常使用的構建邏輯,可以被重複利用。這樣作的好處是,一旦插件有了更新,那麼全部的 maven 用戶都能獲得更新。
Maven 生命週期
在上一篇文章中,咱們用的第二個命令是:mvn package。這裏的 package 是一個maven的生命週期階段 (lifecycle phase )。生命週期指項目的構建過程,它包含了一系列的有序的階段 (phase),而一個階段就是構建過程當中的一個步驟。
那麼生命週期階段和上面說的插件目標之間是什麼關係呢?插件目標能夠綁定到生命週期階段上。一個生命週期階段能夠綁定多個插件目標。當 maven 在構建過程當中逐步的經過每一個階段時,會執行該階段全部的插件目標。
maven 能支持不一樣的生命週期,可是最經常使用的是默認的Maven生命週期 (default Maven lifecycle )。若是你沒有對它進行任何的插件配置或者定製的話,那麼上面的命令 mvn package 會依次執行默認生命週期中直到包括 package 階段前的全部階段的插件目標:
-
process-resources 階段:resources:resources
-
compile 階段:compiler:compile
-
process-classes 階段:(默認無目標)
-
process-test-resources 階段:resources:testResources
-
test-compile 階段:compiler:testCompile
-
test 階段:surefire:test
-
prepare-package 階段:(默認無目標)
-
package 階段:jar:jar
Maven 依賴管理
以前咱們說過,maven 座標可以肯定一個項目。換句話說,咱們能夠用它來解決依賴關係。在 POM 中,依賴關係是在 dependencies 部分中定義的。在上面的 POM 例子中,咱們用 dependencies 定義了對於 junit 的依賴:
Xml 代碼
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies>
那這個例子很簡單,可是實際開發中咱們會有複雜得多的依賴關係,由於被依賴的 jar 文件會有本身的依賴關係。那麼咱們是否是須要把那些間接依賴的 jar 文件也都定義在POM中呢?答案是不須要,由於 maven 提供了傳遞依賴的特性。
所謂傳遞依賴是指 maven 會檢查被依賴的 jar 文件,把它的依賴關係歸入最終解決的依賴關係鏈中。針對上面的 junit 依賴關係,若是你看一下 maven 的本地庫(咱們立刻會解釋 maven 庫)~/.m2/repository/junit/junit/3.8.1/ ,
你會發現 maven 不但下載了 junit-3.8.1.jar,還下載了它的 POM 文件。這樣 maven 就能檢查 junit 的依賴關係,把它所須要的依賴也包括進來。
在 POM 的 dependencies 部分中,scope 決定了依賴關係的適用範圍。咱們的例子中 junit 的 scope 是 test,那麼它只會在執行 compiler:testCompile and surefire:test 目標的時候纔會被加到 classpath 中,在執行 compiler:compile 目標時是拿不到 junit 的。
咱們還能夠指定 scope 爲 provided,意思是 JDK 或者容器會提供所需的jar文件。好比說在作web應用開發的時候,咱們在編譯的時候須要 servlet API jar 文件,可是在打包的時候不須要把這個 jar 文件打在 WAR 中,由於servlet容器或者應用服務器會提供的。
scope 的默認值是 compile,即任什麼時候候都會被包含在 classpath 中,在打包的時候也會被包括進去。
Maven 庫
當第一次運行 maven 命令的時候,你須要 Internet 鏈接,由於它要從網上下載一些文件。那麼它從哪裏下載呢?它是從 maven 默認的遠程庫(http://repo1.maven.org/maven2) 下載的。這個遠程庫有 maven 的核心插件和可供下載的 jar 文件。
可是不是全部的 jar 文件都是能夠從默認的遠程庫下載的,好比說咱們本身開發的項目。這個時候,有兩個選擇:要麼在公司內部設置定製庫,要麼手動下載和安裝所需的jar文件到本地庫。
本地庫是指 maven 下載了插件或者 jar 文件後存放在本地機器上的拷貝。在 Linux 上,它的位置在 ~/.m2/repository,在 Windows XP 上,在 C:\Documents and Settings\username\.m2\repository ,在 Windows 7 上,在 C:\Users\username\.m2\repository。當 maven 查找須要的 jar 文件時,它會先在本地庫中尋找,只有在找不到的狀況下,纔會去遠程庫中找。
運行下面的命令能把咱們的 helloworld 項目安裝到本地庫:
$mvn install
一旦一個項目被安裝到了本地庫後,你別的項目就能夠經過 maven 座標和這個項目創建依賴關係。好比若是我如今有一個新項目須要用到 helloworld,那麼在運行了上面的 mvn install 命令後,我就能夠以下所示來創建依賴關係:
Xml 代碼
<dependency> <groupId>com.mycompany.helloworld</groupId> <artifactId>helloworld</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
好了,maven 的核心概念就簡單的介紹到這裏。至於在 Eclipse 中如何使用 maven,這個網上不少了,google 一下就行。