目錄
- Maven 簡介
- Maven 是什么
- 為什么使用 Maven?
- 安裝 Maven
- 下載 Maven
- 配置 Maven
- 解壓文件
- 配置本地倉庫保存路徑
- 配置國內倉庫地址
- Maven 的核心概念
- 了解 pom.xml 文件
- 坐標
- 依賴范圍
- 生命周期
- compile
- provided
- runtime
- test
- system
- import
- 依賴傳遞
- 依賴排除
- 依賴循環
- 繼承
- 1. Maven 繼承的基本概念
- 2. 如何使用 Maven 繼承
- 2.1 創建父項目 `pom.xml`
- 2.2 創建子項目 `pom.xml`
- build 標簽組成
- 生命周期插件
- 常見的生命周期插件示例
- SpringBoot 定制化打包
- Reference
Maven 簡介
Maven 是什么
Maven 是 Apache 軟件基金會開發的一個項目管理和構建自動化工具,主要用于 Java 項目。它可以:
- 管理項目的依賴(比如第三方庫)
- 自動構建項目(編譯、打包)
- 管理項目的生命周期(從創建到發布)
- 管理插件(自動化任務,如測試、代碼檢查)
一個 Maven 工程遵循約定的目錄結構,這種標準化的目錄布局是 Maven 實現自動化構建過程中不可或缺的關鍵環節。Maven 推薦采用統一的目錄結構,以確保項目的一致性和構建過程的高效性。
project-name/
├── src/
│ ├── main/
│ │ └── java/ # 主代碼
│ └── test/
│ └── java/ # 測試代碼
├── pom.xml # Maven 配置文件
為什么使用 Maven?
傳統 Java 項目可能要手動:
- 下載 JAR 包(第三方庫)
- 配置類路徑(classpath)
- 編譯源代碼
- 打包成 jar/war 文件
Maven 全部幫你做了!它像一個「項目自動管家」,你只需寫好配置文件(pom.xml
),Maven 會自動根據配置從倉庫中拉取依賴。
安裝 Maven
下載 Maven
下載地址:https://maven.apache.org/download.cgi
你可以下載最新版本的 Maven,也可以選擇其他版本
然后里面選擇自己對應的版本下載即可:
配置 Maven
解壓文件
下載之后,解壓到非中文的文件目錄,如下:
配置本地倉庫保存路徑
Maven 會在每次從遠程倉庫獲取第三方依賴后,將其緩存至本地指定的存儲路徑中。這一機制有效避免了在每次構建新項目時重復從遠程倉庫拉取相同依賴的情況,從而顯著提升了開發效率并減少了不必要的網絡開銷。
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
-->
<localRepository>D:\Environment\Repository</localRepository>
本地倉庫默認值:用戶/.m2/repository。由于本地倉庫的默認位置是在用戶的家目錄下,而家目錄往往是在 C 盤,也就是系統盤。將來 Maven 倉庫中 jar 包越來越多,倉庫體積越來越大,可能會拖慢 C 盤運行速度,影響系統性能。
配置國內倉庫地址
Maven 下載 jar 包默認訪問境外的中央倉庫,而國外網站速度很慢。改成阿里云提供的鏡像倉庫,訪問國內網站,可以讓 Maven 下載 jar 包的時候速度更快。配置的方式是:
<mirror><id>tencent</id><name>tencent maven</name><url>http://mirrors.cloud.tencent.com/nexus/repository/maven-public/</url><mirrorOf>central</mirrorOf>
</mirror><mirror><id>nexus-aliyun</id><mirrorOf>central</mirrorOf><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
Maven 的核心概念
了解 pom.xml 文件
pom.xml
(Project Object Model)是 Maven 項目的核心配置文件,其主要功能在于對項目的全面描述與定義,包括但不限于以下內容:
- 項目元信息:定義項目的基本信息,如名稱、版本、組織等標識性數據。
- 依賴管理:聲明項目所依賴的外部庫及其版本,確保構建過程中的依賴解析與一致性。
- 構建配置:指定項目的構建規則,包括編譯、測試、打包等生命周期階段的具體行為。
- 插件與擴展:配置用于增強構建能力的插件及擴展模塊,支持定制化構建需求。
通過 pom.xml
,Maven 實現了項目結構的標準化與構建過程的自動化,為開發者提供了高效且可維護的項目管理工具。
<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><!-- 當前Maven工程的坐標 --><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>Demo project for Spring Boot</description><!-- 當前Maven工程的打包方式,可選值有下面三種: --><!-- jar:表示這個工程是一個Java工程 --><!-- war:表示這個工程是一個Web工程 --><!-- pom:表示這個工程是“管理其他工程”的工程 --><packaging>jar</packaging><properties><!-- 工程構建過程中讀取源碼時使用的字符集 --><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><!-- 當前工程所依賴的jar包 --><dependencies><dependency><!-- 在dependency標簽內使用具體的坐標依賴我們需要的一個jar包 --><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><!-- scope標簽配置依賴的范圍 --><scope>test</scope></dependency></dependencies><!-- 構建配置 --><build><plugins><!-- 編譯插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.10.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build>
</project>
坐標

每一個依賴(或項目)都有三個關鍵標識:
groupId
:組織名,一般是域名反寫,如org.springframework
artifactId
:模塊名,如spring-core
version
:版本號,如5.3.10
合起來可以唯一確定一個庫,如下:
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>compile</scope>
項目首次運行時,會從遠程倉庫拉取依賴,并保存到本地倉庫
上面坐標對應的 jar 包在 Maven 本地倉庫中的位置:
Maven本地倉庫根目錄\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar
依賴范圍
在 Maven 中,依賴范圍(Dependency Scope)決定了一個依賴在構建過程中的可用性和傳播性。
Maven 的生命周期如下:編譯、測試、運行、打包。
不同的范圍影響了該依賴在不同生命周期階段的行為,即<scope>
標簽。
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><!-- scope標簽配置依賴的范圍 --><scope>test</scope>
</dependency>
Maven 提供了幾種常用的依賴范圍類型,每種類型有不同的含義和使用場景。
生命周期
編譯:將 Java 源代碼文件(.java
文件)轉換為 字節碼(.class
文件),這是 Java 虛擬機(JVM)能夠執行的代碼。
測試: 執行單元測試(Unit Test)和集成測試(Integration Test)等。
運行:項目最終的運行時環境中。
打包:將當前項目打包成 Jar 或者 War 包。
compile
描述:compile
范圍是 Maven 依賴的默認范圍。如果你沒有顯式指定依賴的范圍,它會自動使用 compile
范圍。compile
范圍表示該依賴在編譯、測試、運行時都需要。
可用階段:
- 編譯時:可以使用
- 測試時:可以使用
- 運行時:可以使用
- 打包時:包含在最終的構件中
常見場景:適用于大多數的應用程序庫,通常是核心依賴。
示例:
<dependency><groupId>com.example</groupId><artifactId>some-library</artifactId><version>1.0</version>
</dependency>
provided
描述:provided
范圍表示該依賴在編譯和測試時需要,但在運行時由容器或運行時環境提供。典型的例子是 Web 應用程序中的 Servlet API,它在 Web 容器(如 Tomcat)中已經提供,因此不需要在最終的構件中包含該依賴。
可用階段:
- 編譯時:可以使用
- 測試時:可以使用
- 運行時:不包含
- 打包時:不包含(因為容器已經提供了該依賴)
常見場景:Web 項目中的容器依賴(如 servlet-api
)或者一些 Java EE API。
示例:
<dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>3.1.0</version><scope>provided</scope>
</dependency>
runtime
描述:runtime
范圍表示該依賴在運行時需要,但在編譯時不需要。通常這種范圍適用于某些在運行時才需要的庫,比如數據庫驅動程序或者日志框架。
可用階段:
- 編譯時:不需要
- 測試時:可以使用
- 運行時:需要
- 打包時:包含
常見場景:用于運行時需要的庫,通常是數據庫連接池、日志框架等。
示例:
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version><scope>runtime</scope>
</dependency>
test
描述:test
范圍表示該依賴僅在測試時需要。它不會在項目的運行時或者生產環境中包含。通常用于單元測試框架(如 JUnit 或 TestNG)和一些測試工具。
可用階段:
- 編譯時:可以使用
- 測試時:可以使用
- 運行時:不需要
- 打包時:不包含
常見場景:單元測試框架(JUnit、TestNG)、模擬庫(Mockito)等。
示例:
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>
</dependency>
system
描述:system
范圍表示該依賴位于項目外部(如本地文件系統中)。它不是從遠程倉庫下載的,而是通過文件路徑直接引用。system
范圍的依賴必須指定 systemPath
屬性,該路徑指向文件的實際位置。
可用階段:
- 編譯時:可以使用
- 測試時:可以使用
- 運行時:需要
- 打包時:包含
示例:
<dependency><groupId>com.example</groupId><artifactId>some-library</artifactId><version>1.0</version><scope>system</scope><systemPath>${project.basedir}/lib/some-library.jar</systemPath>
</dependency>
注意:不推薦使用
system
范圍,因為它不具備跨平臺的特性,依賴文件路徑是硬編碼的,缺乏可移植性。
import
描述:import
范圍主要用于導入 BOM(Bill of Materials)類型的依賴,它不會像普通的依賴那樣將 JAR 文件直接添加到構建中,而是通過繼承管理的一組版本。常用于依賴管理(dependencyManagement
)的場景,通常在多模塊項目中,或者用于引入其他項目的版本管理。
可用階段:
- 編譯時:不可用
- 測試時:不可用
- 運行時:不可用
- 打包時:不可用
常見場景:用于在父項目中管理子模塊的依賴版本,或引用第三方庫的版本管理。
示例:
<dependencyManagement><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>4.3.7.RELEASE</version><scope>import</scope><type>pom</type></dependency></dependencies>
</dependencyManagement>
依賴傳遞
Maven 支持依賴傳遞,即當一個項目依賴于某個庫時,若該庫本身依賴其他庫,這些依賴會自動成為當前項目的依賴,直到最終沒有更多的傳遞依賴為止。
假設我們有以下的項目依賴關系:
- 項目
A
依賴項目B
。 - 項目
B
依賴項目C
。 - 項目
A
和B
不需要直接依賴C
,就可以引入mysql-connector-java
和lombok
依賴
通過執行依賴樹:
mvn dependency:tree
輸出結果
[INFO] com.example:project-A:jar:1.0
[INFO] +- com.example:library-B:jar:1.0:compile
[INFO] | +- com.example:library-C:jar:1.0:compile
[INFO] | | +- mysql:mysql-connector-java:jar:8.0.23:compile
[INFO] | | \- org.projectlombok:lombok:jar:1.18.20:provided
[INFO] \- (omitted for brevity)
依賴排除
如果 A
項目現在不需要使用 mysql 的依賴或者單獨使用其他版本的依賴,應該如何處理呢?
Maven 提供了依賴排除的工程,避免版本沖突或者不必要的依賴,可以在 pom
文件中進行配置。
<!-- A項目的坐標 -->
<groupId>com.example</groupId>
<artifactId>project-A</artifactId>
<version>1.0</version><dependencies><!-- A 項目依賴 B 項目 --><dependency><groupId>com.example</groupId><artifactId>library-B</artifactId><version>1.0</version><exclusions><!-- 排除 C 項目傳遞的 MySQL 依賴 --><exclusion><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></exclusion></exclusions></dependency>
</dependencies>
通過執行依賴樹:
mvn dependency:tree
輸出結果
[INFO] com.example:project-A:jar:1.0
[INFO] +- com.example:library-B:jar:1.0:compile
[INFO] | +- com.example:library-C:jar:1.0:compile
[INFO] | \- org.projectlombok:lombok:jar:1.18.20:provided
[INFO] \- (omitted for brevity)
MySQL 依賴沒有出現在依賴樹中,因為我們通過 <exclusions>
明確排除了 MySQL
依賴。
依賴循環

如果 A
工程依賴 B
工程,B
工程依賴 C
工程,C
工程又反過來依賴 A
工程,那么在執行構建操作時會報下面的錯誤:
[ERROR] [ERROR] The projects in the reactor contain a cyclic reference:
繼承
Maven 的 繼承 是一種在多模塊項目或父子項目之間共享配置的機制。通過繼承,子項目可以繼承父項目的依賴、插件、屬性、版本信息等配置,減少冗余的配置,提高可維護性。父子項目的關系是通過 parent
元素在 pom.xml
中實現的。
1. Maven 繼承的基本概念
父項目(Parent Project):一個包含通用配置和版本管理的項目,其他子項目可以繼承這些配置。
子項目(Child Project):繼承父項目的 pom.xml
中定義的配置,包括依賴、插件、構建配置等
2. 如何使用 Maven 繼承
2.1 創建父項目 pom.xml
父項目 pom.xml
中可以定義通用的配置,例如依賴版本、插件配置、構建配置等。然后,子項目通過 <parent>
元素繼承這些配置。
父項目的 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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>parent-project</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging> <!-- 父項目的打包類型通常是 pom --><!-- 指定子項目 --><modules><module>child-project</module></modules><dependencyManagement><dependencies><!-- 在父項目中聲明的依賴版本會被所有子項目繼承 --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.3.9</version></dependency></dependencies></dependencyManagement><build><pluginManagement><plugins><!-- 子項目會繼承父項目的插件配置 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></pluginManagement></build></project>
在這個父項目中:
dependencyManagement
:管理所有子項目中共享的依賴版本。pluginManagement
:定義了子項目共享的插件和插件的配置。
2.2 創建子項目 pom.xml
子項目通過 <parent>
元素來繼承父項目的配置。子項目的 pom.xml
中需要指明父項目的 groupId
、artifactId
和 version
。
子項目的 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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!-- 父項目坐標 --><parent><groupId>com.example</groupId><artifactId>parent-project</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>child-project</artifactId><dependencies><!-- 繼承父項目的 spring-core 依賴,版本由父項目提供 --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></dependency></dependencies><build><plugins><!-- 子項目繼承父項目的插件配置 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId></plugin></plugins></build></project>
在這個子項目中:
- 子項目 繼承了父項目的依賴管理,因此不需要在子項目中顯式地指定
spring-core
的版本。 - 子項目 繼承了父項目的插件配置,因此不需要重新定義
maven-compiler-plugin
插件的版本和配置。
build 標簽組成
生命周期插件
Maven 使用插件來執行不同生命周期階段的任務,如編譯、測試、打包等。每個生命周期都有多個階段,而插件負責在這些階段執行實際的任務。Maven 默認有多個生命周期,比如 清理生命周期、默認生命周期 和 站點生命周期。通過 build
標簽中的 <plugins>
元素,你可以為不同的生命周期階段指定插件。
常見的生命周期插件示例
- maven-compiler-plugin:用于編譯 Java 代碼
- maven-surefire-plugin:用于運行單元測試
- maven-jar-plugin:用于打包 JAR 文件
- maven-war-plugin:用于打包 WAR 文件
<build><plugins><!-- 編譯插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source> <!-- 指定編譯的 JDK 版本 --><target>1.8</target> <!-- 指定目標 JDK 版本 --></configuration></plugin><!-- 單元測試插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.22.2</version></plugin><!-- JAR 打包插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.1.0</version><configuration><finalName>my-app</finalName></configuration></plugin></plugins>
</build>
在上面的示例中,指定了三個常用的插件:
maven-compiler-plugin
:用于指定編譯的 JDK 版本。maven-surefire-plugin
:用于運行單元測試。maven-jar-plugin
:用于創建 JAR 文件,并指定輸出文件名。
SpringBoot 定制化打包
Spring Boot 提供了非常靈活的構建和打包方式,你可以通過 Maven 插件來定制 Spring Boot 項目的打包過程。Spring Boot 使用 spring-boot-maven-plugin
插件來創建可執行的 JAR 或 WAR 文件。
<build><plugins><!-- Spring Boot Maven 插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.5.2</version> <!-- 使用的 Spring Boot 版本 --><configuration><finalName>my-springboot-app</finalName> <!-- 打包后的文件名 --></configuration></plugin></plugins>
</build>
Reference
- 超級詳細的 Maven 教程(基礎+高級)
- https://chatgpt.com/