maven的核心功能是依賴管理和自動化構(gòu)建,我們這節(jié)講解maven的依賴管理。
1.坐標(biāo)
maven是根據(jù)坐標(biāo)來定位依賴,一般常用的是三個坐標(biāo):
groupId:一般用公司或者組織官網(wǎng)域名倒序+項目名,例如com.baidu.oa
artifactId:模塊名
version:版本號
我們使用artifactId+groupId+version坐標(biāo)來定位引用某一個依賴;如下圖,我們使用dependency標(biāo)簽引用一個spring-webmvc的jar包。引用jar包可通過maven+jar包名搜索,去maven中央倉庫尋找。
<groupId>com.baidu.erp</groupId>
<artifactId>erp-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<denpendencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.8.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
此時maven會去配置的倉庫地址下載依賴。
2.依賴范圍 (依賴的使用范圍)
上圖中scope標(biāo)簽是來確定jar包的依賴范圍,scope有如下依賴范圍:
compile:默認(rèn)是compile,編譯、測試、運行都有效
test:僅僅測試有效 例如junit ,打包時減少體積
provided:編譯和測試時有效,運行時無效
runtime:測試和運行時有效,編譯時無效
system:系統(tǒng)依賴范圍,使用system范圍的依賴時必須通過systemPath元素顯示地指定依賴文件的路徑,不依賴Maven倉庫解析,所以可能會造成建構(gòu)的不可移植,謹(jǐn)慎使用。
3.依賴傳遞
maven的依賴可以通過引用來傳遞,例如project A依賴project B,那么project就可以使用project B項目的所有包,也就是project B引用的依賴都傳遞給project A,并沒有層級顯示,可以project C、D、E,多層次引用都可以傳遞給project A
4.依賴調(diào)解
如下圖項目依賴關(guān)系
A-->B--D(spring 3.2.8)
A-->C(spring1.2.8)
根據(jù)maven的依賴傳遞項目D會把spring3.2.8版本傳遞給項目A,項目C也會把spring1.2.8版本傳遞給A
此時項目A maven會自動選擇哪個版本呢?
maven根據(jù)就近原則選擇,層級路徑一樣長的時候會選擇pom.xml首先聲明的引用
此時會選擇項目C的1.2.8版本
<groupId>com.baidu.erp</groupId>
<artifactId>A</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<denpendencies>
<dependency>
<groupId>com.baidu.erp</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.baidu.erp</groupId>
<artifactId>C</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<groupId>com.baidu.erp</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<denpendencies>
<dependency>
<groupId>com.baidu.erp</groupId>
<artifactId>D</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<groupId>com.baidu.erp</groupId>
<artifactId>D</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<denpendencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<artifactId></artifactId>
<version>3.2.8</version>
<scope>compile</scope>
</dependency>
</dependencies>
<groupId>com.baidu.erp</groupId>
<artifactId>C</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<denpendencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<artifactId></artifactId>
<version>1.2.8</version>
<scope>compile</scope>
</dependency>
</dependencies>
5.可選依賴
項目B的依賴包,不想必須傳遞給項目A,那么可以在項目B的依賴包下加上<optional>true</optional>,意思是可選的,項目A可以不用
<groupId>com.baidu.erp</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<denpendencies>
<dependency>
<groupId>com.baidu.erp</groupId>
<artifactId>D</artifactId>
<version>0.0.1-SNAPSHOT</version>
<optional>true</optional>
</dependency>
</dependencies>
這樣項目A依賴項目B的時候,可以不依賴項目D的jar包
6.依賴沖突 排除依賴
例如上面依賴選項對方?jīng)]有添加可選依賴optional或者多層依賴導(dǎo)致依賴沖突的時候,各種class not found錯誤,此時是maven根據(jù)依賴原則自動調(diào)解選擇了錯誤的版本,此時需要我們手動選擇較高版本,比如我們排除項目B的版本,不選擇這個低版本
<groupId>com.baidu.erp</groupId>
<artifactId>A</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<denpendencies>
<dependency>
<groupId>com.baidu.erp</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
引用項目B,但是排除項目B的spring-core版本。
當(dāng)項目復(fù)雜,我們可以查看依賴樹來分析
執(zhí)行mvn dependency:tree 可以查看到詳細的依賴樹來分析
7.依賴管理
maven有三種依賴關(guān)系:依賴(上面已講解)、聚合、繼承
1.聚合
當(dāng)我們有大量模塊,手動一個個構(gòu)建就會特別不方便,此時我們可以把多個模塊聚合在一起,這樣就只需構(gòu)建一次。下面我們用父工程聚合A,B,C模塊
<groupId>com.baidu.erp</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 父工程的packaging必須為pom -->
<packaging>pom</packaging>
<modules>
<module>A</module>
<module>B</module>
<module>C</module>
</modules>
這是對于父工程聚合子工程,我們還需把各個子工程移動到父工程目錄下!
如果對于同級別工程<module>../A</module>那么就要用相對路徑
2.繼承
工作中,我們經(jīng)常把一個項目拆分成多個模塊,多個模塊需要的jar包又有大量重復(fù),這時我們需要一個父工程引用這些公共包,然后各模塊繼承這個父工程。
如圖父工程
<groupId>com.baidu.erp</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 父工程的packaging必須為pom -->
<packaging>pom</packaging>
<dependencies>
<!-- spring依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
</dependencies>
如下圖子工程A繼承父工程,包含父工程依賴的jar具體版本號都會繼承過來
<groupId>com.baidu.erp</groupId>
<artifactId>A</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>com.zhss.parent</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
當(dāng)父工程不強制子工程繼承依賴,可以選擇性使用的時候,父工程可以如下圖配置
<groupId>com.baidu.erp</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 父工程的packaging必須為pom -->
<packaging>pom</packaging>
<dependencyManagement>
<!-- 子項目可選擇引用,不會自動繼承,引用后可以不用寫版本號,這里已經(jīng)強制版本號-->
<dependencies>
<!-- spring依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
3.使用scope import 解決單繼承問題
上面這種繼承是單繼承,和java一樣,但是工作中我們不但需要父類工程,還需要引入公共基礎(chǔ)組件,并需要使用公共基礎(chǔ)組件里提供的依賴版本號。此時maven提供了一種import的方式,此方式可以通過非繼承的方式來引入公共依賴配置
<groupId>com.baidu.erp</groupId>
<!-- 我們通常會把這個工程定義為bom工程 -->
<artifactId>A-bom</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- packaging必須為pom -->
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<!-- spring依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
可以使使用如下方式引用
<groupId>com.baidu.erp</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.baidu.erp</groupId>
<artifactId>A-bom</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<!-- 此時的scope import必須在dependencyManagement內(nèi) -->
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!-- 此時和繼承父工程一樣,不需要版本號,已經(jīng)被強制約束了版本號 -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
</dependencies>
4.使用properties統(tǒng)一約定版本號
<groupId>com.baidu.erp</groupId>
<artifactId>A-bom</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 使用properties定義版本號 -->
<properties>
<spring.version>3.2.8.RELEASE</spring.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- spring依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>