1. 程式人生 > 其它 >maven系列(五)倉庫(有todo)

maven系列(五)倉庫(有todo)

倉庫

什麼是maven倉庫

任何一個構件都有一組座標唯一標識。

得益於座標機制,任何Maven專案使用任何一個構件的方式是完全相同的。在此基礎上,maven可以在某個位置統一儲存所有maven專案共享的構件,這個統一的位置就是倉庫。

實際的maven專案只需要宣告這些依賴的座標,在需要的時候,maven會自動根據座標找到倉庫中的構件,並使用他們。

倉庫的佈局

佈局就是maven的超級POM中的<layout>這段,預設佈局(default)如下:

根據座標可以定義其在倉庫中的唯一儲存路徑。該路徑與座標的大致關係為groupId/artifactId/version/artifactId-version.packaging

maven倉庫是基於簡單檔案系統儲存的,因此,當遇到了一些與倉庫相關的問題時,可以很方便地查詢相關檔案,方便定位問題。

倉庫的分類

倉庫只分為兩類:本地倉庫和遠端倉庫。當maven根據座標尋找構件的時候,它首先會檢視本地倉庫,如果本地倉庫存在此構件,則直接使用;如果本地倉庫不存在此構件,或者需要檢視是否有更新的構件版本,maven就會去遠端倉庫查詢,發現需要的構件之後,下載到本地倉庫在使用。如果本地和遠端都沒有,就會報錯。

maven倉庫的分類如下圖:

graph TD; Maven倉庫-->本地倉庫 Maven倉庫-->遠端倉庫 遠端倉庫-->中央倉庫 遠端倉庫-->私服 遠端倉庫-->其他公共庫

本地倉庫

本地倉庫在~/.m2/repository/。如果想要自定義本地倉庫目錄地址,可以編輯檔案~/.m2/settings.xml,設定localRepository元素的值為想要的倉庫地址。(這個配置xml預設不存在,需要從M2_HOME中複製過去一個)

另外,maven的install外掛也是將專案構建輸出檔案安裝到本地倉庫。

遠端倉庫

對於maven來說,每個使用者只有一個本地倉庫,但可以配置訪問很多遠端倉庫。

中央倉庫

由於最原始的本地倉庫是空的,maven必須知道至少一個可用的遠端倉庫,才能子啊執行maven命令的時候下載到需要的構件。中央倉庫就是這樣一個預設的遠端倉庫,maven的安裝自帶了中央倉庫的配置。在$M2_HOME/lib/maven-model-builder-3.6.1jar

中的pom-4.0.0.xml檔案下看到:

  <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>

這段配置檔案是所有maven專案都會繼承的超級POM。

私服

私服代理廣域網上的遠端倉庫,供區域網內的maven使用者使用。

當maven需要下載構件的時候,它從私服請求,如果私服上不存在該構件,則從外部的遠端倉庫下載,快取在私服上之後,再為maven的下載請求提供服務。此外,一些無法從外部倉庫下載到的構件也能從本地上傳到私服上供大家使用

私服的優點:

  1. 節省自己的外網頻寬。
  2. 加速Maven構建
  3. 部署第三方構件。(二方庫)
  4. 提高穩定性,增強控制。
  5. 降低中央倉庫的負荷。

常見的私服軟體包括: JFrog Artifactory和 Nexus

https://www.jfrog.com/confluence/display/JFROG/JFrog+Artifactory

遠端倉庫的配置

  • 遠端倉庫的配置:可以通過<repositoriese>標籤直接在pom中配置。

  • 遠端倉庫的認證

    配置認證資訊和配置倉庫資訊不同,倉庫資訊可以直接配置在pom檔案中,但是認證資訊必須配置在settings.xml檔案中。

    可以通過私鑰配置,也可以同賬號密碼配置。

    <!-- servers
     | This is a list of authentication profiles, keyed by the server-id used within the system.
     | Authentication profiles can be used whenever maven must make a connection to a remote server.
     |-->
    <servers>
        <!-- server
         | Specifies the authentication information to use when connecting to a particular server, identified by
         | a unique name within the system (referred to by the 'id' attribute below).
         |
         | NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
         |       used together.
         |
        <server>
          <id>deploymentRepo</id>
          <username>repouser</username>
          <password>repopwd</password>
        </server>
        -->
    
        <!-- Another sample, using keys to authenticate.
        <server>
          <id>siteServer</id>
          <privateKey>/path/to/private/key</privateKey>
          <passphrase>optional; leave empty if not used.</passphrase>
        </server>
        -->
    </servers>
    
  • 部署至遠端倉庫

    Maven除了能對專案進行編譯、測試、打包之外,還可以將專案生成的構建部署到倉庫中。首先,需要編輯專案的pom.xml檔案。配置distributionManagement元素。

        <distributionManagement>
            <repository>
                <name>xxx </name>
                <id>xxx-release</id>
                <url>private serve release url</url>
            </repository>
            <snapshotRepository>
                <name>xxx </name>
                <id>xxx-snapshot</id>
                <url>private serve snapshot url</url>
            </snapshotRepository>
        </distributionManagement>
    

    往遠端倉庫部署構建的時候,需要認證。配置認證的在上面講了,即在settings.xml中建立一個server元素,其id與倉庫的匹配,並配置正確的認證資訊。

    配置正確後,在命令列執行mvn clean deploy,就會專案構建輸出的構件部署到配置的對應的遠端倉庫,如果當前的版本是快照版本,則部署到快車版本倉庫地址,否則就是release地址。

快照版本

  • 是什麼?

    • snapshot:2.1-SNAPSHOT、2.1-20091215.221414-14、
    • release:1.0.0、1.3-alpha-4、2.0
  • Maven為什麼要區分release和snapshot?

    • maven的快照版本是為了解決合作開發時候,模板B依賴模組A部分新功能情況下,需要對模組A的新功能進行臨時打包 。

    • 如果對模組A的版本設定為2.1-SNAPSHOT,然後釋出到私服中,在釋出過程中,Maven會自動為構建打上時間戳。比如2.1-20091215.221414-14表示2009年12月15日22點14分14秒的第14次快照。有了該時間戳,maven就能夠隨時找到倉庫中該構件版本的最新檔案。

    • 當構建模組B的時候,Maven會自動從倉庫中檢查模組A的最新構建,當發現有更新時便進行下載。預設Maven是每天檢查一次更新(由倉庫的updatePolicy控制),也可以使用

      mvn clean install -U
      

      強制Maven檢查更新。

    • 當專案經過完善的測試後需要釋出的時候,就應該將快照版本更改為釋出版本。例如,講2.1-SNAPSHOT更改為2.1,表示該版本已經穩定,且只對應了唯一構件。相比之下,2.1-SNAPSHOT往往對應了大量的帶有不同時間戳的構件,這也決定了其不穩定性。

從倉庫解析依賴的機制

當本地倉庫沒有依賴構件的時候,Maven會自動從遠端倉庫下載;當依賴版本為快照版本的時候,maven會自動找到最新的快照。則背後的依賴解析機制可以概括如下:

  1. 當依賴的範圍是system的時候,maven直接從本地檔案系統解析構件
  2. 根據依賴座標計算倉庫路徑後,嘗試直接從本地倉庫尋找構件,如果發現相應構件,則解析成功。
  3. 在本地倉庫不存在相應構件的情況下,如果依賴的版本是顯式的釋出版本構件,如1.2、2.1-beta-1,則遍歷所有的遠端倉庫,發現後,下載並解析使用。
  4. 如果依賴的版本是RELEASE或者LATEST,則基於更新策略讀取所有遠端倉庫的元資料groupId/artifactId/maven-metadata.xml,將其與本地倉庫的對應元資料合併後,計算出RELEASE或者LASTEST真實的值,然後基於這個真實的值檢查本地和遠端庫。
  5. 如果依賴的版本是SNAPSHOT,則基於更新策略讀取所有遠端倉庫的元資料groupId/artifactId/maven-metadata.xml,將其與本地倉庫的對應元資料合併後,得到最新快照版本的值,然後基於該值檢查本地倉庫,或者從遠端倉庫下載。
  6. 如果最後解得到的構件版本是時間戳格式的快照,則複製其時間戳格式的檔案至非時間戳格式,如SNAPSHOT,並使用該非時間戳格式的構件。

【需要看原始碼】

前面提到的RELEASE和LATEST版本,它們分別對應了倉庫中存在的該構件的最新發布版本和最新版本(包含快照),而這兩個“最新”是基於groupId/artifactId/maven-metadata.xml計算出來的。

【這個xml可以在maven倉庫看到】

最後,倉庫元資料並不是永遠正確的,有時候當用戶無法解析某些構件,或者解析得到錯誤構件的時候,就有可能是出現了倉庫元資料錯誤,這時候就需要手工地,或者使用工具對其進行修復。

映象

如果倉庫X可以提供倉庫Y儲存的所有內容,那麼就可以認為X是Y的一個映象。

關於映象,一個更常見的用法是結合私服。由於私服可以代理任何外部的公共倉庫,因此,對於內部的maven使用者來說,使用一個私服地址就等於使用了所有需要的外部映象,這可以將配置集中到私服,從而簡化Maven本身的配置。

具體的一個映象配置如下:

<mirrors>
    <mirror>
        <id>aliyunmaven</id>
        <mirrorOf>*</mirrorOf>
        <name>阿里雲公共倉庫</name>
        <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
</mirrors>

該例中<mirrorOf>值為星號,表示該配置是所有Maven倉庫的映象,任何對於遠端倉庫的請求都會被轉至阿里雲。如果該映象倉庫需要認證,則配置一個id為internal-repository<server>即可。

為了滿足一些複雜的需求,maven還支援更高階的映象配置:

  1. <mirrorOf>*</mirrorOf>:匹配所有的遠端倉庫
  2. <mirrorOf>external:*</mirrorOf>:匹配所有遠端倉庫,使用localhost的除外,使用file://協議的除外。
  3. <mirrorOf>repo1,repo2</mirrorOf>:匹配倉庫repo1和repo2,使用逗號分隔多個遠端倉庫。
  4. <mirrorOf>*,! repo1</mirrorOf>:匹配所有遠端倉庫,repo1除外,使用感嘆號將倉庫從匹配中排除。

倉庫搜尋服務

上述四個倉庫搜尋服務都代理了主流的Maven公共倉庫,比如central,JBoss,Java.net等。區別只有頁面風格和額外功能。

補充

JFrog Artifactory 和Nenus

todo