專案的依賴關係主要分為三種:依賴,繼承,聚合
依賴關係
依賴關係是最常用的一種,就是你的專案需要依賴其他專案,比如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(pom)。
繼承關係
繼承就是避免重複,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 元素列表如下:
groupI:專案組 ID ,專案座標的核心元素;
version :專案版本,專案座標的核心元素;
description :專案的描述資訊;
organization :專案的組織資訊;
inceptionYear :專案的創始年份;
url :專案的 url 地址
develoers :專案的開發者資訊;
contributors :專案的貢獻者資訊;
distributionManagerment:專案的部署資訊;
issueManagement :缺陷跟蹤系統資訊;
ciManagement :專案的持續繼承資訊;
scm :專案的版本控制資訊;
mailingListserv :專案的郵件列表資訊;
properties :自定義的 Maven 屬性;
dependencies :專案的依賴配置;
dependencyManagement :醒目的依賴管理配置;
repositories :專案的倉庫配置;
build :包括專案的原始碼目錄配置、輸出目錄配置、外掛配置、外掛管理配置等;
reporting :包括專案的報告輸出目錄配置、報告外掛配置等。