1. 程式人生 > >maven的核心知識點

maven的核心知識點

 Maven學過java的都認識,但是大多數人只知道了他的依賴打包功能,對於其他核心功能理解並不深,下面我來講講maven的核心知識:

座標與依賴、
倉庫、
生命週期與外掛、
模組聚合、
模組繼承
等概念。並通過一個開發Maven外掛的例項來深入瞭解Maven的核心機制. 而對於 如何配置Maven、Nexus私服、Jenkins持續整合、Maven測試、構建Web、資源過濾、自定義Archetype 等相對簡單、講解繁瑣且網上有大量實踐案例的內容沒有涉及. 本文的目標是希望讀者能夠通過本文能對Maven核心原理有個相對深入的理解.

座標與依賴

為了能夠自動化的解析任何一個java構件,maven必須將他們唯一的標識,這就是依賴管理的底層基礎,座標————maven的座標為java引入了秩序,任何一個構件都必須為自己定義一個座標,如groupid,artifactId、version、packaging、classfier:

<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
<packaging>jar</packaging>

groupId: 定義當前模組隸屬的實際Maven專案, 表示方式與Java包類似 groupId不應直接對應專案隸屬的公司/組織(一個公司/組織下可能會有很多的專案).
artifactId: 定義實際專案中的一個Maven模組 推薦使用專案名作為artifactId字首, 如:commons-lang3以commons作為字首(因為Maven打包預設以artifactId作為字首)
version :

定義當前專案所處版本(如1.0-SNAPSHOT、4.2.7.RELEASE、1.2.15、14.0.1-h-3 等) Maven版本號定義約定: <主版本>.<次版本>.<增量版本>-<里程碑版本>
packaging: 定義Maven專案打包方式, 通常打包方式與所生成構件副檔名對應 有jar(預設)、war、pom、maven-plugin等.
classifier: 用來幫助定義構建輸出的一些附屬構件(如javadoc、sources) 不能直接定義專案的classifier(因為附屬構件不是由專案預設生成, 須有附加外掛的幫助)

依賴:
maven最出名的就是maven的依賴管理,用了之後,我們不需再去開源網站一一下載元件,只需一個依賴宣告即可:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.2.7.RELEASE</version>

    <type>jar</type>
    <scope>compile</scope>
    <optional>false</optional>
    <exclusions>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

依賴傳遞\
maven的依賴傳遞機制會自動幫助我們載入我們依賴包的依賴,如:我們的專案依賴了spring-core, 而spring-core又依賴了commons-logging:
這裡寫圖片描述
有了依賴傳遞機制, 在專案中添加了spring-core依賴時就不用再去考慮它依賴了什麼, 也不用擔心引入多餘的依賴. Maven會解析各個直接依賴的POM, 將必要的間接依賴以傳遞性依賴的形式引入到當前目錄中(inherits from its parents, or from its dependencies, and so on).
(依賴調節原則: 1. 路徑最近者優先; 2. 第一宣告者優先.)
依賴管理
Maven提供了dependency外掛可以對Maven專案依賴檢視以及優化, 如mvndependency:tree, mvn dependency:help.

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

Maven 倉庫

Maven 中, 任何一個依賴、外掛或專案構建的輸出, 都可稱為構件, 而Maven倉庫就是集中儲存這些構件的地方.

maven有兩類倉庫,本地倉庫和遠端倉庫,當maven根據座標去尋找構件的時候,maven會先找本地倉庫,如果沒有再去遠端倉庫去下載
本地倉庫:預設地址是~/.m2/,一個構件只有在本地倉庫存在後才能被maven專案所引用。
遠端倉庫也分為兩類中央倉庫和私服。
中央倉庫:當我們建立maven專案時,原始的本地倉庫是空的,所以我們要有一個預設的遠端的倉庫提供我們去下載,中央倉庫就是這樣的倉庫。
私服:
這裡寫圖片描述

私服屬於一種特殊的遠端倉庫,通過代理廣域網的遠端倉庫,maven使用者傳送下載外掛請求,私服收到後如果不存在該構件就去找中央倉庫去下載,並快取下來,再為使用者提供下載服務,此外如果在外部中央倉庫沒有的構件,如公司內部的外掛,maven也可以上傳到私服,供公司其他maven下載使用。架設私服需對pom做如下配置:

<project >
    ...
    <distributionManagement>
        <repository>
            <id>releases</id>
            <url>http://mvn.server.com/nexus/content/repositories/releases/</url>
        </repository>
        <snapshotRepository>
            <id>snapshots</id>
            <url>http://mvn.server.com/nexus/content/repositories/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

</project>

repository表示釋出版本構件的倉庫, snapshotRepository代表快照版本的倉庫.
id為該遠端倉庫唯一標識, url表示該倉庫地址.
配置正確後, 執行$ mvn clean deploy則可以將專案構建輸出的構件部署到對應配置的遠端倉庫.

注: 往遠端倉庫部署構件時, 往往需要認證: 需要在settings.xml中建立servers元素, 其id與倉庫的id匹配, 詳見: Password Encryption.

生命週期與外掛

maven將所有專案的構建過程都統一抽象成生命週期:專案的清理,初始化,編譯,測試,打包,整合測試,驗證,部署,站點生成….
幾乎所有的專案都能對映到這些生命週期上去,但是生命週期是抽象的,任務執行都是靠外掛來完成,每個生命週期階段都由一個或多個外掛完成,maven為大多數步驟綁定了預設的外掛,當然如果需要可以自定義外掛。
這裡寫圖片描述
Maven 擁有三套相互獨立的生命週期: clean、default 和 site, 而每個生命週期包含一些phase階段, 階段是有順序的, 並且後面的階段依賴於前面的階段. 而三套生命週期相互之間卻並沒有前後依賴關係, 即呼叫site週期內的某個phase階段並不會對clean產生任何影響.

clean生命週期的目的是清理專案:
這裡寫圖片描述
執行如$ mvn clean;

default生命週期定義了真正構建時所需要執行的所有步驟:
這裡寫圖片描述

執行如$ mvn clean install;

site生命週期的目的是建立和釋出專案站點: Maven能夠基於POM所包含的資訊,自動生成一個友好的站點,方便團隊交流和釋出專案資訊

這裡寫圖片描述

執行命令如$ mvn clean deploy site-deploy;

外掛

生命週期的階段phase與外掛的目標goal相互繫結, 用以完成實際的構建任務. 而對於外掛本身, 為了能夠複用程式碼,它往往能夠完成多個任務, 這些功能聚集在一個外掛裡,每個功能就是一個目標.
如:$ mvn compiler:compile: 冒號前是外掛字首, 後面是該外掛目標(即: maven-compiler-plugin的compile目標).
而該目標綁定了default生命週期的compile階段:
這裡寫圖片描述

這裡寫圖片描述

自定義繫結

除了內建繫結以外, 使用者還能夠自定義將某個外掛目標繫結到生命週期的某個階段上. 如建立專案的原始碼包, maven-source-plugin外掛的jar-no-fork目標能夠將專案的主程式碼打包成jar檔案, 可以將其繫結到verify階段上:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>3.0.0</version>
            <executions>
                <execution>
                    <id>attach-sources</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>jar-no-fork</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

executions下每個execution子元素可以用來配置執行一個任務.

maven-help-plugin

mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plugin[:3.0.0] [-Ddetail] [-Dgoal=jar-no-fork]