# Maven簡介
Maven的本質是一個專案管理工具,將專案開發和管理過程抽象成一個專案物件模型(POM))
這玩意兒是使用Java開發的,所以採用的就是Java的思想:物件導向
POM (Project Object Model):專案物件模型
Maven的作用:
- 專案構建:提供標準的、跨平臺的自動化專案構建方式
- 依賴管理:方便快捷的管理專案依賴的資源(jar包),避免資源間的版本衝突問題
- 統一開發結構:提供標準的、統一的專案結構
下載與安裝:
- 官網:http://maven.apache.org/
- 下載:http://maven.apache.org/download.cgi
# Maven基礎概念
倉庫:用於儲存資源,包含各種jar包
倉庫分類:本地倉庫和遠端倉庫(私服和中央倉庫)
座標:Maven中的座標用於描述倉庫中資源的位置
座標的主要組成:
- groupId:定義當前Maven專案隸屬組織名稱(通常是域名反寫)
- artifactId:定義當前Maven專案名稱(通常是模組名稱)
- version:定義當前版本號
- packaging:定義該專案的打包方式
座標的作用:使用唯一的標識,唯一性定位資源位置,透過該標識可以將資源的識別與下載交由機器完成。
倉庫配置:
- 本地倉庫配置:預設位置與自定義位置
- 遠端倉庫配置:
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
映象倉庫配置:阿里雲Maven映象倉庫釋出與配置地址
<mirrors>
<mirror>
<!-- 此映象的唯一識別符號,用來區分不同的mirror元素 -->
<id>nexus-aliyun</id>
<!-- 對那種倉庫進行映象(就是替代哪種倉庫)-->
<mirrorOf>central</mirrorOf>
<!-- 映象名稱 -->
<name>Nexus aliyun</name>
<!-- 映象URL -->
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
全域性setting和使用者setting
- 定義當前計算機中Maven的公共配置,即 mavne安裝目錄/conf/setting.xml
- 定義當前使用者配置,即 配置的本地倉庫地址處有個平級的setting.xml
注:使用者setting和全域性setting不一致時,會優先採用使用者setting.xml的配置,因此最好是這二者內容保持一致
# Maven專案
# 手動生成Maven專案
Maven工程目錄結構
Maven專案構建命令:Maven構建命令使用mvn開頭,後面加功能引數,可以一次執行多個命令,使用空格分隔
mvn compile # 編譯
mvn clean # 清理
mvn test # 測試
mvn package # 打包
mvn install # 安裝到本地倉庫
# IDEA生成Maven專案
使用原型建立Maven專案與不使用原型建立Maven專案
例:使用原型建立web專案,選擇archetype-webapp進行專案建立,新增Tomcat外掛
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
# 依賴管理
-
依賴配置:依賴指的是當前專案執行所需要的jar,一個專案可以設定多個依賴。格式:
<!--設定當前專案所依賴的所有jar--> <dependencies> <!--設定具體的依賴--> <dependency> <!--依賴所屬群組id--> <groupId></groupId> <!--依賴所屬專案id--> <artifactId></artifactId> <!--依賴版本號--> <version></version> <!-- <type>pom</type> <scope>import</scope> 只能用在 <dependencyManagement></dependencyManagement> 中 --> <!--型別:jar 則匯入jar包 pom 匯入的是一個父模組--> <type></type> <!-- 作用域:import 代表把父模組中的jar包匯入進來 為import時,dependency不參與依賴傳遞 只是把dependency需要的依賴都取過來,像個佔位符一樣替換了就行 --> <scope>import</scope> </dependency> </dependencies>
-
依賴傳遞
依賴具有傳遞性,包括直接傳遞和間接傳遞
直接傳遞:在當前專案中透過依賴配置建立的依賴關係(A使用B,A和B就是直接傳遞)
間接傳遞:被依賴的資源如果依賴其他資源,當前專案間接依賴其他資源(比較拗口,意思是如果A依賴B,而B依賴C,那麼
A和C之間就是間接傳遞)
依賴傳遞的衝突問題:
- 路徑優先:當依賴中出現相同的資源時,層級越深,優先順序越低,層級越淺,優先順序越高
- 宣告優先:當資源在相同層級被依賴時,配置順序靠前的覆蓋配置順序靠後的
- 特殊優先:當同級配置了相同資源的不同版本,後配置的覆蓋先配置的
- 可選依賴
可選依賴指的是對外隱藏當前所依賴的資源
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!--新增下面這一行-->
<optional>true</optional>
</dependency>
- 排除依賴
排除依賴指主動斷開依賴的資源,被排除的資源無需指定版本
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<exclusions>
<exclusion>
<groupId></groupId>
<artifactId></artifactId>
</exclusion>
</exclusions>
</dependency>
- 依賴範圍
依賴的jar包預設情況可以在任何地方使用,可以透過scope標籤設定其作用範圍
作用範圍:
- 主程式範圍有效(main資料夾範圍內)
- 測試程式範圍有效(test資料夾範圍內)
- 是否參與打包(package資料夾範圍內)
還有兩個:system、import
- import:依賴項替換為指定 POM 的
<dependencyManagement>
中的該依賴項。僅<dependencyManagement>
部分中 pom 型別的依賴項支援此範圍
- 依賴範圍傳遞性:帶有依賴範圍的資源在傳遞時,作用範圍會受到影響
# 生命週期與外掛
Maven專案構建生命週期描述的是一次構建過程經歷了多少個事件
Maven對專案構建的生命週期劃分為3套
- clean:清理工作
- default:核心工作,例如編譯、測試、打包、部署等
- site:產生報告,釋出站點等
clean生命週期:
- pre-clean:執行一些需要在clean之前完成的工作
- clean:移除所有上一次構建生成的檔案
- post-clean:執行一些需要在clean之後立刻完成的工作
default構建生命週期:compile ——> test-compile ——> test ——> package ——> install
-
validate(校驗) 校驗專案是否正確並且所有必要的資訊可以完成專案的構建過程
-
initialize(初始化) 初始化構建狀態,比如設定屬性值
-
generate-sources(生成原始碼) 生成包含在編譯階段中的任何原始碼
-
process-sources(處理原始碼) 處理原始碼,比如說,過濾任意值
-
generate-resources(生成資原始檔) 生成將會包含在專案包中的資原始檔
-
process-resources (處理資原始檔) 複製和處理資源到目標目錄,為打包階段最好準備
-
compile(編譯) 編譯專案的原始碼
-
process-classes(處理類檔案) 處理編譯生成的檔案,比如說對Java class檔案做位元組碼改善最佳化
-
generate-test-sources(生成測試原始碼) 生成包含在編譯階段中的任何測試原始碼
-
process-test-sources(處理測試原始碼) 處理測試原始碼,比如說,過濾任意值
-
generate-test-resources(生成測試資原始檔) 為測試建立資原始檔
-
process-test-resources(處理測試資原始檔) 複製和處理測試資源到目標目錄
-
test-compile(編譯測試原始碼) 編譯測試原始碼到測試目標目錄
-
process-test-classes(處理測試類檔案) 處理測試原始碼編譯生成的檔案
-
test(測試) 使用合適的單元測試框架執行測試(Juint是其中之一)
-
prepare-package(準備打包) 在實際打包之前,執行任何的必要的操作為打包做準備
-
package(打包) 將編譯後的程式碼打包成可分發格式的檔案,比如JAR、WAR或者EAR檔案
-
pre-integration-test(整合測試前) 在執行整合測試前進行必要的動作。比如說,搭建需要的環境
-
integration-test(整合測試) 處理和部署專案到可以執行整合測試環境中
-
post-integration-test(整合測試後) 在執行整合測試完成後進行必要的動作。比如說,清理整合測試環境
-
verify (驗證) 執行任意的檢查來驗證專案包有效且達到質量標準
-
install(安裝) 安裝專案包到本地倉庫,這樣專案包可以用作其他本地專案的依賴
-
deploy(部署) 將最終的專案包複製到遠端倉庫中與其他開發者和專案共享
site生命週期:
-
pre-site 執行一些需要在生成站點文件之前完成的工作
-
site 生成專案的站點文件
-
post-site 執行一些需要在生成站點文件之後完成的工作,並且為部署做準備
-
site-deploy 將生成的站點文件部署到特定的伺服器上
外掛:外掛與生命週期內的階段繫結,在執行到對應的生命週期時執行對應的外掛功能
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<!--執行外掛-->
<executions>
<!--具體怎麼執行-->
<execution>
<!--目標:執行什麼-->
<goals>
<!--執行jar-->
<goal>jar</goal>
</goals>
<!--執行到那個生命週期階段時就要執行該外掛 對應前面default中的那些值-->
<phase>generate-test-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
<goal>jar</goal>
值選項:官網:Apache Maven Source Plugin
- source:aggregate aggregrates sources for all modules in an aggregator project.
- source:jar is used to bundle the main sources of the project into a jar archive——對main中原始碼打包
- source:test-jar on the other hand, is used to bundle the test sources of the project into a jar archive——對測試程式碼打包
- source:jar-no-fork is similar to jar but does not fork the build lifecycle.
- source:test-jar-no-fork is similar to test-jar but does not fork the build lifecycle.
# 聚合
作用:聚合用於快速構建Maven工程,一次性構建多個專案/模組
製作方式:建立一個空模組,打包型別定義為pom
<packaging>pom</packaging>
定義當前模組進行構建操作時關聯的其他模組名稱
<modules>
<module>模組地址</module>
<module>模組地址</module>
<module>模組地址</module>
<module>模組地址</module>
</modules>
注意:參與聚合操作的模組最終執行順序與模組間的依賴關係有關,與配置順序無關
# 繼承
作用:透過繼承可以實現在子工程中沿用父工程中的配置(與Java類似)
製作方式:在子工程中生命其父工程座標與對應的位置
<!--定義該工程的父工程-->
<parent>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!--填寫父工程的pom檔案-->
<relativePath>父工程pom檔案地址</relativePath>
</parent>
在父工程中定義依賴管理
<!--宣告此處進行依賴管理-->
<dependencyManagement>
<!--具體的依賴-->
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
</dependency>
</dependencies>
</dependencyManagement>
<!--要管理外掛的話,使用如下方式-->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!--.....................-->
</plugin>
</plugins>
</pluginManagement>
</build>
繼承依賴使用:在子工程中定義依賴關係,無需宣告依賴版本,版本參照父工程中依賴的版本
<!--子工程使用依賴-->
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
</dependency>
</dependencies>
<!--子工程使用外掛-->
<build>
<plugins>
<plugin>
<groupId></groupId>
<artifactId></artifactId>
<!--<version></version>-->
</plugin>
</plugins>
</build>
繼承的資源:
# 繼承與聚合的區別
作用:聚合用於快速構建專案,繼承用於快速配置
相同點:
-
聚合與繼承的pom.xml檔案打包方式均為pom,可以將兩種關係製作到同一個pom檔案中
-
聚合與繼承均屬於設計型模組,並無實際的模組內容
不同點:
-
聚合是在當前模組中配置關係,聚合可以感知到參與聚合的模組有哪些
-
繼承是在子模組中配置關係,父模組無法感知哪些子模組繼承了自己
# 屬性
- 自定義屬性
作用:等同於定義變數,方便統一維護
定義格式:
<!--定義自定義屬性-->
<properties>
<spring.version>5.1.9.RELEASE</spring.version>
<junit.version>4.12</junit.version>
</properties>
呼叫格式:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
- 內建屬性
作用:使用Maven內建屬性,快速配置
呼叫格式:
${basedir}
${version}
- Setting屬性
作用:使用Maven配置檔案setting.xml中的標籤屬性,用於動態配置
呼叫格式:
${settings.localRepository}
- Java系統屬性
作用:讀取Java系統屬性
呼叫格式:
${user.home}
系統屬性查詢方式:
mvn help:system
- 環境變數屬性
作用:使用Maven配置檔案setting.xml中的標籤屬性,用於動態配置
呼叫格式:
${env.JAVA_HOME}
環境變數屬性查詢方式:
mvn help:system
# 版本管理
SNAPSHOT(快照版本):
- 專案開發過程中,方便團隊成員合作,解決模組間相互依賴和實時更新的問題,開發者對每個模組進行構建的時候,輸出的臨時性版本就叫快照版本(測試階段版本)
- 快照版本會隨著開發的進展不斷更新
RELEASE(釋出版本):
- 專案開發到進入階段里程碑後,向團隊外部發布較為穩定的版本,這種版本所對應的構建檔案是穩定的,即便進行功能的後續開發,也不會改變當前釋出版本的內容,這種版本就叫釋出版本
工程版本號約定:
# 資源配置
配置檔案引用pom屬性
作用:在任意配置檔案中載入pom檔案中定義的屬性
- pom中定義變數:
<properties>
<jdbc.username>root</jdbc.username>
<jdbc.password>zixieqing072413</jdbc.password>
</properties>
- pom中開啟配置檔案載入pom屬性
<build>
<!--配置資原始檔對應的資訊-->
<resources>
<resource>
<!--設定配置檔案對應的位置目錄 如 application.yml
支援使用屬性動態設定路徑 如 ${project.basedir}-->
<directory>地址</directory>
<!--開啟對配置檔案的資源載入過濾-->
<filtering>true</filtering>
</resource>
</resources>
<!--test配置檔案也需要使用時:配置資原始檔對應的資訊-->
<testResources>
<testResource>
<!--設定配置檔案對應的位置目錄 如 application.yml
支援使用屬性動態設定路徑 如 ${project.basedir}-->
<directory>地址</directory>
<!--開啟對配置檔案的資源載入過濾-->
<filtering>true</filtering>
</testResource>
</testResources>
</build>
- 在需要使用變數得到配置檔案中使用,呼叫格式:
${地址}
<!--示例-->
${jdbc.username}
# 多環境開發配置
<!--建立多環境-->
<profiles>
<!--定義具體的環境:生產環境-->
<profile>
<!--定義環境對應的唯一名稱 如 prod_env-->
<id>開發環境名稱1</id>
<!--定義環境中的專用的屬性值-->
<properties>
<jdbc.url>jdbc連結</jdbc.url>
</properties>
<!--將該套環境設為預設啟動環境-->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!--定義具體的環境:開發環境 格式同上-->
</profiles>
Maven使用命令啟動那套環境:
mvn 指令 -p 環境定義id
# 示例
mvn install -p prod_env
# 跳過測試
提示
正式開發時,不建議跳過
跳過測試的場景:
- 整體模組功能未開發
- 模組中某個功能未開發完畢
- 單個功能更新除錯導致其他功能失敗
- 快速打包
- .........................
使用方式:
- 命令的方式
mvn 指令 –D skipTests
# 示例
mvn install –D skipTests
注意
執行的指令生命週期必須包含測試環節
- 使用IDEA介面操作
- 使用pom配置
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<!-- 設定跳過測試 -->
<skipTests>true</skipTests>
<!-- 包含指定的測試用例 -->
<includes>
<include>**/User*Test.java</include>
</includes>
<!-- 排除指定得到測試用例 -->
<excludes>
<exclude>**/User*TestCase.java</exclude>
</excludes>
</configuration>
</plugin>
# 私服
使用Nexus,是sonatype的產品:
- 下載地址1:https://help.sonatype.com/repomanager3/download
- 下載地址2:https://www.sonatype.com/thanks/repo-oss
啟動伺服器(Windows):
nexus.exe /run nexus
訪問伺服器:預設埠8081,可在其配置檔案中修改
http://localhost:8081
修改基礎配置資訊:安裝路徑/etc/nexus-default.properties,如預設埠號
修改伺服器執行配置:安裝路徑/bin/nexus.vmoptions,如預設記憶體空間大小
# IDEA中資源上傳和下載
私服倉庫分類:
宿主倉庫(hosted):儲存無法從中央倉庫獲取的資源,如
- 自主研發
- 第三方非開源專案
代理倉庫(proxy):代理遠端倉庫,透過Nexus訪問其他公共倉庫
倉庫租(group):
- 將若干殘酷組成一個群組,簡化配置
- 倉庫租不儲存資源,屬於設計型倉庫
私服使用者名稱密碼:配置在本地倉庫的setting.xml中即可
上傳位置:配置在IDEA中,上傳到私服中的倉庫組不同
下載地址:配置在本地倉庫的setting.xml即可
# 訪問私服配置
- 配置本地倉庫訪問私服許可權(setting.xml)
<servers>
<server>
<!--放release版本的 和nexus中命名保持一致-->
<id>zixq-release</id>
<!--訪問私服的使用者名稱密碼-->
<username>admin</username>
<password>admin</password>
</server>
<server>
<!--放snapshots版本的-->
<id>zixq-snapshots</id>
<username>admin</username>
<password>admin</password>
</server>
</servers>
- 配置本地倉庫來源(setting.xml)
<!--可以和阿里雲倉庫同時存在-->
<mirrors>
<mirror>
<id>nexus-zixq</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
</mirrors>
# IDEA釋出依賴到私服配置
- 配置當前專案訪問私服上傳資源的儲存位置(pom.xml)
<distributionManagement>
<repository>
<!--倉庫id,和上面本地倉庫setting.xml中server id保持一致-->
<id>zixq-release</id>
<!--放release版倉庫的url-->
<url>http://localhost:8081/repository/zixq-release/</url>
</repository>
<snapshotRepository>
<id>zixq-snapshots</id>
<url>http://localhost:8081/repository/zixq-snapshots/</url>
</snapshotRepository>
</distributionManagement>
- 釋出資源到私服的命令
mvn deploy
流程:透過IDEA pom中配置的<url>http://localhost:8081/repository/zixq-release/</url>
訪問私服,透過<id>zixq-release</id>
去本地倉庫的setting.xml 的server id找訪問私服的username、password,然後進行釋出
# IDEA外掛之Maven Helper
Maven Helper可以解決依賴問題,安裝了Maven Helper外掛,只要開啟pom檔案,就可以開啟該pom檔案的Dependency Analyzer檢視,並且這個頁面還支援搜尋。很方便
進入Dependency Analyzer檢視之後有三個檢視選項,分別是:
- Conflicts:衝突
- All Dependencies as List:列表形式檢視所有依賴
- All Dependencies as Tree:樹結構檢視所有依賴
# jar包衝突說明
解決IDEA中jar包衝突,使用maven的外掛:maven helper外掛,它能夠給我們羅列出來同一個jar包的不同版本,以及它們的來源,但是對不同jar包中同名的類沒有辦法
# 依賴順序
點選【All Dependencies as Tree】,檢視:從上向下,A依賴於B,B依賴於C
.點選【Conflicts】,從圖中可以看出有哪些jar存在衝突,存在衝突的情況下最終採用了哪個依賴的版本。標紅的就是衝突版本,白色的是當前的解析版本。這個選項,需要從下向上看
# 解決思路
- 排除指定的版本:如果有兩個依賴的版本發生了衝突,那麼只要用exclusion關鍵字把其中一個依賴給排除掉,只剩下一個依賴即可
-
子工程指定版本號
-
子工程先排除,再指定版本號:如下圖,在starter-web中排除spring-webmvc,然後指定spring-webmvc的版本為6.0.9
-
鎖定版本:使用dependencyManagement統一對依賴的版本進行定義
-
路徑優先:當依賴中出現相同的資源時,層級越深,優先順序越低,層級越淺,優先順序越高。實際使用就是直接在pom中顯示使用且定義版本
-
宣告優先:當資源在相同層級被依賴時,配置順序靠前的覆蓋配置順序靠後的
-
特殊優先:當同級配置了相同資源的不同版本,後配置的覆蓋先配置的