URL:
http://juvenshun.javaeye.com/blog/547787
任何一個構件都有其惟一的座標,根據這個座標能夠定義其在倉庫中的惟一存儲路徑,這即是Maven的倉庫佈局方式。例如log4j:log4j:1.2.15這一依賴,其對應的倉庫路徑爲log4j/log4j/1.2.15/log4j-1.2.15.jar,細心的讀者能夠觀察到,該路徑與座標的大體對應關係爲groupId/artifactId/version/artifactId-version.packaging。下面看一段Maven的源碼並結合具體的實例來理解Maven倉庫的佈局方式:
- private static final char PATH_SEPARATOR = '/';
-
- private static final char GROUP_SEPARATOR = '.';
-
- private static final char ARTIFACT_SEPARATOR = '-';
-
- public String pathOf( Artifact artifact )
- {
- ArtifactHandler artifactHandler = artifact.getArtifactHandler();
-
- StringBuilder path = new StringBuilder( 128 );
-
- path.append( formatAsDirectory( artifact.getGroupId() ) ).append( PATH_SEPARATOR );
- path.append( artifact.getArtifactId() ).append( PATH_SEPARATOR );
- path.append( artifact.getBaseVersion() ).append( PATH_SEPARATOR );
- path.append( artifact.getArtifactId() ).append( ARTIFACT_SEPARATOR ).append( artifact.getVersion() );
-
- if ( artifact.hasClassifier() )
- {
- path.append( ARTIFACT_SEPARATOR ).append( artifact.getClassifier() );
- }
-
- if ( artifactHandler.getExtension() != null && artifactHandler.getExtension().length() > 0 )
- {
- path.append( GROUP_SEPARATOR ).append( artifactHandler.getExtension() );
- }
-
- return path.toString();
- }
-
- private String formatAsDirectory( String directory )
- {
- return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );
- }
該pathOf()方法的目的是根據構件信息生成其在倉庫中的路徑。在閱讀本段代碼以前,讀者能夠先回顧一下上一章Maven座標的相關內容。這裏,咱們根據一個實際的例子來分析路徑的生成,考慮這樣一個構件:groupId=org.testng、artifactId=testng、version=5.八、classifier=jdk1五、packaging=jar,其對應的路徑按以下步驟生成:
- 首先基於構件的groupId準備路徑,formatAsDirectory()將groupId中的句點分隔符轉換成路徑分隔符,該例中,groupId org.testng就會被轉換成org/testng,以後再加一個路徑分隔符斜槓,那麼org.testng就成爲了org/testng/。
- 基於構件的artifactId準備路徑,也就是在前面的基礎上加上artifactId以及一個路徑分隔符,該例中的artifactId爲testng,那麼在這一步事後路徑就成爲了org/testng/testng/。
- 接着使用版本信息,在前面的基礎上加上version和路徑分隔符,該例中版本是5.8,那麼路徑就成爲了org/testng/tesgng/5.8/。
- 這一步再依次加上artifactId,構件分隔符連字號,以及version,因而構建的路徑就變成了org/testng/testng/5.8/testng-5.8。讀者可能會注意到這裏使用了artifactId.getVersion(),而上一步用的是artifactId.getBaseVersion(),version和baseVersion的區別在本章討論SNAPSHOT的時候會具體闡述。
- 緊接着若是構件有classifier,就加上構件分隔符和classifier,該例中構件的classifier是jdk15,那麼路徑就變成org/testng/testng/5.8/testng-5.8-jdk5。
- 最後第檢查構件的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沒法得到項目聲明的依賴時,能夠簡單該依賴對應的文件在倉庫中是否存在,若是不存在,是否有其它版本可用,等等。