Maven 基礎(一) | 使用 Maven 的正確姿勢
- 2020 年 1 月 13 日
- 筆記

記得,剛工作的時候我連 maven 都不會用,現在工作差不多兩年了,對 maven 也有一定的了解。我平時有做筆記的習慣,這篇是我學習時整理的筆記,分享給你們,有用的話,求文末點亮一個在看,謝謝你!
一、什麼是 Maven?
Maven
是一個項目管理工具,它的本質是一個項目對象模型 (POM),體現在配置中就是我們常見的 pom.xml
文件,而這個 pom
文件就是 Maven
的核心,它管理了整個項目的生命周期。它主要做兩件事:
- 項目構建:對項目進行編譯、打包、測試、部署以及上傳到私服倉庫等
- 依賴管理:
Maven
誕生時就提出了一個倉庫的概念,項目中用到的第三方jar
包,我們在pom.xml
中配置好依賴即可,Maven
會自動到它的官方中央倉庫下載這個jar
包到我們的本地倉庫。 - 中央倉庫地址:https://mvnrepository.com/
二、為什麼要使用 Maven?
- 方便依賴管理:
Java
發展至今,生態非常完善。我們在項目中用到什麼功能,網上一搜肯定有對應的jar
包,各種功能就導致了各種jar
包的引入,這些jar
包之間可能會有依賴,可能會有版本衝突。而Maven
的誕生解決了這些問題。 - 構建多模塊項目:現在很多項目都是分了多個模塊,便於開發、也便於擴展。多模塊就意味着模塊之間會有各種依賴,我們運行某個模塊,可能這個模塊依賴了別的模塊。而
Maven
的一鍵構建項目幫我們解決了這個問題。 - 方便移植:以前沒
maven
的時代,團隊協作要上傳、下載一大堆jar
包導入項目,耗時、費力。而有了maven
,我們只需要同步一下pom
文件即可同步jar
包。這是maven
解決的第三個問題。
三、怎麼使用 Maven?
3.1 Maven 的安裝
這個就不講了,網上很多資料。比如:
- https://www.cnblogs.com/KyleXu/p/9972042.html
3.2 Maven 的配置
Maven
的配置比較簡單,主要是修改 conf
文件夾下的 setting
文件。配置以下三個倉庫:
本地倉庫
項目依賴的 jar
包是需要下載到本地才能用的。本地倉庫就是從 maven 私服或者遠程倉庫下載的 jar
的存儲地址,默認是 當前用戶名.m2repository
,我建議改個好記的地方,後面方便檢查包有沒下載到本地。打開 setting.xml
搜索 localRepository
修改成自定義的地址。
<localRepository>D:Repository</localRepository>
配置的位置,如下圖:

本地倉庫
私服倉庫
這個倉庫的話,一般就是公司內部使用的啦。用來存儲公司內部自己的 jar
包。打開 setting.xml
文件搜索 mirrors
,配置公司的鏡像地址即可。
<mirror> <id>nexus-repos</id> <mirrorOf>*</mirrorOf> <name>Team Nexus Repository</name> <url>http://127.0.0.1:8081/nexus/content/groups/public</url> </mirror>
遠程倉庫
遠程倉庫就是一個 maven
官方維護的,包含大量 jar
包的倉庫。這個庫默認是 maven 官方的,但是下載非常慢。所以業界典範阿里巴巴也推出了一個國內的鏡像,我們一般把遠程倉庫配成阿里的鏡像地址,就可以快速地下載 jar
包啦。和私服倉庫一樣,遠程倉庫也是配置在 <mirrors>
標籤內。
<mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror>
配置的位置,如下圖:

遠程倉庫
有人可能問了,配置那麼多個倉庫。究竟 jar
從哪個下載的呀?都把我搞糊塗了,別急,我花了個流程圖,它的查找順序是這樣的:本地不需要網絡,優先從本地找;找不到,再去速度較高的內網私服找;然後才是速度稍低的外網遠程倉庫找。

maven 查找文件流程
3.3 Maven 的命令
常用命令
命令 |
含義 |
備註 |
---|---|---|
mvn clean |
清除 |
打包前,清空上一次的包 |
mvn compile |
編譯 |
將 java 代碼編譯成 class 文件 |
mvn test |
測試 |
運行單元測試 |
mvn install |
安裝到本地 |
安裝到本地倉庫,一般是 jar 包 |
mvn package |
打包 |
一般會在 target 目錄下生成包,jar 或 war |
mvn deploy |
上傳 |
上傳到私服,需在 setting.xml 文件配置私服倉庫以及賬號密碼 |
以上就是 maven
常用的命令,要注意的是:很少情況下我們只運行其中一個命令,都是組合運行的。比如打包到本地,打包前得清空原有的包吧?那組合起來就是 mvn clean
+ mvn install
當然,在 IDEA
中開發 maven
項目,我們並不需要手打。只需點擊對應命令即可(也可以按住 ctrl
選中多個命令一起運行)

maven 操作
總而言之,根據自己的需求來選擇打包命令。還有其他的命令請見:
- maven 詳細命令參考:https://www.jianshu.com/p/ee7bc34d7ccc
創建 maven 項目
現在一般都是配合 idea
新建 maven 項目了,這個命令用得很少,但我們還是得知道一下:生成 maven
項目的原理是,依賴一個插件 maven-archetype-plugin
,然後這個插件自帶一些 archetype
模版,也可以說成項目的骨架。其中:-DgroupId
和 -DartifactId
填寫自己想好的項目坐標,一般 -DgroupId
是公司名的翻轉,比如 com.google
而 -DartifactId
就是項目的名稱了。最重要的是 -DarchetypeArtifactId
,他指定了創建的骨架。
mvn archetype:generate -DgroupId=com.nasus -DartifactId=maven-test -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

創建 maven 項目成功
點進去,只有 src
文件夾和 pom.xml
文件:src
是最重要的目錄,代碼和測試用例以及資源都是放在這裡的,對於 maven 項目而言,pom.xml
也是必不可少的。

項目結構
用 idea
打開的項目結構是這樣的:

idea 打開
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/maven-v4_0_0.xsd"> <!--聲明項目描述符遵循哪一個 POM 模型版本,上面的 xsd 規範定義了這個版本,默認就行,不需要修改,不可刪除--> <modelVersion>4.0.0</modelVersion> <!--團體唯一標識符--> <groupId>com.nasus</groupId> <!--項目唯一標識符定位這個包--> <artifactId>maven-test</artifactId> <!--打包類型--> <packaging>jar</packaging> <!--打包版本--> <version>1.0-SNAPSHOT</version> <!--包名--> <name>maven-test</name> <!--不用管,刪掉也行--> <url>http://maven.apache.org</url> <!--項目需要依賴的 jar 包--> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
由於篇幅原因,這裡就不詳細講具體的 pom.xml
標籤了,詳細介紹請看:
- pom 標籤介紹參考:https://www.runoob.com/maven/maven-pom.html
項目打包到本地倉庫
由於項目是 java
項目,在打包前,我們要在 pom.xml
中配置項目的 JDK
版本以及 maven
插件版本,在 <dependencies>
標籤前加入項目屬性配置,完整配置如下:
<!--項目屬性,在 <dependencies> 前加--> <properties> <!-- JDK編譯版本 --> <java.version>1.8</java.version> <!-- 項目編碼 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- JDK編譯版本 --> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties> <!--項目需要依賴的 jar 包--> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies>
選擇命令,這裡我選了 clean、compile、package
:

選擇命令
點擊綠色執行按鈕,在 target
目錄下生成 maven-test-1.0.SNAPSHOT.jar
:

打包結果
跳過單元測試
在開發中,我們經常需要本地測試,而這時我們是不需要跑單元測試的。所以,我們可以跳過單元測試:選中 test
,點擊紅框按鈕即可。

跳過單元測試
手動打 jar 包到本地倉庫
手動打 jar
包的應用場景是:開發公司舊項目,當找不到依賴的 jar
源碼,依賴的 jar
又沒有上傳到倉庫,只有在同事電腦的本地倉庫有一個 jar
包時,我們可以直接運行這條命令把 jar
包打到我們電腦本地倉庫,愉快的使用起來。
mvn install:install-file -Dfile=jar包的路徑 -DgroupId=gruopId中的內容 -DartifactId=actifactId的內容 -Dversion=version的內容 -Dpackaging=jar
四、maven 依賴管理
maven 通過 pom.xml 來進行依賴管理,我們用它來描述項目的依賴屬性。可以把它看作是 maven 項目的地圖,它描述了 jar 包的坐標、版本以及依賴關係等。如果不確定你想要引入 jar 的坐標怎麼寫,可以上 maven 中央倉庫查詢:
- maven 中央倉庫:https://mvnrepository.com/
4.1 maven 坐標
maven 的第三方依賴都在 <dependencies>
標籤內定義,該標籤下的 <dependency>
包裹的內容就是一個 jar
的坐標,如下 pom 就引入了 junit
和 cglib
兩個 jar
。下面就說一下每個坐標的標籤都代表什麼。
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency> </dependencies>
- dependencies
在 dependencies 標籤中,添加項目需要的 jar 所對應的 maven 坐標。
- dependency
一個 dependency 標籤表示一個坐標,也就是一個 jar,在 pom 中引入一個 jar 可以這樣寫:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
- groupId
公司、團體、個人開發者的唯一標識符,maven 約束它以創建這個項目的組織名稱的逆向域名開頭,比如開發者的域名是 nasus.com
那他的唯一標識符就是 com.nasus
。
<!--團體唯一標識符--> <groupId>com.nasus</groupId>
- artifactId
項目唯一標識符,一個組織可能有多個項目,為了方便 maven 引入,maven 約定以項目名稱命名該標識符,比如我開發的 maven-test 項目。
<!--項目唯一標識符--> <artifactId>maven-test</artifactId>
- version
項目的版本。一個項目,可能會有多個版本。如果是正在開發的項目,我們可以給版本號加上一個 SNAPSHOT,表示這是一個快照版本。
什麼是快照?
對於版本,如果 maven
以前下載過指定的版本文件,比如說 maven-test:1.0
,maven
將不會再從倉庫下載新的可用的 1.0
文件。若要下載更新的代碼,maven-test
的版本需要升到 1.1
。
快照是一種特殊的版本,指定了某個當前的開發進度的副本。不同於常規的版本,maven
每次構建都會在遠程倉庫中檢查新的快照。我們自己的模塊依賴了同事開發的模塊,正常來說,同事會每次發佈更新代碼的快照到倉庫中。
新建項目的默認版本號就是快照版,比如上面用 maven 命令新建的 maven-test 項目:

SNAPSHOT
4.2 依賴範圍
- scope
maven 項目不同的階段引入到 classpath 中的依賴是不同的,例如,編譯時,maven 會將與編譯相關的依賴引入 classpath 中,測試時,maven 會將測試相關的的依賴引入到 classpath 中,運行時,maven 會將與運行相關的依賴引入 classpath 中,而依賴範圍就是用來控制依賴於這三種 classpath 的關係。 如下圖所示:

依賴傳遞,圖:菜鳥教程
scope 表示依賴的範圍,它有 compile(編譯階段)、test(測試階段)、provided(供應階段)、runtime(運行階段)、system(系統階段)、import(導入階段)
六個可選值。其中 compile
是默認的。system
和 import
用得少,不詳細講。
不同依賴的適用範圍不一樣,舉幾個最典型的栗子:
範圍 |
編譯有效 |
測試有效 |
運行時有效 |
打包有效 |
示例 |
---|---|---|---|---|---|
compile |
√ |
√ |
√ |
√ |
spring-core |
test |
× |
√ |
× |
× |
junit |
provided |
√ |
√ |
× |
× |
javax.servlet-api |
runtime |
× |
√ |
√ |
√ |
JDBC 驅動 |
- compile: 編譯依賴範圍。如果沒有指定,就會默認使用該依賴範圍。使用此依賴範圍的 Maven 依賴,對於編譯、供應、測試、運行四種 classpath 都有效。比如
spring-core
- provided: 已提供依賴範圍。使用此依賴範圍的 Maven 依賴,對於 編譯和測試 classpath 有效,但在運行時無效。典型的例子是
servlet-api
編譯和測試項目的時候需要該依賴,但在運行項目的時候,由於容器已經提供,就不需要maven
重複地引入一遍:
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
- test: 單元測試依賴範圍,只在測試的時候生效,所以可以設置它的 scope 為 test,這樣,當項目打包發佈時,單元測試的依賴就不會跟着發佈。比如:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
- runtime: 運行時依賴範圍。對於測試和運行 classpath 有效,但在編譯主代碼時無效。典型的例子是 JDBC 驅動實現,項目主代碼的編譯只需要 JDK 提供的 JDBC 接口,只有在執行測試或者運行項目的時候才需要實現上述接口的具體 JDBC 驅動。所以,我們使用 JDBD 驅動時,可以定義成以下樣例:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.12</version> <scope>runtime</csope> </dependency>
4.3 排除依賴
如下 xml,原來的定義中已引入 commons-net
依賴,而 hermes-ftp
中又依賴了 commons-net
,為避免版本衝突,我們可以排除 hermes-ftp
中的 commons-net
依賴。
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.6</version> </dependency> <dependency> <groupId>com.nasus.greece.jupiter</groupId> <artifactId>hermes-ftp</artifactId> <version>1.1.0-SNAPSHOT</version> <!--排除 commons-net 依賴--> <exclusions> <exclusion> <artifactId>commons-net</artifactId> <groupId>commons-net</groupId> </exclusion> </exclusions> </dependency>
4.4 依賴傳遞
假設有如下項目關係:WebMavenDemo
項目依賴 JavaMavenService1
,JavaMavenService1
項目依賴 JavaMavenService2
。

項目關係
pom.xml 文件配置好依賴關係後,必須首先 mvn install 後,依賴的 jar 包才能使用。比如:
WebMavenDemo
的pom.xml
文件想能編譯通過,JavaMavenService1
必須mvn install
JavaMavenService
的pom.xml
文件想能編譯通過,JavaMavenService2
必須mvn install
傳遞性:

傳遞性
假設我們現在 JavaMavenService2
增加 spring-core
,那就會發現 WebMavenDemo
和 JavaMavenService1
也會自動的增加了這個 jar
包,這就是依賴的傳遞性。
注意:非
compile
範圍的依賴是不能傳遞的。
- 來源:cnblogs.com/hzg110/p/6936101.html
4.5 統一管理依賴版本
在上面介紹 pom 文件時,我們講過 properties
標籤,它還有一個作用就是限定依賴的 jar 包版本,它常用在父項目中指定版本號,那麼子項目用到該包就避免了版本不一致造成的依賴衝突,它的寫法是這樣的:

統一管理版本
五、build 配置
maven 打 war 包時,可能需要一些額外的配置,請參看以下 xml 文件:
<build> <!-- 項目的名字 --> <finalName>maven-test</finalName> <!-- 描述項目中資源的位置 --> <resources> <!-- 自定義資源1 --> <resource> <!-- 資源目錄 --> <directory>src/main/java</directory> <!-- 包括哪些文件參與打包 --> <includes> <include>**/*.xml</include> </includes> <!-- 排除哪些文件不參與打包 --> <excludes> <exclude>**/*.txt</exclude> <exclude>**/*.doc</exclude> </excludes> </resource> </resources> <!-- 設置構建時候的插件 --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.1</version> <configuration> <!-- 源代碼編譯版本 --> <source>1.8</source> <!-- 目標平台編譯版本 --> <target>1.8</target> </configuration> </plugin> <!-- 資源插件(資源的插件) --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.1</version> <executions> <execution> <phase>compile</phase> </execution> </executions> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- war插件(將項目打成war包) --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1</version> <configuration> <!-- war包名字 --> <warName>maven-test</warName> </configuration> </plugin> </plugins> </build>
六、使用 idea 搭建 maven 聚合工程
這個網上很多資料,不講了。留個鏈接。
- idea 搭建 maven 聚合工程參考:https://www.cnblogs.com/limn/p/9363416.html
-END-
如果看到這裡,你喜歡這篇文章的話,幫忙"轉發"或者點個"在看",行嗎?祝你們 2020 暴富。微信搜索「一個優秀的廢人」,關注後回復「1024」送你一套完整的 java 教程。