1 . 坐標
maven 的所有構件均通過坐標進行組織和管理。maven 的坐標通過 5 個元素進行定義,其中 groupId、artifactId、version 是必須的,packaging 是可選的(默認為jar),classifier 是不能直接定義的。
- groupId:定義當前 Maven 項目所屬的實際項目,跟 Java 包名類似,通常與域名反向一一對應。
- artifactId:定義當前 Maven 項目的一個模塊,默認情況下,Maven 生成的構件,其文件名會以 artifactId 開頭,如 hibernate-core-3.6.5.Final.jar。
- version:定義項目版本。
- packaging:定義項目打包方式,如 jar,war,pom,zip ……,默認為 jar。
- classifier:定義項目的附屬構件,如 hibernate-core-3.6.6.Final-sources.jar,hibernate-core-3.6.6.Final-javadoc.jar,其中 sources 和 javadoc 就是這兩個附屬構件的 classifier。classifier 不能直接定義,通常由附加的插件幫助生成。
2 . 依賴
使用 Maven 可以方便的管理依賴,如下是一段在 pom.xml 文件中聲明依賴的代碼示例:
1 <dependencies> 2 <dependency> 3 <groupId>org.springframework</groupId> 4 <artifactId>spring-test</artifactId> 5 <version>3.2.0.RELEASE</version> 6 <type>jar</type> 7 <scope>test</scope> 8 <systemPath>${java.home}/lib/rt.jar</systemPath> 9 <optional>false</optional> 10 <exclusions> 11 <exclusion></exclusion> 12 </exclusions> 13 </dependency> 14 </dependencies>
- type:依賴類型,對應構件中定義的 packaging,可不聲明,默認為 jar;
- scope:依賴范圍;
- optional:依賴是否可選;
- exclusions:排除傳遞依賴。
2 . 1 . 依賴范圍
執行不同的 Maven 命令(mvn package,mvn test,mvn install ……),會使用不同的 classpath,Maven 對應的有三套 classpath:編譯classpath、測試classpath,運行classpath。scope 選項的值,決定了該依賴構件會被引入到哪一個 classpath 中。
- compile:編譯依賴范圍,默認值。此選項對編譯、測試、運行三種 classpath 都有效,如 hibernate-core-3.6.5.Final.jar,表明在編譯、測試、運行的時候都需要該依賴;
- test:測試依賴范圍。只對測試有效,表明只在測試的時候需要,在編譯和運行時將無法使用該類依賴,如 junit;
- provided:已提供依賴范圍。編譯和測試有效,運行無效。如 servlet-api ,在項目運行時,tomcat 等容器已經提供,無需 Maven 重復引入;
- runtime:運行時依賴范圍。測試和運行有效,編譯無效。如 jdbc 驅動實現,編譯時只需接口,測試或運行時才需要具體的 jdbc 驅動實現;
- system:系統依賴范圍。和 provided 依賴范圍一致,需要通過 <systemPath> 顯示指定,且可以引用環境變量;
- import:導入依賴范圍。使用該選項,通常需要 <type>pom</type>,將目標 pom 的 dependencyManagement 配置導入合並到當前 pom 的 dependencyManagement 元素。
2 . 2 . 依賴傳遞
如上圖所示,hibernate-core 依賴 hibernate-commons-annotations ,而 hibernate-commons-annotations 又依賴 slf4j-api ,hibernate-core 對 slf4j-api 的依賴就是傳遞依賴。我們只需要引入 hibernate-core 構件的依賴,不用考慮它還有其它的依賴, 也不用擔心會引入多余或沖突的依賴,Maven 會自動為我們引入依賴及傳遞依賴。
2 . 3 . 依賴傳遞和依賴范圍
如上圖 2.2 所示,幾種依賴關系分別叫做第一直接依賴、第二直接依賴和傳遞性依賴,其中第一直接依賴和第二直接依賴的依賴范圍,決定了傳遞性依賴的依賴范圍。
2 . 4 . 依賴沖突
通常我們不需要關心傳遞性依賴,當多個傳遞性依賴中有對同一構件不同版本的依賴時,如何解決呢?
- 短路徑優先:假如有以下依賴:A -> B -> C ->X(版本 1.0) 和 A -> D -> X(版本 2.0),則優先解析較短路徑的 X(版本 2.0);
- 先聲明優先:若路徑長度相同,則誰先聲明,誰被解析。
2 . 5 . 依賴排除
針對依賴沖突中的“短路徑優先”,如果我們想使用長路徑的依賴怎么辦呢?這時可以使用依賴排除 <exclusions> 元素,顯示排除短路徑依賴。在非沖突的情況下,這種方法同樣有效。
2 . 6 . 依賴歸類
通常在項目中,我們會同時依賴同一個構件的不同模塊,如 spring-orm-3.2.0,spring-context-3.2.0,且多個模塊版本相同,為了維護和升級方便,我們可以對其同一管理,這時可以使用到 Maven 屬性,類似於變量的概念。
1 <properties> 2 <springframework.version>3.2.0.RELEASE</springframework.version> 3 </properties> 4 5 <dependencies> 6 <dependency> 7 <groupId>org.springframework</groupId> 8 <artifactId>spring-orm</artifactId> 9 <version>${springframework.version}</version> 10 </dependency> 11 <dependency> 12 <groupId>org.springframework</groupId> 13 <artifactId>spring-context</artifactId> 14 <version>${springframework.version}</version> 15 </dependency> 16 </dependencies>