讀古今文學網 > Maven實戰 > 6.2 倉庫的佈局 >

6.2 倉庫的佈局

任何一個構件都有其唯一的坐標,根據這個坐標可以定義其在倉庫中的唯一存儲路徑,這便是Maven的倉庫佈局方式。例如,log4j:log4j:1.2.15這一依賴,其對應的倉庫路徑為log4j/log4j/1.2.15/log4j-1.2.15.jar,細心的讀者可以觀察到,該路徑與坐標的大致對應關係為groupId/artifactId/version/artifactId-version.packaging。下面看一段Maven的源碼,並結合具體的實例來理解Maven倉庫的佈局方式,見代碼清單6-1:

代碼清單6-1 Maven處理倉庫佈局的源碼

該pathOf()方法的目的是根據構件信息生成其在倉庫中的路徑。在閱讀本段代碼之前,可以先回顧一下第5章的相關內容。這裡根據一個實際的例子來分析路徑的生成,考慮這樣一個構件:groupId=org.testng、artifactId=testng、version=5.8、classifier=jdk15、packaging=jar,其對應的路徑按如下步驟生成:

1)基於構件的groupId準備路徑,formatAsDirectory()將groupId中的句點分隔符轉換成路徑分隔符。該例中,groupId org.testng就會被轉換成org/testng,之後再加一個路徑分隔符斜槓,那麼,org.testng就成為了org/testng/。

2)基於構件的artifactId準備路徑,也就是在前面的基礎上加上artifactId以及一個路徑分隔符。該例中的artifactId為testng,那麼,在這一步過後,路徑就成為了org/testng/testng/。

3)使用版本信息。在前面的基礎上加上version和路徑分隔符。該例中版本是5.8,那麼路徑就成為了org/testng/tesgng/5.8/。

4)依次加上artifactId,構件分隔符連字號,以及version,於是構建的路徑就變成了org/testng/testng/5.8/testng-5.8。讀者可能會注意到,這裡使用了artifactId.getVersion(),而上一步用的是artifactId.getBaseVersion(),baseVersion主要是為SNAPSHOT版本服務的,例如version為1.0-SNAPSHOT的構件,其baseVersion就是1.0。

5)如果構件有classifier,就加上構件分隔符和classifier。該例中構件的classifier是jdk15,那麼路徑就變成org/testng/testng/5.8/testng-5.8-jdk5。

6)檢查構件的extension,若extension存在,則加上句點分隔符和extension。從代碼中可以看到,extension是從artifactHandler而非artifact獲取,artifactHandler是由項目的packaging決定的。因此,可以說,packaging決定了構件的擴展名,該例的packaging是jar,因此最終的路徑為org/testng/testng/5.8/testng-5.8-jdk5.jar。

到這裡,應該感謝Maven開源社區,正是由於Maven的所有源代碼都是開放的,我們才能仔細地深入到其內部工作的所有細節。

Maven倉庫是基於簡單文件系統存儲的,我們也理解了其存儲方式,因此,當遇到一些與倉庫相關的問題時,可以很方便地查找相關文件,方便定位問題。例如,當Maven無法獲得項目聲明的依賴時,可以查看該依賴對應的文件在倉庫中是否存在,如果不存在,查看是否有其他版本可用,等等。