天天看點

maven-核心概念1 坐标2生命周期3依賴管理4插件

1 坐标

1 什麼是坐标?

在平面幾何中坐标(x,y)可以辨別平面中唯一的一點。在maven中坐标就是為了定位一個唯一确定的jar包。

Maven世界擁有大量建構,我們需要找一個用來唯一辨別一個建構的統一規範

擁有了統一規範,就可以把查找工作交給機器

2 Maven坐标主要組成

maven坐标元素包括groupId,artifactId,version,packaging,classifier。隻要提供正确的坐标元素,maven就能找到對應的構件。

基本坐标簡解

groupId:(公司或組織域名倒序) 定義目前這個maven項目錄屬的實際項目,表示方式通常與域名反向相對應。

artifactId:(子產品名,也是實際項目的名稱 )定義實際項目中的一個maven項目,推薦做法使用實際項目名稱作為artifactId的字首。 maven生成的構件,其檔案名會以artifactId作為開頭。

version:定義maven項目目前所處的版本。

packaging:定義maven項目的打包方式,如果不定義packaging,預設使用jar。

classifier:幫助定義建構輸出的一些附屬構件。不能直接定義classifier。

詳解

1 groupId

定義目前Maven項目隸屬的實際項目。首先,Maven項目和實際項目不一定是一對一的關系。比如SpringFramework這一實際項目,其對應的Maven項目會有很多,如spring-core、spring-context等。這是由于Maven中子產品的概念,是以,一個實際項目往往會被劃分成很多子產品。其次,groupId不應該對應項目隸屬的組織或公司。原因很簡單,一個組織下會有很多實際項目,如果groupId隻定義到組織級别,而後面我們會看到,artifactId隻能定義Maven項目(子產品),那麼實際項目這個層将難以定義。最後,groupId的表示方式與Java包名的表示方法類似,通常與域名反向一一對應。上例中,groupId為org.sonatype.nexus,org.sonatype表示Sonatype公司建立的一個非營利性組織,nexus表示Nexus這一實際項目,該groupId與域名nexus.sonatype.org對應。

2artifactId

該元素定義實際項目中的一個Maven項目(子產品),推薦的做法是使用實際項目名稱作為artifactId的字首。比如上例中的artifactId是nexus-indexer,使用了實際項目名nexus作為字首,這樣做的好處是友善尋找實際構件。在預設情況下,Maven生成的構件,其檔案名會以artifactId作為開頭,如nexus-indexer-2.0.0.jar,使用實際項目名稱作為字首之後,就能友善從一個lib檔案夾中找到某個項目的一組構件。考慮有5個項目,每個項目都有一個core子產品,如果沒有字首,我們會看到很多core-1.2.jar這樣的檔案,加上實際項目名字首之後,便能很容易區分foo-core-1.2.jar、bar-core-1.2.jar…

3 version

該元素定義Maven項目目前所處的版本,如上例中nexus-indexer的版本是2.0.0。需要注意的是,Maven定義了一套完成的版本規範,以及快照(SNAPSHOT)的概念。

4 packaging

該元素定義Maven項目的打包方式。首先,打包方式通常與所生成構件的檔案擴充名對應,如上例中packaging為jar,最終的檔案名為nexus-indexer-2.0.0.jar,而使用war打包方式的Maven項目,最終生成的構件會有一個.war檔案,不過這不是絕對的。其次,打包方式會影響到建構的生命周期,比如jar打包和war打包會使用不同的指令。最後,當不定義packaging的時候,Maven會使用預設值jar。

5 classifier

該元素用來幫助定義建構輸出的一些附屬建構。附屬構件與主構件對應,如上例中的主構件是nexus-indexer-2.0.0.jar,該項目可能還會通過使用一些插件生成如nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources.jar這樣一些附屬建構,其包含了Java文檔和源代碼。這時候,javadoc和sources就是這兩個附屬建構的classifier。這樣,附屬建構也就擁有了自己唯一的坐标。還有一個關于classifier的典型例子是TestNG,TestNG的主構件是基于Java1.4平台的,而他又提供了一個classifier為jdk5的附屬構件。注意,不能直接定義項目的classifier,因為附屬建構不是項目直接預設生成地,而是由附加的插件幫助生成。

上述5個元素中,groupId、artifactId、version是必須定義的,packaging是可選的(預設為jar),而classifier是不能直接定義的。

同時,項目建構的檔案名和坐标相對應的,一般的規則為artifactId-version [-classifier] .packaging,[-classifier]表示可選。比如上例nexus-indexer的主構件為nexus-indexer-2.0.0.jar,附屬建構有nexus-indexer-2.0.0-javaodc.jar。這裡還要強調一點是,packaging 并非一定與構件擴充名對應,比如packaging為maven-plugin的構件擴充名為jar。

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.0</version>//以上三個為依賴的基本坐标,maven根據坐标才能找到依賴
        <type>jar</type>//依賴的類型
        <scope>test</scope>//依賴的範圍
        <classifier>jdk15</classifier>//它表示在相同版本下針對不同的環境或者jdk使用的jar
        <optional>true</optional>//是否為可選依賴
        <exclusions>//用來排除傳遞性依賴
            <exclusion>
                <groupId>org.apache.maven</groupId>
                <artifactId>maven-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
  </dependencies>
           

2生命周期

Maven 建構生命周期定義了一個項目建構跟釋出的過程。

一個典型的 Maven 建構(build)生命周期是由以下幾個階段的序列組成的:

maven-核心概念1 坐标2生命周期3依賴管理4插件
maven-核心概念1 坐标2生命周期3依賴管理4插件

為了完成 default 生命周期,這些階段(包括其他未在上面羅列的生命周期階段)将被按順序地執行。

Maven 有以下三個标準的生命周期:

clean:項目清理的處理

default(或 build):項目部署的處理

site:項目站點文檔建立的處理

生命周期可以了解為項目建構的步驟集合。

生命周期是由多個階段(Phase)組成。每個階段都是一個完整的功能,比如mvn clean中的clean就是一個階段。

1 Clean生命周期

pre-clean 執行一些需要在clean之前完成的工作

clean 移除所有上一次建構生成的檔案

post-clean 執行一些需要在clean之後立刻完成的工作

mvn clean指令,等同于 mvn pre-clean clean。隻要執行後面的指令,那麼前面的指令都會執行,不需要再重新去輸入指令。

有Clean生命周期,在生命周期又有clean階段。

2 Default生命周期(重點)

validate

generate-sources

process-sources

generate-resources

process-resources 複制并處理資源檔案,至目标目錄,準備打包。

compile 編譯項目的源代碼。

process-classes

generate-test-sources

process-test-sources

generate-test-resources

process-test-resources 複制并處理資源檔案,至目标測試目錄。

test-compile 編譯測試源代碼。

process-test-classes

test 使用合适的單元測試架構運作測試。這些測試代碼不會被打包或部署。

prepare-package

package 接受編譯好的代碼,打包成可釋出的格式,如 JAR 。

pre-integration-test

integration-test

post-integration-test

verify

install 将包安裝至本地倉庫,以讓其它項目依賴。

deploy 将最終的包複制到遠端的倉庫,以讓其它開發人員與項目共享。

在maven中,隻要在同一個生命周期,你執行後面的階段,那麼前面的階段也會被執行,而且不需要額外去輸入前面的階段,這樣大大減輕了程式員的工作。

3 Site生命周期

pre-site 執行一些需要在生成站點文檔之前完成的工作

site 生成項目的站點文檔

post-site 執行一些需要在生成站點文檔之後完成的工作,并且為部署做準備

site-deploy 将生成的站點文檔部署到特定的伺服器上

3依賴管理

依賴範圍

maven-核心概念1 坐标2生命周期3依賴管理4插件

其中依賴範圍scope 用來控制依賴和編譯,測試,運作的classpath的關系. 主要的是三種依賴關系如下:

1.compile: 預設編譯依賴範圍。對于編譯,測試,運作三種classpath都有效

2.test:測試依賴範圍。隻對于測試classpath有效

3.provided:已提供依賴範圍。對于編譯,測試的classpath都有效,但對于運作無效。因為由容器已經提供,例如servlet-api

4.runtime:運作時提供。例如:jdbc驅動

依賴傳遞

A、B、C

B工程依賴A工程,C工程依賴B工程,那麼B工程是C工程的直接依賴,A工程是C工程的間接依賴

maven-核心概念1 坐标2生命周期3依賴管理4插件

标題依賴範圍傳遞

maven-核心概念1 坐标2生命周期3依賴管理4插件

 當第二依賴的範圍是compile的時候,傳遞性依賴的範圍與第一直接依賴的範圍一緻。

 當第二直接依賴的範圍是test的時候,依賴不會得以傳遞。

 當第二依賴的範圍是provided的時候,隻傳遞第一直接依賴範圍也為provided的依賴,且傳遞性依賴的範圍同樣為 provided;

 當第二直接依賴的範圍是runtime的時候,傳遞性依賴的範圍與第一直接依賴的範圍一緻,但compile例外,此時傳遞的依賴範圍為runtime;

标題依賴沖突

1 跨pom檔案的沖突

MavenFirst的pom檔案中依賴來junit的4.9版本,那邊MavenSecond和MavenThird中都是使用了4.9版本。

maven-核心概念1 坐标2生命周期3依賴管理4插件

如果MavenSecond中重新依賴junit的4.8版本,那麼MavenSecond和MavenThird中都是使用了4.8本,這展現來依賴的就近使用原則。

maven-核心概念1 坐标2生命周期3依賴管理4插件

依賴的jar包如下:

maven-核心概念1 坐标2生命周期3依賴管理4插件

2 同一個pom檔案的沖突

maven-核心概念1 坐标2生命周期3依賴管理4插件

可選依賴

maven-核心概念1 坐标2生命周期3依賴管理4插件

排除依賴

maven-核心概念1 坐标2生命周期3依賴管理4插件

4插件

我們都知道Maven本質上是一個插件架構,它的核心并不執行任何具體的建構任務,所有 這些任務都交給插件來完成,例如編譯源代碼是由maven- compiler-plugin完成的。

插件(plugin),每個插件都能實作一個階段的功能。Maven的核心是生命周期,但是生命周期相當于主要指定了maven指令執行的流程順序,而沒有真正實作流程的功能,功能是有插件來實作的。

比如:compile就是一個插件實作的功能。

編譯插件

maven-核心概念1 坐标2生命周期3依賴管理4插件

Tomcat插件

如果使用maven的tomcat插件的話,那麼本地則不需要安裝tomcat。

maven-核心概念1 坐标2生命周期3依賴管理4插件