《Maven實戰》閱讀總結(二)Maven倉庫

(五)Maven倉庫

Maven倉庫

在Maven世界中,任何一個依賴、插件或者項目構建的輸出,均可以成爲構件(jar、war包等)。
Maven在某個位置上統一存儲全部Maven項目共享的構件,即爲Maven倉庫
Maven項目不用各自存儲依賴文件,只需聲明依賴的座標,在須要時(編譯、運行、打包),Maven會自動根據座標找到Maven倉庫中的構件,並使用它們。java

倉庫的佈局

在Maven世界中,任何一個構件都有其惟一的座標,經過座標能夠定義其在倉庫中的惟一存儲路徑,即Maven的倉庫佈局方式。
Maven構件的存儲路徑爲:groupId/artifactId/version/artifactId-version[-classifier].packaging
Ps(我的理解): 倉庫的佈局方式就是定義了座標與構件路徑的對應關係,即如何經過座標找到構件。apache

倉庫的分類

對Maven而言,倉庫只分爲兩類,本地倉庫、遠程倉庫。而遠程倉庫又可細分爲中央倉庫、私服、其餘公共庫。
當Maven根據座標尋找構件時,首先查看本地倉庫,若是不存在,Maven就會去遠程倉庫查找並下載到本地文件。若是都沒有,Maven就會報錯。分類以下圖
clipboard.png緩存

1 本地倉庫

一般Maven項目目錄下,沒有諸如lib/這樣存放依賴文件的目錄,Maven老是基於座標使用本地倉庫的依賴文件。
默認狀況下,不管是Windows仍是Linux,本地倉庫的路徑都爲~/.m2/repository(~ 是用戶目錄)
更改本地倉庫路徑:~/.m2/settings.xml,設置localRepository元素的值。
如:安全

<settings>
    ...
    <localRepository>D:\java\repository</localRepository>
    ...
</settings>

安裝構件到本地倉庫:
1)mvn clean install:構建項目輸出文件並安裝到本地倉庫
2)mvn install:install-file -Dfile=x -DgroupId=x -DartifactId=x -Dversion=x -Dpackaging=x
Dfile待安裝構建路徑;DgroupId、DartifactId、Dversion、Dpackaging聲明其在倉庫中的座標服務器

2 遠程倉庫

安裝好Maven後,若是不執行任何Maven命令,本地倉庫目錄是不存在的。當用戶輸入第一條Maven命令以後,Maven纔會建立本地倉庫,而後根據配置和須要,從遠程倉庫下載構件至本地倉庫。
Maven本地倉庫只有一個,但能夠配置多個遠程倉庫
比如本地倉庫是書房,遠程倉庫是書店,當用戶須要看一本書時,若是在書房中沒找到,就到書店購買並放回書房。一般一我的只有一個書房,但外面的書店有不少。maven

3 中央倉庫

因爲原始的本地倉庫是空,Maven必須知道至少一個可用的遠程倉庫,才能在執行Maven命令時下載到須要的構件。
中央倉庫就是這樣一個默認遠程倉庫。在Maven安裝文件中自帶了中央倉庫的配置。
在Maven安裝目錄/lib/maven-model-builder-xx.jar中訪問路徑org/apache/maven/model/pom-4.0.0.xml。
Ps(我的理解):pom-4.0.0.xml 與 pom.xml中<modelVersion>4.0.0</modelVersion> 應該存在某些關聯
pom-4.0.0.xml是全部Maven項目都會繼承的超級POM,查看該文件,能夠找到中央倉庫配置。工具

<repositories>
    <repository>
        <id>central</id>
        <name>Central Repository</name>
        <url>https://repo.maven.apache.org/maven2</url>
        <layout>default</layout>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

4 私服

私服是一種特殊的遠程倉庫,它是架設在局域網內的倉庫服務。私服代理廣域網上的遠程倉庫,供局域網內的Maven用戶使用。
clipboard.png佈局

上圖展現了組織內部使用私服的狀況,即便在一臺直接連入Internet的我的機器上使用Maven,也應本地創建私服。
創建私服的優勢:ui

節省本身的外網帶寬 消除對外的重複構件下載,下降外網帶寬的壓力。
加速Maven構建 不停的請求外部倉庫十分耗時,Maven的一些內部機制(如快照更新檢查)要求Maven在執行構建時不停地檢查遠程倉庫數據,當項目配置不少外部遠程倉庫時,構建速度大大下降。使用私服,Maven只需檢查局域網內私服數據,提升構建速度。
部署第三方構建 安裝組織內部生成的私有構件到私服,供內部Maven用戶
提升穩定性,加強控制 Maven構建高度依賴於遠程倉庫,Internet不穩定,Maven構建也會變得不穩定,甚至失敗,使用私服後,即便暫時沒有Internet,因爲私服緩存了不少構件,Maven也能正常運行。此外,不少私服(如Nexus)軟件還提供了額外的功能,如權限管理,RELEASE/SNAPSHOT區分等
下降中央倉庫的負荷 使用私服能夠避免不少對中央倉庫的重複下載。

遠程倉庫的配置

在POM中配置遠程倉庫url

<repositories>
    <repository>
        <id>...</id>    <!-- 倉庫惟一標識,重複會覆蓋上一個遠程倉庫 -->
        <name>...</name>    <!-- 倉庫名稱 -->
        <url>...</url>    <!-- 倉庫地址 -->
        <releases>    <!-- 重要!控制Maven對於發佈版本構件的下載 -->
            <enabled>...</enabled>    <!-- true/false 控制發佈版本構件的下載 -->
            <updatePolicy>...</updatePolicy>    <!-- 更新策略 daily(默認,天天一次)、never(從不)、always(每次構建)、interval:X(間隔X分鐘) -->
            <checksumPolicy>...</checksumPolicy>    <!-- 檢查檢驗和文件的策略 warn(默認,校驗失敗,輸出警告信息)、fail(校驗失敗,沒法完成構建)、ignore(忽略校驗失敗) -->
        </releases>
        <snapshots>    <!-- 重要!控制Maven對於快照版本構件的下載 -->
            <enabled>...</enabled>    <!-- true/false 控制快照版本構件的下載 -->
            <updatePolicy>...</updatePolicy>    <!-- 更新策略 daily(默認,天天一次)、never(從不)、always(每次構建)、interval:X(間隔X分鐘) -->
            <checksumPolicy>...</checksumPolicy>    <!-- 檢查檢驗和文件的策略 warn(默認,校驗失敗,輸出警告信息)、fail(校驗失敗,沒法完成構建)、ignore(忽略校驗失敗) -->
        </snapshots>
        <layout>default</layout>    <!-- 倉庫佈局方式 -->
    </repository>
    ...
</repositories>

1 遠程倉庫的認證

大部分遠程倉庫無須認證就可訪問,但有時出於安全方面考慮,咱們須要提供認證信息才能訪問一些遠程倉庫。
配置認證信息必須配置在settings.xml中,由於POM每每提交到代碼倉庫中供全部成員訪問,顯然,本地settings.xml更安全

<settings>
    ...
    <servers>
        <server>
            <id>..</id>    <!-- 須要提供認證信息才能訪問的遠程倉庫ID -->
            <username>...</username>    <!-- 用戶名 -->
            <password>...</password>    <!-- 密碼 -->
        </server>
    </servers>
    ...
</settings>

2 部署至遠程倉庫

1) 編輯項目的pom.xml

<project>
    <distributionManagement>
        <repository>    <!-- 指定發佈版本構件的倉庫 -->
            <id>...</id>
            <name>...</name>
            <url>...</url>
        </repository>
        <snapshotRepository>    <!-- 指定快照版本構件的倉庫 -->
             <id>...</id>
            <name>...</name>
            <url>...</url>
        </snapshotRepository>
    </distyibutionManagement>
</project>

2) 往遠程倉庫部署構件時,每每須要認證。在settings.xml中配置認證信息
3)執行mvn clean deploy,部署到遠程倉庫

快照版本

在Maven世界中。任何一個項目或者構件都必須有本身的版本,而Maven又將版本分爲兩種:
發佈版本:穩定,格式如:1.0.0、1.3-alpha-四、2.0
快照版本:不穩定,格式如:2.1-SNAPSHOT、2.1-20091214.221414-13

假設:同時開發項目A、B,而項目B依賴於項目A,在項目未正式方布時,開發方案以下
方案一:檢出項目A源碼進行構建。能得到項目A最新構件,但須要額外的構建操做,並且構建出問題也很差解決,低效
方案二:重複部署項目A,版本號不變。須要清理本地倉庫相同版本號的項目A構件,否則沒法下載A最新構件
方案三:不停更新版本。須要頻繁修改POM文件,同時形成版本號的濫用。
方案四:將項目A的版本設置爲快照版本。

Maven在發佈項目快照版本時,會自動打上時間戳。如2.1-20091214.221414-13 表示 2009年12月14日22時14分14秒 第13次快照。經過時間戳,Maven就能找到該構件的最新快照版本。
默認狀況下,Maven會天天檢查一次更新(由倉庫配置的updatePolicy控制),也可經過-U命令強制更新,如mvn clean install -U

從倉庫解析依賴的機制

當本地倉庫沒有依賴構件時,Maven會自動從遠程倉庫下載;當依賴版本爲快照版本時,Maven會自動找到最新的快照。其依賴解析機制以下
1)依賴範圍是system,Maven直接從本地文件系統解析構件。
2)根據依賴座標計算倉庫路徑,Maven直接從本地倉庫尋找構件,若是發現相應構件,則解析成功。
3)本地倉庫不存在,且依賴版本是顯式的發佈版本構件(1.0,1.2-beta-1),遍歷全部遠程倉庫,發現後下載並解析使用
4)若是依賴版本是RELEASE和LATEST,則基於更新策略讀取全部遠程倉庫的元數據groupId/artifactId/maven-metadata.xml,將其與本地倉庫的對應元數據合併後,計算出RELEASE或LATEST的真實的值,而後基於這個值檢查本地和遠程倉庫。
5)若是依賴版本是SNAPSHOT,則基於更新策略讀取全部遠程倉庫的元數據groupId/artifactId/version/maven-metadata.xml,將其與本地倉庫的對應元數據合併後,獲得最新快照版本的值,而後基於該值檢查本地倉庫和遠程倉庫。
6)若是最後解析獲得的構件版本是時間戳格式的快照,如1.4.1-20091104.121450-121,則複製其時間戳格式文件至非時間戳格式,如SNAPSHOT,並使用該非時間戳格式的構件。

Maven基於更新策略來檢查更新,與遠程倉庫配置中<release>和<snapshot>中的子元素<enable>、<updatePolicy>有關,只有enable爲true,才能訪問該倉庫對應發佈版本/快照版本的構件信息,並基於updatePolicy更新策略檢查更新,使用-U能夠強制更新。
當Maven檢查完更新策略,並決定檢查依賴版本,就須要檢查倉庫元數據maven-metadata.xml
基於groupId和artifactId的maven-metadata.xml

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>org.sonatype.nexus</groupId>
  <artifactId>nexus</artifactId>
  <versioning>
    <latest>1.4.2-SNAPSHOT</latest>    <!-- 指向最新版本 -->
    <release>1.4.0</release>    <!-- 指向最新發布版本 -->
    <versions>    <!-- 版本歷史記錄 -->
      <version>1.3.5</version>
      <version>1.3.6</version>
      <version>1.4.0-SNAPSHOT</version>
      <version>1.4.0.1-SNAPSHOT</version>
      <version>1.4.1-SNAPSHOT</version>
      <version>1.4.2-SNAPSHOT</version>
    </versions>
    <lastUpdated>20091214221557</lastUpdated>    <!-- 記錄最近更新時間 -->
  </versioning>
</metadata>

該XML文件列出倉庫中存在的該構件的全部可用的版本,Maven經過合併多個遠程倉庫及本地倉庫的元數據,就能計算出基於全部倉庫的latest和release分別是什麼,而後再解析具體的構件。
Ps:不推薦依賴聲明中使用LATEST和RELEASE,Maven隨機解析到不一樣的構件,當構件發生變化,可能會形成項目構建失敗,且不易排查。

當依賴版本是快照版本時,Maven也須要檢查更新。
基於groupId、artifactId和version的maven-metadata.xml

<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
  <groupId>org.sonatype.nexus</groupId>
  <artifactId>nexus</artifactId>
  <version>1.4.2-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <timestamp>20091214.221414</timestamp>
      <buildNumber>13</buildNumber>
    </snapshot>
    <lastUpdated>20091214221414</lastUpdated>
  </versioning>
</metadata>

該XML文件的snapshot元素包含timestamp和buildNumber兩個元素分別表明這一快照的時間戳和構建號。並由此能夠獲得該倉庫中此快照的最新構件版本實際爲1.4.2-20091214.221414-13,經過合併全部遠程倉庫和本地倉庫的元數據,就能知道全部倉庫中該構件的最新快照。

最後,元數據並不是永遠正確,當某些構件沒法解析,或解析錯誤時,需手工或使用工具(如Nexus)對齊進行修復。

鏡像

若是倉庫X能夠提供倉庫Y存儲的全部內容,那麼就能夠認定X是Y的一個鏡像。
舉個例子,http://maven.net.cn/content/g...://repol.maven.org/maven2在中國的鏡像,因爲地理位置因素,使用該鏡像每每可以提供比中央倉庫更快的服務。

編輯settings.xml,配置鏡像

<settings>
    ...
    <mirrors>
        <mirror>
            <id>...</id>    <!-- 鏡像倉庫id -->
            <name>...</name>    <!-- 鏡像倉庫名稱 -->
            <url>...</url>    <!-- 鏡像倉庫地址 -->
            <mirrorOf>...</mirrorOf>    <!-- 被鏡像倉庫表達式: *(匹配全部遠程倉庫) -->
        </mirror>
    </mirrors>
    ...
</settings>

mirrorOf元素用來匹配被鏡像倉庫(有點相似於Servlet的url-pattern表達式),當你要訪問的遠程倉庫id知足mirrorOf表示式時,就會被攔截訪問鏡像服務器。表達式語法以下:

* 匹配全部遠程倉庫
external:* 匹配全部遠程倉庫,localhost除外
a,b 匹配a和b倉庫,多個倉庫用,隔開
*,!a 匹配全部遠程倉庫,a除外,使用感嘆號將倉庫從匹配中排除

倉庫搜索服務

使用Maven進行平常開發時,獲取依賴須要確切的依賴座標,經過倉庫搜索服務能夠根據關鍵字獲得Maven座標。

Sonatype Nexus http://repository.sonatype.org 提供關鍵字搜索、類名搜索、座標搜索、校驗和搜索等功能,座標和構件下載
aliyun Nexus http://maven.aliyun.com 同上,aliyun架設的公共Nexus倉庫實例,服務較快
Jarvana http://www.jarvana.com/jarvana 提供基於關鍵字、類型搜索,座標,構件下載。還支持瀏覽構件內部內容和便捷的Java文檔瀏覽功能
MVNbrowser http://www.mvnbrowser.com 只提供關鍵字搜索,座標,還可查看構件依賴於那些構件(Dependencies)以及該構件被哪些其餘構件依賴(Referenced By)
MVNrepository http://mvnrepository.com 提供關鍵字搜索,座標,構件下載,依賴於被依賴關係信息,構件所含信息,還能提供一個簡單圖表,顯示某個構件各版本間的大小變化
相關文章
相關標籤/搜索