Maven實戰:pom.xml與settings.xml

pom.xml與settings.xmljava

pom.xml與setting.xml,能夠說是Maven中最重要的兩個配置文件,決定了Maven的核心功能,雖然以前的文章零零碎碎有提到過pom.xml和settings.xml裏面的內容,但都是大略帶過,學習與研究地並不細緻,本文的目的就是詳細研究下這兩個Maven重要的配置文件,從這兩個配置文件能夠牽出很是多的Maven話題。spring

 

Maven座標express

首先談一下爲何要使用Maven座標。apache

Maven世界擁有數量很是巨大的構件,也就是平時使用的一些jar、war等文件,在Maven爲這些構件引入座標概念以前,咱們沒法使用任何一種方式來惟一標識全部這些構件。所以,若是須要使用Spring依賴,那麼就去Spring官網尋找;若是須要使用log4j依賴,那麼又去Apache官網尋找。又由於各個網站風格迥異,大量時間花費在了搜索和瀏覽網頁的工做上。沒有統一規範與法則,工做就沒法自動化,重複性的勞動原本就應該交給機器來作安全

Maven定義了這樣一組規則:世界上任何一個構件均可以使用Maven座標惟一標識,Maven座標元素包括groupId、artifactId、version、packaging、classifier,如今只要咱們提供正確的元素座標,Maven就能找到對應的構件。至於去哪裏下載,Maven自己內置了一箇中央倉庫的地址"http://repo1.maven.org/maven2",該中央倉庫包含了世界上絕大部分流行的開源項目構件,Mavne會在須要的時候去那裏下載,固然也能夠配置本身的中央倉庫地址,去本身的中央倉庫下載構件。服務器

舉個例子,Spring的context:maven

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.2.6.RELEASE</version>
</dependency

看一下下屬的各個元素:學習

  • groupId:定義當前Maven項目隸屬的實際項目。因爲Maven項目和實際項目未必是一對一的關係,好比SpringFramework這個實際項目可能對應的Maven項目有不少,像core、context、expression等等,所以groupId不該該對應項目隸屬的公司或組織,不然artifact將很難定義
  • artifactId:定義實際項目中的一個Maven模塊,推薦的作法是使用實際項目名稱做爲artifactId的前綴,這樣會很方便去尋找實際構件
  • version:定義Maven項目當前所處的版本,如上面的spring-context就是4.2.6的,RELEASE表示正式發行版本
  • packing:定義Maven項目的打包方式,這項不是必須的,沒列出來,不定義默認就是jar的打包方式
  • classifier:幫助定義構件輸出的一些附屬構件,好比xxx-javadoc.jar、xxx-sources.jar,附屬構件與主構件對應,這項是不能直接定義的

Maven座標的概念大體上就是這樣,理解Maven座標,是理解Maven很重要的一步。網站

 

傳遞性依賴url

什麼是傳遞性依賴,以Spring舉一個例子。使用Spring的時候會依賴於其餘開源的類庫,此時有兩種作法:

一、下載一個很大的.zip包,裏面包含了全部Spring的jar,可是這麼作每每就引入了許多沒必要要的依賴

二、只下載spring相關的.zip包,不包含依賴,實際使用的時候根據出錯信息,加入須要的其餘依賴

顯然這兩種作法都很是麻煩,Maven的傳遞性依賴機制很好地解決了這一問題。打開spring-core-4.1.0.RELEASE的pom.xml,我截取一段關鍵部分:

<dependencies>
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.9</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1.3</version>
      <scope>compile</scope>
    </dependency>
    ...
</dependencies>

好比A項目依賴了spring-core,spring-core又依賴了commons-codec和commons-logging,那麼commons-codec和commons-logging就是A項目的一個傳遞性依賴。有了傳遞性依賴機制,在使用spring-core的時候就不用去考慮它依賴了什麼,也不用擔憂引入多餘的依賴,Maven會解析各個直接依賴的POM,將那些必要的間接依賴,以傳遞性依賴的形式引入到當前的項目中去。

有了傳遞性依賴機制,一方面大大簡化和方便了依賴聲明,另外一方面在大部分狀況下咱們只須要關心項目的直接依賴是什麼而不用考慮這些直接依賴會引入什麼傳遞性依賴,不過有時候傳遞性依賴也會有一些問題,此時咱們就須要清除地知道該傳遞性依賴是從哪條路徑引入的,這就叫依賴調解,依賴調解主要有兩點原則:

一、A->B->C->X(1.0),A->D->X(2.0),此時兩條依賴路徑上有兩個版本的X,此時遵循路徑最近者優先,所以X(2.0)將被解析使用

二、A->B->Y(1.0),A->C->Y(2.0),Y(1.0)和Y(2.0)的依賴長度是同樣的,從Maven2.0.9開始,此時遵循第一聲明者優先,即順序最靠前的那個依賴優先

 

排除依賴

傳遞性依賴會給項目隱式地引入不少依賴,這極大地簡化了項目依賴的管理,可是有時候這種特性也會帶來問題。好比有種狀況:

當前項目依賴A,A因爲某些緣由依賴了另一個類庫的SNAPSHOT版本,那麼這個SNAPSHOT就會成爲當前項目的傳遞性依賴,二SNAPSHOT的不穩定性將直接影響到當前的項目,此時就須要排除該SNAPSHOT,而且在當前項目中聲明該類庫的某個正式發佈的版本

排除依賴很簡單,看一下寫法:

<dependency>
    <groupId>com.alibaba.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>3.2.7</version>
    <exclusions>
        <exclusion>
            <groupId>apache-lang</groupId>
            <artifactId>commons-lang</artifactId>
        </exclusion>
    </exclusions>
</dependency>

這裏我引入了rocketmq的依賴,可是我不想依賴rocketmq裏面的apache-lang,而想要本身引入依賴,因此我就把apache-lang給排除了。

這裏須要注意的是,聲明exclusion的時候只須要groupId和artifactId便可,而不須要version元素,這是由於只須要groupId和artifactId就能惟必定位依賴圖中的某個依賴。換句話說,Maven解析後的依賴中,不可能出現groupId和artifactId相同,可是version不一樣的兩個依賴。

 

settings.xml

settings.xml裏面是Maven的基本配置,元素比較多,逐一看一下

一、proxy

proxy表示Maven的代理,看一下寫法:

<proxies>
    <proxy>
      <id>optional</id>
      <active>true</active>
      <protocol>http</protocol>
      <username>proxyuser</username>
      <password>proxypass</password>
      <host>proxy.host.net</host>
      <port>80</port>
      <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    </proxy>
</proxies>

須要proxy是由於不少時候你所在的公司基於安全因素考慮,要求你使用經過安全認證的代理訪問因特網。這種狀況下,就須要爲Maven配置HTTP代理,才能讓它正常訪問外部倉庫,如下載所須要的資源。proxies下能夠配置多個proxy元素,若是聲明瞭多個proxy元素,則默認狀況下第一個被激活的proxy會生效。active爲true表示激活該代理,protocol表示使用的代理協議,固然最重要的是指定正確的主機名(host)和端口(port),若是代理服務器須要認證則配置username和password,nonProxyHost元素表示指定哪些主機名不須要代理,能夠用"|"分隔多個主機名,也支持通配符"*"。

二、repository

repository表示Maven的中央倉庫,由於儘管默認的遠程倉庫中的構件很是龐大,可是總歸會有不知足咱們需求的時候,這時候就要用到別的中央倉庫了。看一下寫法:

<repository>
    <id>public</id>
    <name>local private nexus</name>
    <url>http://192.168.1.6:8081/nexus/content/groups/public</url>
    <releases>
        <enabled>true</enabled>
    </releases>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
</repository>

能夠聲明多個repository。id必須是惟一的,尤爲注意,Maven自帶的中央倉庫使用的id爲central,若是其餘倉庫聲明也用該id,就會覆蓋中央倉庫的配置。releases和snapshots比較重要,前者表示開啓倉庫的發佈版本下載支持,後者表示關閉倉庫的快照版本下載支持,這樣一來,Maven就會去倉庫下載發佈版本的構件而不會下載快照版本的構件了。

三、server

大部分遠程倉庫無須認證就能夠訪問,可是有時候處於安全方面的因素考慮,須要提供認證信息才能訪問一些遠程倉庫,處於安全考慮,認證信息通常只放在settings.xml中,server就是認證元素。看一下配置:

<server>
    <id>nexus-releases</id>
    <username>deployment</username>
    <password>deployment</password>
</server>

這裏的關鍵是id,這個id必須與須要認證的repository元素的id徹底一致才行,換句話說,正式這個id將認證信息和倉庫配置聯繫在了一塊兒。

四、mirror

若是倉庫X能夠提供倉庫Y存儲的全部內容,那麼就能夠認爲倉庫X是倉庫Y的一個鏡像(mirror),換句話說,任何一個能夠從Y中獲取到的構件夠能夠從X中獲取到。舉個例子,"http://maven.net.cn/content/groups/public/"是中央倉庫"http://repo1.maven.org/maven2/"在中國的鏡像,因爲地理位置的因素,該鏡像每每可以提供比中央倉庫更快的服務,這就是爲何要使用mirror的緣由。

看一下mirror的配置:

<mirror>
    <id>nexus</id>
    <name>internal nexus repository</name>
    <url>http://192.168.1.6:8081/nexus/content/groups/public</url>
    <mirrorOf>*</mirrorOf>
</mirror>

該例子中,mirrof爲*,表示該配置爲全部中央倉庫的鏡像,任何對於中央倉庫的請求都會轉至該鏡像。另外三個元素id、name、url與通常倉庫配置無異,表示該鏡像倉庫的惟一標識符、名稱以及地址。相似的,若是該鏡像須要認證,也能夠基於該id配置倉庫認證。

相關文章
相關標籤/搜索