項目的依賴關系主要分為三種:依賴,繼承,聚合
依賴關系
依賴關系是最常用的一種,就是你的項目需要依賴其他項目,比如Apache-common包,Spring包等等。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
<type >jar</ type >
<optional >true</ optional >
</dependency>
任意一個外部依賴說明包含如下幾個要素:groupId
, artifactId
, version
, scope
, type
, optional
。其中前3個是必須的。
這里的version可以用區間表達式來表示,比如(2.0,)表示>2.0,[2.0,3.0)表示2.0<=ver<3.0;多個條件之間用逗號分隔,比如[1,3],[5,7]。
type 一般在pom引用依賴時候出現,其他時候不用。
maven認為,程序對外部的依賴會隨著程序的所處階段和應用場景而變化,所以maven中的依賴關系有作用域(scope)的限制。在maven中,scope包含如下的取值:
Scope選項 | 描述 |
---|---|
compile(編譯范圍) | compile是默認的范圍;如果沒有提供一個范圍,那該依賴的范圍就是編譯范圍。編譯范圍依賴在所有的classpath中可用,同時它們也會被打包。 |
provided(已提供范圍) | provided依賴只有在當JDK或者一個容器已提供該依賴之后才使用。例如,如果你開發了一個web應用,你可能在編譯classpath中需要可用 的Servlet API來編譯一個servlet,但是你不會想要在打包好的WAR中包含這個Servlet API;這個Servlet API JAR由你的應用服務器或者servlet容器提供。已提供范圍的依賴在編譯classpath(不是運行時)可用。它們不是傳遞性的,也不會被打包。 |
runtime(運行時范圍) | runtime依賴在運行和測試系統的時候需要,但在編譯的時候不需要。比如,你可能在編譯的時候只需要JDBC API JAR,而只有在運行的時候才需要JDBC驅動實現 |
test(測試范圍) | test范圍依賴在編譯和運行時都不需要,它們只有在測試編譯和測試運行階段可用。 |
system(系統范圍) | system范圍依賴與provided類似,但是你必須顯式的提供一個對于本地系統中JAR文件的路徑。這么做是為了允許基于本地對象編譯,而這些對象是系統類庫的一部分。這樣的構件應該是一直可用的,Maven也不會在倉庫中去尋找它。 如果你將一個依賴范圍設置成系統范圍,你必須同時提供一個systemPath元素 。注意該范圍是不推薦使用的(應該一直盡量去從公共或定制的Maven倉庫中引用依賴)。 |
dependency
中的type
一般不用配置,默認是jar。當type為pom時,代表引用關系:
此時,本項目會將persistence-deps
的所有jar包導入依賴庫。
可以創建一個打包方式為pom項目來將某些通用的依賴歸在一起,供其他項目直接引用,不要忘了指定依賴類型為pom(<type>pom</type>)。
繼承關系
繼承就是避免重復,maven的繼承也是這樣,它還有一個好處就是讓項目更加安全。項目之間存在上下級關系時就屬于繼承關系。
父項目的配置如下:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.clf.parent</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<packaging>pom</packaging>
<!-- 該節點下的依賴會被子項目自動全部繼承 -->
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
<dependencyManagement>
<!-- 該節點下的依賴關系只是為了統一版本號,不會被子項目自動繼承,-->
<!--除非子項目主動引用,好處是子項目可以不用寫版本號 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 這個元素和dependencyManagement相類似,它是用來進行插件管理的-->
<pluginManagement>
......
</pluginManagement>
</project>
注意,此時<packaging>
必須為pom
。
為了項目的正確運行,必須讓所有的子項目使用依賴項的統一版本,必須確保應用的各個項目的依賴項和版本一致,才能保證測試的和發布是相同的結果。
Maven 使用dependencyManagement 元素來提供了一種管理依賴版本號的方式。通常會在一個組織或者項目的最頂層的父POM 中看到dependencyManagement 元素。使用pom.xml 中的dependencyManagement 元素能讓所有在子項目中引用一個依賴而不用顯式的列出版本號。Maven 會沿著父子層次向上走,直到找到一個擁有dependencyManagement元素的項目,然后它就會使用在這個dependencyManagement 元素中指定的版本號。
父項目在dependencies聲明的依賴,子項目會從全部自動地繼承。而父項目在dependencyManagement里只是聲明依賴,并不實現引入,因此子項目需要顯示的聲明需要用的依賴。如果不在子項目中聲明依賴,是不會從父項目中繼承下來的;只有在子項目中寫了該依賴項,并且沒有指定具體版本,才會從父項目中繼承該項,并且version和scope都讀取自父pom另外如果子項目中指定了版本號,那么會使用子項目中指定的jar版本。
如果某個項目需要繼承該父項目,基礎配置應該這樣:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.clf.parent.son</groupId>
<artifactId>my-son</artifactId>
<version>1.0</version>
<!-- 聲明將父項目的坐標 -->
<parent>
<groupId>org.clf.parent</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<!-- 父項目的pom.xml文件的相對路徑。相對路徑允許你選擇一個不同的路徑。 -->
<!-- 默認值是../pom.xml。Maven首先在構建當前項目的地方尋找父項目的pom, -->
<!-- 其次在文件系統的這個位置(relativePath位置), -->
<!-- 然后在本地倉庫,最后在遠程倉庫尋找父項目的pom。 -->
<relativePath>../parent-project/pom.xml</relativePath>
</parent>
<!-- 聲明父項目dependencyManagement的依賴,不用寫版本號 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
</dependencies>
</project>
聚合關系
隨著技術的飛速發展和各類用戶對軟件的要求越來越高,軟件本身也變得越來越復雜,然后軟件設計人員開始采用各種方式進行開發,于是就有了我們的分層架構、分模塊開發,來提高代碼的清晰和重用。針對于這一特性,maven也給予了相應的配置。
maven的多模塊管理也是非常強大的。一般來說,maven要求同一個工程的所有模塊都放置到同一個目錄下,每一個子目錄代表一個模塊,比如
總項目/
? |--- pom.xml 總項目的pom配置文件
? |--- 子模塊1/
?? |--- pom.xml 子模塊1的pom文件
? |--- 子模塊2/
?? |--- pom.xml子模塊2的pom文件
總項目的配置如下:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.clf.parent</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<!-- 打包類型必須為pom -->
<packaging>pom</packaging>
<!-- 聲明了該項目的直接子模塊 -->
<modules>
<!-- 這里配置的不是artifactId,而是這個模塊的目錄名稱-->
<module>module-1</module>
<module>module-2</module>
<module>module-3</module>
</modules>
<!-- 聚合也屬于父子關系,總項目中的dependencies與dependencyManagement、pluginManagement用法與繼承關系類似 -->
<dependencies>
......
</dependencies>
<dependencyManagement>
......
</dependencyManagement>
<pluginManagement>
......
</pluginManagement>
</project>
子模塊的配置如下:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.clf.parent.son</groupId>
<artifactId>my-son</artifactId>
<version>1.0</version>
<!-- 聲明將父項目的坐標 -->
<parent>
<groupId>org.clf.parent</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
</parent>
</project>
繼承與聚合的關系
首先,繼承與聚合都屬于父子關系,并且,聚合 POM與繼承關系中的父POM的packaging都是pom。
不同的是,對于聚合模塊來說,它知道有哪些被聚合的模塊,但那些被聚合的模塊不知道這個聚合模塊的存在。對于繼承關系的父 POM來說,它不知道有哪些子模塊繼承與它,但那些子模塊都必須知道自己的父 POM是什么。
在實際項目中,一個 POM往往既是聚合POM,又是父 POM,它繼承了某個項目,本身包含幾個子模塊,同時肯定會存在普通的依賴關系,就是說,依賴、繼承、聚合這三種關系是并存的。
Maven可繼承的POM 元素列表如下:
groupId :項目組 ID ,項目坐標的核心元素;
version :項目版本,項目坐標的核心元素;
description :項目的描述信息;
organization :項目的組織信息;
inceptionYear :項目的創始年份;
url :項目的 url 地址
develoers :項目的開發者信息;
contributors :項目的貢獻者信息;
distributionManagerment:項目的部署信息;
issueManagement :缺陷跟蹤系統信息;
ciManagement :項目的持續繼承信息;
scm :項目的版本控制信息;
mailingListserv :項目的郵件列表信息;
properties :自定義的 Maven 屬性;
dependencies :項目的依賴配置;
dependencyManagement:醒目的依賴管理配置;
repositories :項目的倉庫配置;
build :包括項目的源碼目錄配置、輸出目錄配置、插件配置、插件管理配置等;
reporting :包括項目的報告輸出目錄配置、報告插件配置等。