Maven 核心概念與使用技巧總結
近期整理個人的文章時,剛剛好看到這篇早期編寫的maven基礎總結,對于文章整體架構和maven的基礎介紹不是特別滿意,遂打算針對一些比較核心的概念和一些實用的技巧進行梳理總結,希望對你有幫助。
一、詳解maven中的核心概念
1. 關于maven中構建的概念
maven構建(build)是面向過程的串行工作流程,總的來說maven構建涉及以下幾個主要環節:
- 清理:刪除以前的編譯結果,為重新編譯做好準備,所以這也就是為什么我們平時在打包的時候總會執行以下mvn clean。
- 編譯:將Java源程序編譯為字節碼文件。
- 測試:針對項目中的關鍵點進行測試,確保項目在迭代開發過程中關鍵點的正確性。
- 報告:在每一次測試后以標準的格式記錄和展示測試結果。
- 打包:將一個包含諸多文件的工程封裝為一個壓縮文件進行安裝部署。一般情況下java 工程對應 jar 包,而web工程對應的是war包(目前主流的開發模式下基本都是使用jar包)。
- 安裝:基于maven指令將jar包或war包安裝到本地倉庫中。
- 部署:將打包的結果部署到遠程倉庫或將war包部署到服務器上運行
2. maven 中約定的目錄結構
maven作為強大的項目管理工具,其對于項目管理的標準就是其魅力所在,其文件結構目錄特點可歸納為:
- pom.xml進行統一的依賴配置。
- src目錄分為main和test分別記錄主程序的源碼和測試程序的源代碼。
- java目錄存儲源代碼。
- resources目錄記錄一些靜態文件資源。
對應的目錄樹如下所示:
project
|---src
|---|---main
|---|---|---java
|---|---|---resources
|---|---test
|---|---|---java
|---|---|---resources
|---pom.xml
二、詳解POM文件
1. POM中的基本信息
(1) modelVersion:它標識使用的Maven模型的版本,對于 Maven2 和 Maven3 來說,它只能是 4.0.0,這也是目前主流的版本:
(2) groupId:意味開發項目的組織 id,一般是公司域名的倒寫,已百度為例,其groupId就是com.baidu,而對應筆者,因為個人用過的網站域名是sharkchili.com,所以對應的groupId就是com.sharkchili。
(3) artifactId:項目名稱,也是模塊名稱(針對多模塊的maven項目),以筆者日常學習和實踐項目名為learnExample那么artifactId也就是這個名稱。
(4) version:項目的版本號。如果項目還在開發中即不穩定的開發版本,通常格式為版本-SNAPSHOT,例如筆者當前開發的初期項目版本為就是0.0.1-SNAPSHOT。
(5) packaging:項目打包的類型,可以使 jar、war、rar、ear、pom(父工程必須指明類型為pom),默認是 jar。
對應的我們也給出maven中pom這些核心配置的示例:
<!-- 模型版本-->
<modelVersion>4.0.0</modelVersion>
<!-- 項目組號-->
<groupId>com.sharkchili</groupId>
<!-- 項目名稱-->
<artifactId>learnExample</artifactId>
<!-- 打包方式-->
<packaging>pom</packaging>
<!-- 項目版本號-->
<version>0.0.1-SNAPSHOT</version>
2. 依賴的基本概念(重要)
為了一個項目可以構建或運行,項目中不可避免的,dependencies 和dependency是Maven 的一個重要概念,它的作用就是管理項目中的所引用的 jar 包。在 Maven 中,這些 jar 就被稱為依賴,使用標簽 dependency 來配置。而這種依賴的配置正是通過坐標來定位的,由此我們也不難看出,maven 把所有的 jar 包也都視為項目存在了。
按照maven的規范,pom文件會通過dependencies統一記錄引入的依賴,而引入的依賴統一使用dependency標簽進行標識,例如筆者的項目引入了spring boot和mybatis的依賴,對應的配置就如下格式所示:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>${spring-boot.version}</version>
</dependency>
<!-- 集成mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
3. 詳解屬性配置標簽properties
properties 是 用 來 定 義 一 些 配 置 屬 性 的 , 例 如:project.build.sourceEncoding(項目構建源碼編碼方式),可以設置為UTF-8,防止中文亂碼,也可定義相關構建版本號,便于日后統一升級。
以筆者的項目為例,即通過project.build.sourceEncoding和project.reporting.outputEncoding指定構建編碼和輸出報告的格式,以及通過spring-boot.version指定相關依賴的版本便于后續統一管理:
4. 詳解構建配置項build
build 表示與構建相關的配置,例如設置編譯插件的 jdk 版本等:
5. 詳解maven中繼承的概念
先來說說parent標簽,改標簽 在 Maven 中,如果多個模塊都需要聲明相同的配置,例如:groupId、version、有相同的依賴、或者相同的組件配置等,也有類似 Java 的繼承機制,用 parent 聲明要繼承的父工程的 pom 配置。
以筆者的項目為例,因為使用了spring boot的腳手架,所以對應的parent就指定所有依賴版本統一交由spring-boot-starter-parent這個spring腳手架的版本:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
6. 詳解maven中模塊化
這里我們再來說說modules的基本概念, 在 Maven 的多模塊開發中,為了統一構建整個項目的所有模塊,可以提供一個額外的模塊,該模塊打包方式為 pom,并且在其中使用 modules 聚合的其它模塊,這樣通過本模塊就可以一鍵自動識別模塊間的依賴關系來構建所有模塊,叫 Maven 的聚合。
以筆者當前的maven工程為例,它聚合了無數個子模塊,對應的父pom標簽就指定了各種module:
<modules>
<module>transactionalEventListener</module>
<module>multiTransactional</module>
<module>updateBatch</module>
</modules>
對應的我們也給出這些模塊在項目中的路徑與上述配進行對照,可以看到因為這些模塊是以maven子模塊的方式常見,所以module中都僅僅記錄模塊名稱不帶有任何路徑:
三、詳解maven中倉庫的概念
1. 倉庫的概念
Maven核心程序僅僅定義了自動化構建項目的生命周期,但具體的構建工作是由特定的構件完成的。而且為了提高構建的效率和構件復用,maven把所有的構件統一存儲在某一個位置,這個位置就叫做倉庫。
2. maven倉庫存什么
Maven倉庫主要存放的各個項目中需要引入的jar包,它可以是以下幾種類型:
- Maven 的插件,插件也是一些 jar,這些 jar 可以完成一定的功能。
- 我們自己開發并打包到本地的項目。
- 第三方框架或工具的 jar 包。
3. 倉庫的類別
根據倉庫存儲的位置,把倉庫分為如下兩種倉庫,它們分別是:
(1) 本地倉庫:本地倉庫存在于當前電腦上,默認存放在~\.m2\repository中,為本機上所有的Maven工程服務。你也可以通過Maven的配置文件Maven_home/conf/settings.xml中修改本地倉庫所在的目錄。~ 是用戶的主目錄,windows系統中是 c:/user/登錄系統的用戶名。
(2) 遠程倉庫:遠程倉庫分為為全世界范圍內的開發人員提供服務的中央倉庫、為全世界范圍內某些特定的用戶提供服務的中央倉庫鏡像、為本公司提供服務自己架設的私服。中央倉庫是maven默認的遠程倉庫,其地址是:http://repo.maven.apache.org/maven2/中央倉庫,包含了絕大多數流行的開源Java構件,以及源碼、作者信息、許可證信息等。一般來說,簡單的Java項目依賴的構件都可以在這里下載得到。
(3) 私服:是一種特殊的遠程倉庫,它是架設在局域網內的倉庫服務,私服代理廣域網上的遠程倉庫,供局域網內的Maven用戶使用。當Maven需要下載構件的時候,它從私服請求,如果私服上不存在該構件,則從外部的遠程倉庫下載,緩存在私服上之后,再為Maven的下載請求提供服務。我們還可以把一些無法從外部倉庫下載到的構件上傳到私服上。
4. Maven對倉庫的加載順序
在 Maven 構建項目的過程中如果需要某些插件,會嚴格按照如下順序進行加載:
- 先到到 Maven 的本地倉庫中查找,如果找到則可以直接使用。如果找不到,則進入步驟2。
- 在網絡連通的情況下,它會自動連接外網,到遠程中央倉庫中查找,如果遠程倉庫中能找到,則先把所需要的插件下載到本地倉庫,然后再使用,并且下次再用到相同的插件也可以直接使用本地倉庫的。
- 如果沒有外網或者遠程倉庫中也找不到,則構建失敗。
四、詳解maven依賴常見屬性
1. maven坐標(gav)
Maven 把任何一個插件都作為倉庫中的一個項目進行管理,用如下三大屬性即標識唯一的一個依賴坐標,從而讓maven完成依賴的識別和加載:
- groupId:組織名,通常是公司或組織域名倒序+項目名
- artifactId:模塊名,通常是工程名
- version:版本號
需要注意的是:項目在倉庫中的位置是由坐標來決定的:groupId、artifactId 和 version 決定項目在倉庫中的路徑,而artifactId 和 version 決定 jar 包的名稱。
2. 詳解maven中的依賴(dependency)
一個 Maven 項目正常運行需要其它項目的支持,Maven 會根據坐標自動到本地倉庫中進行查找。對于個人開發的 Maven 項目需要進行通過install指令,才能保存到本地倉庫中。
以筆者的maven項目為例,可以看到,如下坐標就標識著筆者將hutool的5.8.18版本和lombok的1.18.30版本兩個常用的依賴工具包引入到本地:
<dependencies>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>compile</scope>
</dependency>
</dependencies>
3. Maven常用設置
在 Maven 的 pom.xml 文件中,<properties>用于定義全局變量,POM 中通過${property_name}的形式引用變量的值:
定義全局變量:如下便是maven項目對于全局屬性的通用配置示例,后續如果依賴需要引用,則可以直接通過${變量}格式使用,例如我們需要使用spring-boot.version那么就可以直接通過${spring-boot.version}引用該版本:
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.4.0</spring-boot.version>
</properties>
如下便是筆者引用全局變量的示例:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
五、詳解Maven常用命令(重要)
1. 簡介maven的三大功能
Maven 對所有的功能都提供相對應的命令,對應的maven 三大功能有:
- 管理依賴
- 構建項目
- 管理項目信息
2. 管理依賴
對于maven來說,依賴管理只需要聲明就可以自動到倉庫下載,例如我們需要mybatis的相關依賴,我們只需通過dependency標簽標識依賴坐標即可完成依賴加載:
3. 項目構建
Maven 提供一個項目構建的模型,把編譯、測試、打包、部署等都對應成一個個的生命周期階段,并對每一個階段提供相應的命令,程序員只需要掌握一小堆命令,就可以完成項目的構建過程。
- mvn clean: 清理,它會刪除原來編譯和測試的目錄,也就是項目的target 目錄,需要注意的是,該指令對于install到倉庫里的包不會刪除。
- mvn compile:對主程序進行編譯,該指令會在當前目錄下生成一個 target,里邊存放編譯主程序之后生成的字節碼文件。
- mvn test-compile:對程序進行編譯測試,它會在當前目錄下生成一個 target,里邊存放編譯測試程序之后生成的字節碼文件。
- mvn test(不常用) :測試指令,會生成一個目錄surefire-reports,保存測試結果。
- mvn package(常用):執行完整的主程序打包流程,它會依次執行上述的編譯、編譯測試、測試流程,并且按照 pom.xml 配置把主程序打包生成 jar 包或者 war 包。
- mvn install: 執行主程序本地安裝,該指令會把本工程打包,并且按照本工程的坐標保存到本地倉庫中。
- mvn deploy(常用) :執行主程序發布,該指令會把本工程打包,并按照本工程的坐標保存到本地庫中,并且還會保存到私服倉庫中。便于自由依賴jar包在團隊內加載并使用。
六、詳解maven插件
1. maven構建過程簡析
maven 過程構建周期,由 maven 的插件 plugin 來執行完成。例如我們執行mvn clean install,對應控制臺就會輸出如下過程:
2. 詳解maven中的構建插件
- clean 插件maven-clean-plugin:2.5:clean :功能就是清除工程目前下的 target 目錄。
- resources 插件maven-resources-plugin:2.6:resource 插件的功能就是把項目需要的配置文件拷貝到指定的目當,默認是拷貝 src\main\resources 目錄下的件到classes 目錄下
- compile 插件 maven-compiler-plugin:用于項目的編譯。
- test 測試插件:單元測試所用的 compile 和 resources 插件和主代碼是相同的,但執行的目標不行,目標 testCompile 和 testResources是把src\test\java 下的代碼編譯成字節碼輸出到 target\test-classes,同時把 src\test\resources 下的配置文件拷貝到target\test-classes。
- package 打包插件: maven-jar-plugin
- deploy 發布插件 maven-install-plugin
七、詳解Maven 在 在 IDEA 中的應用
1. 創建maven工程
首先選擇File-->New-->Project進行項目創建:
按需給項目命名選擇maven并開始進行配置與創建:
然后,我們就可以得到一個標準結構的maven項目:
2. pom引入所需的依賴
以當前項目為例,如果筆者希望引入hutool工具包,那么我們就可以按照上文所說的dependencies標簽中給出hutool的坐標地址:
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
</dependency>
</dependencies>
如此一來,依賴就成功完成的加載了:
3. IDEA對于maven構建的側邊欄
同時我們也可以在IDEA的右側看到maven項目中的依賴、插件和構建指令等信息:
八、詳解IDEA 中導入Maven模塊
1. 在項目結構除中導入或移除module
有時候我們需要針對多個模塊進行開發(這里我們暫時不列舉maven父子工程的概念),我們就可以通過IDEA導入其他maven模塊統一界面開發,對此我們就可以點擊File-->Project Structurt進入項目導入:
然后點擊添加:
找到需要導入的工程點擊OK將其導入:
選擇導入已存在的maven模塊,然后一路點擊確定:
這樣一來目標就快就成功導入了,后續我們就可以進行統一開發管理了:
九、詳解maven的依賴管理
1. maven依賴的范圍
以下是關于 Maven 中 compile、test、provided 三種依賴范圍的詳細對比:
依賴范圍 | 對主程序是否有效 | 對測試程序是否有效 | 是否參與打包 | 是否參與部署 |
compile | 是 | 是 | 是 | 是 |
test | 否 | 是 | 否 | 否 |
provided | 是 | 是 | 否 | 否 |
2. 指定資源引入jar包
src/main/java 和 src/test/java 這兩個目錄中的所有*.java 文件會分別在 comile 和 test-comiple 階段被編譯,編譯結果分別放到了 target/classes 和 targe/test-classes 目錄中,但是這兩個目錄中的其他文件都會被忽略掉。 如果需要把 src 目錄下的文件包放到 target/classes 目錄,作為輸出的 jar 一部分。需要指定資源文件位置,如下所示,通過<build>標簽來指定配置:
<build>
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目錄-->
<includes><!--包括目錄下的.properties,.xml 文件都會掃描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!-- filtering 選項 false 不啟用過濾器, *.property 已經起到過濾的作用了 -->
<filtering>false</filtering>
</resource>
</resources>
</build>