Maven 筆記

紫明轩發表於2024-07-02

# Maven簡介

Maven的本質是一個專案管理工具,將專案開發和管理過程抽象成一個專案物件模型(POM))

這玩意兒是使用Java開發的,所以採用的就是Java的思想:物件導向

POM (Project Object Model):專案物件模型
截圖2021-07-17 下午6.51.07

Maven的作用:

  1. 專案構建:提供標準的、跨平臺的自動化專案構建方式
  2. 依賴管理:方便快捷的管理專案依賴的資源(jar包),避免資源間的版本衝突問題
  3. 統一開發結構:提供標準的、統一的專案結構

下載與安裝:

  • 官網:http://maven.apache.org/
  • 下載:http://maven.apache.org/download.cgi

# Maven基礎概念

image-20240621211654330

倉庫:用於儲存資源,包含各種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工程目錄結構
截圖2021-07-17 下午6.50.36

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>

# 依賴管理

  1. 依賴配置:依賴指的是當前專案執行所需要的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>
    
  2. 依賴傳遞

依賴具有傳遞性,包括直接傳遞和間接傳遞

直接傳遞:在當前專案中透過依賴配置建立的依賴關係(A使用B,A和B就是直接傳遞)

間接傳遞:被依賴的資源如果依賴其他資源,當前專案間接依賴其他資源(比較拗口,意思是如果A依賴B,而B依賴C,那麼

A和C之間就是間接傳遞)

截圖2021-07-17 下午6.49.40

依賴傳遞的衝突問題:

  • 路徑優先:當依賴中出現相同的資源時,層級越深,優先順序越低,層級越淺,優先順序越高
  • 宣告優先:當資源在相同層級被依賴時,配置順序靠前的覆蓋配置順序靠後的
  • 特殊優先:當同級配置了相同資源的不同版本,後配置的覆蓋先配置的
  1. 可選依賴

可選依賴指的是對外隱藏當前所依賴的資源

<dependency>
  <groupId></groupId>
  <artifactId></artifactId>
  <version></version>
  <!--新增下面這一行-->
  <optional>true</optional>
</dependency>
  1. 排除依賴

排除依賴指主動斷開依賴的資源,被排除的資源無需指定版本

<dependency>
  <groupId></groupId>
  <artifactId></artifactId>
  <version></version>
  <exclusions>
    <exclusion>
      <groupId></groupId>
      <artifactId></artifactId>
    </exclusion>
  </exclusions>
</dependency>
  1. 依賴範圍

依賴的jar包預設情況可以在任何地方使用,可以透過scope標籤設定其作用範圍

作用範圍:

  • 主程式範圍有效(main資料夾範圍內)
  • 測試程式範圍有效(test資料夾範圍內)
  • 是否參與打包(package資料夾範圍內)
截圖2021-07-17 下午7.10.15

還有兩個:system、import

  • import:依賴項替換為指定 POM 的 <dependencyManagement>中的該依賴項。僅 <dependencyManagement> 部分中 pom 型別的依賴項支援此範圍
  1. 依賴範圍傳遞性:帶有依賴範圍的資源在傳遞時,作用範圍會受到影響

image-20240621212758397

# 生命週期與外掛

Maven專案構建生命週期描述的是一次構建過程經歷了多少個事件

image-20240621212937084

Maven對專案構建的生命週期劃分為3套

  1. clean:清理工作
  2. default:核心工作,例如編譯、測試、打包、部署等
  3. 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>

繼承的資源:

image-20240622012647178

# 繼承與聚合的區別

作用:聚合用於快速構建專案,繼承用於快速配置

相同點:

  • 聚合與繼承的pom.xml檔案打包方式均為pom,可以將兩種關係製作到同一個pom檔案中

  • 聚合與繼承均屬於設計型模組,並無實際的模組內容

不同點:

  • 聚合是在當前模組中配置關係,聚合可以感知到參與聚合的模組有哪些

  • 繼承是在子模組中配置關係,父模組無法感知哪些子模組繼承了自己

# 屬性

  1. 自定義屬性

作用:等同於定義變數,方便統一維護

定義格式:

<!--定義自定義屬性-->
<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>
  1. 內建屬性

作用:使用Maven內建屬性,快速配置

呼叫格式:

${basedir}
${version}
  1. Setting屬性

作用:使用Maven配置檔案setting.xml中的標籤屬性,用於動態配置

呼叫格式:

${settings.localRepository}
  1. Java系統屬性

作用:讀取Java系統屬性

呼叫格式:

${user.home}

系統屬性查詢方式:

mvn help:system
  1. 環境變數屬性

作用:使用Maven配置檔案setting.xml中的標籤屬性,用於動態配置

呼叫格式:

${env.JAVA_HOME}

環境變數屬性查詢方式:

mvn help:system

# 版本管理

SNAPSHOT(快照版本):

  • 專案開發過程中,方便團隊成員合作,解決模組間相互依賴和實時更新的問題,開發者對每個模組進行構建的時候,輸出的臨時性版本就叫快照版本(測試階段版本)
  • 快照版本會隨著開發的進展不斷更新

RELEASE(釋出版本):

  • 專案開發到進入階段里程碑後,向團隊外部發布較為穩定的版本,這種版本所對應的構建檔案是穩定的,即便進行功能的後續開發,也不會改變當前釋出版本的內容,這種版本就叫釋出版本

工程版本號約定:

截圖2021-07-17 下午8.24.46

# 資源配置

配置檔案引用pom屬性

作用:在任意配置檔案中載入pom檔案中定義的屬性

  1. pom中定義變數:
<properties>
	<jdbc.username>root</jdbc.username>
    <jdbc.password>zixieqing072413</jdbc.password>
</properties>
  1. 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>
  1. 在需要使用變數得到配置檔案中使用,呼叫格式:
${地址}


<!--示例-->
${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

# 跳過測試

提示

正式開發時,不建議跳過

跳過測試的場景:

  • 整體模組功能未開發
  • 模組中某個功能未開發完畢
  • 單個功能更新除錯導致其他功能失敗
  • 快速打包
  • .........................

使用方式:

  1. 命令的方式
mvn 指令 –D skipTests

# 示例
mvn install –D skipTests

注意

執行的指令生命週期必須包含測試環節

  1. 使用IDEA介面操作

image-20240622024041847

  1. 使用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):

  • 將若干殘酷組成一個群組,簡化配置
  • 倉庫租不儲存資源,屬於設計型倉庫

image-20240622154257305

私服使用者名稱密碼:配置在本地倉庫的setting.xml中即可

上傳位置:配置在IDEA中,上傳到私服中的倉庫組不同

下載地址:配置在本地倉庫的setting.xml即可

# 訪問私服配置

  1. 配置本地倉庫訪問私服許可權(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>
  1. 配置本地倉庫來源(setting.xml)
<!--可以和阿里雲倉庫同時存在-->

<mirrors>
    <mirror>
    <id>nexus-zixq</id>
    <mirrorOf>*</mirrorOf>
	<url>http://localhost:8081/repository/maven-public/</url>
    </mirror>
</mirrors>

# IDEA釋出依賴到私服配置

  1. 配置當前專案訪問私服上傳資源的儲存位置(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>
  1. 釋出資源到私服的命令
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:樹結構檢視所有依賴

image-20240622161654202

image-20240622161913548

# jar包衝突說明

解決IDEA中jar包衝突,使用maven的外掛:maven helper外掛,它能夠給我們羅列出來同一個jar包的不同版本,以及它們的來源,但是對不同jar包中同名的類沒有辦法

# 依賴順序

點選【All Dependencies as Tree】,檢視:從上向下,A依賴於B,B依賴於C

image-20240622162333722

.點選【Conflicts】,從圖中可以看出有哪些jar存在衝突,存在衝突的情況下最終採用了哪個依賴的版本。標紅的就是衝突版本,白色的是當前的解析版本。這個選項,需要從下向上看

image-20240622162927630

# 解決思路

  1. 排除指定的版本:如果有兩個依賴的版本發生了衝突,那麼只要用exclusion關鍵字把其中一個依賴給排除掉,只剩下一個依賴即可

image-20240622163156783

  1. 子工程指定版本號

  2. 子工程先排除,再指定版本號:如下圖,在starter-web中排除spring-webmvc,然後指定spring-webmvc的版本為6.0.9

image-20240622163357642

  1. 鎖定版本:使用dependencyManagement統一對依賴的版本進行定義

  2. 路徑優先:當依賴中出現相同的資源時,層級越深,優先順序越低,層級越淺,優先順序越高。實際使用就是直接在pom中顯示使用且定義版本

  3. 宣告優先:當資源在相同層級被依賴時,配置順序靠前的覆蓋配置順序靠後的

  4. 特殊優先:當同級配置了相同資源的不同版本,後配置的覆蓋先配置的

相關文章