(轉)Maven使用總結
阿新 • • 發佈:2021-09-17
Maven使用總結
依賴範圍
-
maven建立的工程的目錄中包含
main
和test
資料夾,分別表示主程式的資料夾和測試程式的資料夾 -
maven使用
scop
設定依賴範圍,常用的依賴範圍如下:-
compile :編譯依賴範圍,在測試和執行都有效,這個是預設的依賴範圍
- 對主程式是否有效:有效
- 對測試程式是否 有效: 有效
- 是否參與打包:參與``
- 是否參與部署:參與
-
test:測試依賴的範圍
- 對主程式是否有效:無效
- 對測試程式是否 有效: 有效
- 是否參與打包:不參與
- 典型的例子:
junit
-
provided
- 對主程式是否有效: 有效
- 對測試程式是否有效:有效
- 是否參與打包:不參與
- 是否參與部署:不參與
- 典型的例子:
servlet-api
- 主要解決在開發中需要用到的,但是在部署的時候不需要的依賴,比如
servlet-api
,在開發中沒有Tomcat執行環境,因此需要這個servlet-api
,但是一旦部署在Tomcat中,Tomcat中會提供這個servlet-api
,如果此時在新增的話會產生依賴衝突
- 主要解決在開發中需要用到的,但是在部署的時候不需要的依賴,比如
-
Runtime
:測試和執行時需要。編譯不需要。如JDBC驅動包- 對測試程式是否有效:有效
- 對主程式是否有效:有效
- 是否參與部署: 參與
- 是否參與打包:參與
-
system
:系統依賴範圍。本地依賴,不在maven中央倉庫- 這個必須和
systemPath
<!-- 新增服務提供者的jar介面 --> <dependency> <groupId>cn.tedu.dubbo</groupId> <artifactId>dubbo-provider</artifactId> <version>0.0.1</version> <scope>system</scope> <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/dubbo-provider-helloService-0.0.1.jar</systemPath> </dependency>
- 這個必須和
-
依賴傳遞
- 在開發專案的時候,我們通常需要建立多個專案,如果一個專案中需要用到另外一個專案的類或者資料,那麼需要引入這個專案快照
- 如果
HelloFriend
專案依賴Hello
這個專案,此時的HelloFriend
的pom.xml
檔案如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.tedu</groupId>
<artifactId>HelloFriend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- 新增Hello這個專案的依賴快照 -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
- 此時專案
HelloFriend
中存在依賴只有Hello
專案這個jar
,但是如果我們在Hello
專案的pom.xml
檔案中新增一個junit
的依賴,這個依賴範圍為設定為compile
,如下:
<dependencies>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
- 做了上面的操作,我們可以檢視專案
HelloFriend
和Hello
中都自動的匯入了Junit
依賴,這個就是依賴傳遞。
注意
- 依賴傳遞只有是依賴範圍為
compile
的情況下才有作用,如果我們需要一個servlet-api
的依賴,因為servlet-api
這個jar在部署的時候會和Tomcat衝突,因此只能設定為provided
,但是此時就不能依賴傳遞了,只能在每個專案中的pom.xml
檔案中都添加了
依賴排除
HelloFriend
專案依賴Hello
專案,其中compile
範圍的依賴都會匯入HelloFriend
中- 使用
dubbo
預設會新增給我們新增spring-framework
的版本為2.5.6
,預設新增的依賴只能排除,不能在專案中再新增一個其他的版本,只有排除之後才能新增,否則會導致jar包衝突 Hello
專案中的依賴為:
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<!-- 新增dubbo依賴的jar,會自動新增spring 2.5版本的依賴 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
-
此時
HelloFriend
的專案需要使用4.3.13
版本的spring,那麼我們有如下解決辦法:- 在
Hello
專案中改變依賴,排除spring2.5版本的:- 一般在公司中專案的版本都是定製好的,我們不可能隨意改動父專案中定義好的版本,因此這個方法明顯是不行的
<!-- 使用spring4.3.13 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.13.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <!--排除spring2.5版本--> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency>
- 在
- 我們可以在專案
HelloFriend
排除這個spring的依賴,那麼我們就可以不需要改變Hello
專案中的依賴了,如下:- 這個才是正確的排除依賴的方式
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<!-- 新增Hello這個專案的依賴快照 -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--排除專案中的spring2.5的依賴,這個不會影響Hello專案中的版本-->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
依賴原則
依賴路徑最短優先原則
- 假設專案
MakeFriend
依賴HelloFriend
,並且HelloFriend
依賴Hello
專案。此時Hello專案中
使用的log4j 1.2.14
版本的,但是在HelloFriend
版本中使用的是log4j1.2.17
版本的,那麼此時的MakeFriend
應該選擇什麼版本呢? - image
Hello
的依賴如下:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
HelloFriend
依賴如下:
<!-- 新增Hello這個專案的依賴快照 -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--新增1.2.17版本的log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
MakeFriend
的依賴如下:
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>HelloFriend</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
- 我們根據圖形可以看到
MakeFriend
到HelloFriend
的log4j1.2.17
的路徑是2
,但是到Hello
中的log4j1.2.14
的路徑為3
,因此Maven會選擇HelloFriend
中的log4j1.2.17
版本作為MakeFriend的依賴
pom檔案中申明順序優先
-
在
路徑
都是一樣的情況下,那麼就要看在pom.xml
檔案中申明的順序了,先申明的就使用哪個專案中的依賴版本 -
假設現在的依賴改變了,
MakeFriend
現在是直接依賴Hello
和HelloFriend
,如下圖 - image
-
我們可以看出此時到兩個版本的依賴都是一樣的路徑為
2
,那麼我們應該選擇哪個版本呢,此時就需要看看在MakeFriend
中的pom.xml
檔案的申明順序- 可以看出先申明的是
HelloFriend
,因此MakeFriend
使用的是log4j1.2.17
- 可以看出先申明的是
<!-- 先申明HelloFriend,那麼就要使用log4j.1.2.17版本 -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>HelloFriend</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
覆寫優先
生命週期
- maven的生命週期有三個部分組成,分別為
clean生命週期
,site生命週期
,default生命週期
生命週期呼叫的特點
- 三大生命週期中也會包含各個階段,並且各個階段是有序進行的,maven為了實現構建的自動化,如果我們使用了命令呼叫生命週期後面的處理階段,那麼會從最前面的階段開始執行,不用每一個階段都執行一遍。
clean生命週期
-
在進行真正的構建之前進行一些清理工作
-
clean生命週期包括:
per-clean
:執行了一些需要在clean之前完成的工作clean
:移除所有上一次構建生成的檔案post-clean
:執行一些需要在clean之後立刻完成的工作
-
當我們執行
mvn:clean
命令的時候只會執行per-clean
和clean
這兩個階段的任務,不會執行post-clean
的工作
default生命週期
- 構建的核心部分,編譯、測試、打包、部署
- 包括如下的23個生命週期階段:
生命週期階段 | 描述 |
---|---|
validate | 檢查工程配置是否正確,完成構建過程的所有必要資訊是否能夠獲取到。 |
initialize | 初始化構建狀態,例如設定屬性。 |
generate-sources | 生成編譯階段需要包含的任何原始碼檔案。 |
process-sources | 處理原始碼,例如,過濾任何值(filter any value)。 |
generate-resources | 生成工程包中需要包含的資原始檔。 |
process-resources | 拷貝和處理資原始檔到目的目錄中,為打包階段做準備。 |
compile | 編譯工程原始碼。 |
process-classes | 處理編譯生成的檔案,例如 Java Class 位元組碼的加強和優化。 |
generate-test-sources | 生成編譯階段需要包含的任何測試原始碼。 |
process-test-sources | 處理測試原始碼,例如,過濾任何值(filter any values)。 |
test-compile | 編譯測試原始碼到測試目的目錄。 |
process-test-classes | 處理測試程式碼檔案編譯後生成的檔案。 |
test | 使用適當的單元測試框架(例如JUnit)執行測試。 |
prepare-package | 在真正打包之前,為準備打包執行任何必要的操作。 |
package | 獲取編譯後的程式碼,並按照可釋出的格式進行打包,例如 JAR、WAR 或者 EAR 檔案。 |
pre-integration-test | 在整合測試執行之前,執行所需的操作。例如,設定所需的環境變數。 |
integration-test | 處理和部署必須的工程包到整合測試能夠執行的環境中。 |
post-integration-test | 在整合測試被執行後執行必要的操作。例如,清理環境。 |
verify | 執行檢查操作來驗證工程包是有效的,並滿足質量要求。 |
install | 安裝工程包到本地倉庫中,該倉庫可以作為本地其他工程的依賴。 |
deploy | 拷貝最終的工程包到遠端倉庫中,以共享給其他開發人員和工程。 |
- 當一個階段通過 Maven 命令呼叫時,例如
mvn compile
,只有該階段之前以及包括該階段在內的所有階段會被執行。 - [圖片上傳失敗...(image-7b5809-1538922827484)]
Site生命週期
- Maven Site 外掛一般用來建立新的報告文件、部署站點等。
- 包含以下階段
pre-site
:執行一些需要在生成站點文件之前完成的工作site
:生成專案的站點文件post-site
:執行一些需要生成站點文件之後完成的工作site-deploy
:將生成站點文件部署到特定的伺服器上
Maven統一管理依賴的版本號
- 假設如下的依賴:
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<!-- Spring-JDBC,要和spring-webmvc的版本一致 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
- 那麼當我們需要改變spring的依賴版本號為
4.3.12.RELEASE
,那麼我們只有逐個改變version
中的值,現在是兩個依賴比較好改變的,如果要有很多個的話,那麼難免會改錯,因此我們需要使用一種方式統一管理依賴的版本號。我們可以使用<properties>
標籤來管理,新的配置檔案如下:properties
中的標籤體可以任意指定,如果需要引用定義的標籤體中的內容,那麼直接使用${標籤體}
即可- 此時我們要是改變版本,那麼只需要改變
<properties>
中的版本即可
<!-- 使用properties管理版本號 -->
<properties>
<!-- 這裡的標籤體可以任意指定,後續只要使用${}引用標籤體即可使用其中定義的內容 -->
<spring-version>4.3.13.RELEASE</spring-version>
</properties>
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<!-- version使用${} -->
<version>${spring-version}</version>
</dependency>
<!-- Spring-JDBC,要和spring-webmvc的版本一致 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
繼承
- 我們知道只有
compile
範圍內的依賴才可以傳遞,但是對於test
和provided
中的依賴卻是不可以傳遞的,那麼必須在每個專案中都要新增依賴,此時肯定會出現每個專案中依賴版本不一致的情況,這樣對於每個人的開發來說是比較困難的,因為不同版本的依賴使用的方式也不同,此時我們就需要統一管理這個版本了。 - 下面我們以
junit
的版本控制為例
步驟
- 建立一個父工程
Hello-Parent
,打包的方式為pom
- 在
Hello-Parent
中的pom.xml
檔案中使用dependencyManagement
管理版本,控制junit
的版本依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.tedu</groupId>
<artifactId>Hello-Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 使用properties控制版本號 -->
<properties>
<junit-version>4.12</junit-version>
</properties>
<!-- 使用dependencyManagement管理版本 -->
<dependencyManagement>
<dependencies>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
- 在子工程中使用
parent
標籤指定宣告對父工程的引用
<parent>
<groupId>cn.tedu</groupId>
<artifactId>Hello-Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 使用relativePath指定父工程的相對位置 -->
<relativePath>../Hello-Parent</relativePath>
</parent>
- 將子工程座標和父工程座標重複的地方刪除,不刪除也沒關係
- 在子工程中刪除
junit
的version
標籤,表明是繼承自父工程的版本,不需要指定
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!--此時不需要指定version了,因為父工程中已經指定了-->
</dependency>
- 子工程全部的配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 這裡的groupId和父工程中的重複了,因此可以刪除
<groupId>cn.tedu</groupId>-->
<artifactId>Hello</artifactId>
<!-- 這裡的version版本也和父工程的重複了,因此可以刪除
<version>0.0.1-SNAPSHOT</version> -->
<parent>
<groupId>cn.tedu</groupId>
<artifactId>Hello-Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 使用relativePath指定父工程的相對位置 -->
<relativePath>../Hello-Parent</relativePath>
</parent>
<dependencies>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!--不需要指定version-->
</dependency>
</dependencies>
</project>
聚合
- 我們在開發專案的時候都是分模組開發的,此時如果想要使用maven安裝這個專案的話,那麼需要一個一個的安裝,但是我們可以使用聚合的方式,可以實現一次性安裝。並且安裝還是有先後順序的,一定要先安裝父工程,否則將會找不到依賴資訊,我們使用聚合的方式就沒有先後安裝的障礙了,maven會為我們自動的解決
步驟
- 建立一個maven工程,打包方式為
pom
,當然也是可以直接使用父工程 - 在pom.xml配置檔案中配置
module
- 詳細的pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.tedu</groupId>
<artifactId>Hello-Manager</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 繼承父工程 -->
<parent>
<groupId>cn.tedu</groupId>
<artifactId>Hello-Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 使用relativePath指定父工程的相對位置 -->
<relativePath>../Hello-Parent</relativePath>
</parent>
<!-- 使用聚合的方式 -->
<modules>
<module>../Hello-Parent</module>
<module>../Hello</module>
<module>../HelloFriend</module>
<module>../MakeFriend</module>
</modules>
</project>
原文:https://www.jianshu.com/p/b7d08690d242
Keep moving forwards~