自從用了這款項目構建神器后,領導開始對我刮目相看~
大家好,我是二哥呀!
今天來給大家介紹一款項目構建神器——Maven,不僅能幫我們自動化構建,還能夠抽象構建過程,提供構建任務實現(xiàn);它跨平臺,對外提供了一致的操作接口,這一切足以使它成為優(yōu)秀的、流行的構建工具,從此以后,再也不用擔心項目搞崩了。
由于公眾號的文章發(fā)布后不能修改,也沒辦法加個統(tǒng)一的目錄作為索引頁,所以我就把《Java 程序員進階之路》的系列文章開源到了 GitHub(點擊閱讀原文可以直接跳轉):
https://github.com/itwanger/toBeBetterJavaer
每天看著 star 數(shù)的上漲我心里非常的開心,希望越來越多的 Java 愛好者能因為這個開源項目而受益,而越來越多人的 star,也會激勵我繼續(xù)更新下去~
總結一下 Maven 的優(yōu)點,主要有以下 3 點:
依賴管理:Maven 能幫助我們解決軟件包依賴的管理問題,不再需要提交大量的 jar 包、引入第三方庫; 規(guī)范目錄結構:Maven 標準的目錄結構有助于項目構建的標準化,通過配置 profile 還可以根據(jù)不同的環(huán)境(開發(fā)環(huán)境、測試環(huán)境,生產(chǎn)環(huán)境)讀取不同的配置文件; 方便集成:能夠集成在 IDE 中更方便使用。
一、安裝 Maven
由于 JDK 是 Maven 安裝的前置條件,所以請使用 java -version 確認是否已經(jīng)安裝了 JDK:

我本人使用的是 macOS,所以可以有兩種安裝方式,一種官網(wǎng)下載,手動安裝;一種直接使用 brew 一鍵安裝。
我們先介紹官網(wǎng)下載,手動安裝,該方式同樣適用于 Windows 系統(tǒng),差別可參照 Maven 官網(wǎng)安裝教程:
http://maven.apache.org/install.html
1)一種官網(wǎng)下載,手動安裝
第一步,去官網(wǎng)下載 Maven 安裝包:
官網(wǎng)地址:http://maven.apache.org/download.cgi

很多初學者在官網(wǎng)下載的時候不知道選哪一個,這里做一下簡單的介紹。
bin(binary)代表由 Java 源文件編譯后的二進制 class 文件,src(source)代表Java 源文件。 一般情況下,選擇 bin 文件進行安裝就 OK 了;如果你想自己編譯,可選 src 版本。 tar.gz 壓縮格式適用于 Unix 操作系統(tǒng),zip 適用于 Windows 操作系統(tǒng);但不是絕對的。
第二步,解壓下載的安裝包,復制該路徑:

bin 目錄:該包含了 Maven 運行的所有腳本,用來配置 Java 命令,準備執(zhí)行環(huán)境,然后執(zhí)行 Java 命令。 boot 目錄:該目錄只包含了一個 plexus-classworlds-xxx-jar 文件,該文件是一個類加載器框架,相當于默認的 Java 類加載器,提供了更加豐富的語法以便配置,Maven 使用該加載器加載自己的類庫。 conf 目錄:該目錄包含了一個非常重要的文件 settings.xml。可以直接修改該文件,用來全局定制 Maven 的行為;也可以復制該文件到 ~/.m2/目錄下(~表示用戶目錄),修改該文件可以在用戶范圍內定制 Maven 的行為。lib 目錄:該目錄包含了Maven運行時所需要的 Java 類庫,包括Maven 依賴的第三方類庫,比如 slf4j-api.jar。

第三步,配置環(huán)境變量
打開終端,輸入 vim ~/.bash_profile 命令打開 bash_profile 文件:

bash_profile 文件用于配置環(huán)境變量和啟動程序,詳細介紹可參照:
https://www.cnblogs.com/kevingrace/p/8072860.html
在文件中添加設置環(huán)境變量的命令:
export?M2_HOME=/Users/maweiqing/cmower/save/apache-maven-3.8.3
export?PATH=${PATH}:${M2_HOME}/bin

保存后退出,可以執(zhí)行 source ~/.bash_profile 使配置生效:

第四步,查看配置是否生效
輸入 mvn -v 命令,如果輸出以下內容,表示配置成功:

如未生效,可再開一個終端窗口嘗試 mvn -v 命令。
2)brew 一鍵安裝
第一步,使用 brew install maven 命令一鍵安裝,并自動配置環(huán)境變量
第二步,使用 mvn -v 命令查看版本
二、Maven 配置文件大盤點
Maven 是基于 POM(Project Object Model) 進行的,項目的所有配置都會放在 pom.xml 文件中,包括項目的類型、名字,依賴關系,插件定制等等。
"1.0"?encoding="UTF-8"?>
"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">
????4.0.0
????com.itwanger
????MavenDemo
????0.0.1-SNAPSHOT
????MavenDemo
第一行是XML頭,指定了該xml文檔的版本和編碼方式。 project 是根元素,聲明了一些POM相關的命名空間及xsd元素。 modelVersion指定了當前POM的版本,對于Maven 3來說,值只能是4.0.0。 groupId定義了項目屬于哪個組織,通常是組織域名的倒序,比如說我的域名是 itwanger.com,所以groupId就是 com.itwanger。 artifactId定義了項目在組織中的唯一ID。 version指定了項目當前的版本,SNAPSHOT意為快照,說明該項目還處于開發(fā)中。 name 聲明了一個對于用戶更為友好的項目名稱。
groupId、artifactId和version這三個元素定義了一個項目的基本坐標,在Maven的世界里,任何的jar和pom都是以基于這些坐標進行區(qū)分的。
...
????
????????實際項目
?????模塊
?????版本
?????<type>依賴類型type>
?????依賴范圍
?????依賴是否可選
?????
?????
?????????
???????????…
??????????…
???????
?????
??
...
dependencies 可以包含一個或者多個dependency元素,以聲明一個或者多個項目依賴。 grounpId、artifactId和version 組成了依賴的基本坐標。 type 指定了依賴的類型,默認為 jar。 scope 指定了依賴的范圍(詳情見下面依賴范圍部分)。 optional 標記了依賴是否是可選的(詳情見下面依賴可選部分)。 exclusions 用來排除傳遞性依賴(詳情見下面依賴排除部分)。
依賴范圍有以下幾種:
compile,默認的依賴范圍,表示依賴需要參與當前項目的編譯,后續(xù)的測試、運行周期也參與其中,是比較強的依賴。 test,表示依賴僅僅參與測試相關的工作,包括測試代碼的編譯和運行。比較典型的如 junit。 runntime,表示依賴無需參與到項目的編譯,不過后期的測試和運行需要其參與其中。 provided,表示打包的時候可以不用包進去,別的容器會提供。和 compile 相當,但是在打包階段做了排除的動作。 system,從參與程度上來說,和 provided 類似,但不通過 Maven 倉庫解析,可能會造成構建的不可移植,要謹慎使用。

關于傳遞性依賴:
比如一個account-email項目為例,account-email有一個compile范圍的spring-code依賴,spring-code有一個compile范圍的commons-logging依賴,那么commons-logging就會成為account-email的compile的范圍依賴,commons-logging是account-email的一個傳遞性依賴:

有了傳遞性依賴機制,在使用Spring Framework的時候就不用去考慮它依賴了什么,也不用擔心引入多余的依賴。Maven會解析各個直接依賴的POM,將那些必要的間接依賴,以傳遞性依賴的形式引入到當前的項目中。
關于依賴可選:

項目中A依賴B,B依賴于X和Y,如果所有這三個的范圍都是compile的話,那么X和Y就是A的compile范圍的傳遞性依賴,但是如果我想X、Y不作為A的傳遞性依賴,不給它用的話,可以按照下面的方式配置可選依賴:
??
????4.0.0 ??
????com.itwanger ??
????project-b ??
????1.0.0 ??
??????
??????????
????????????mysql ??
????????????mysql-connector-java ??
????????????5.1.10 ??
????????????true ??
???????? ??
??????????
????????????postgresql ??
????????????postgresql??
????????????8.4-701.jdbc3 ??
????????????true ??
???????? ??
???? ??
關于依賴排除:
有時候你引入的依賴中包含你不想要的依賴包,你想引入自己想要的,這時候就要用到排除依賴了,比如下圖中spring-boot-starter-web自帶了logback這個日志包,我想引入log4j2的,所以我先排除掉logback的依賴包,再引入想要的包就行了。
?org.springframework.boot
?spring-boot-starter-web
?2.5.6
?
??
???org.springframework.boot
???spring-boot-starter-logging
??
?
?org.springframework.boot
?spring-boot-starter-log4j2
?2.5.6
聲明exclustion的時候只需要groupId和artifactId,不需要version元素,因為groupId和artifactId就能唯一定位某個依賴。
三、Maven 倉庫
在 Maven 的術語中,倉庫是一個位置(place),項目中依賴的第三方庫以及插件(可統(tǒng)稱為構件),都放在這里。所有的 Maven 項目都可以共享這個倉庫,只需要根據(jù)依賴的坐標,就可以在需要的時候找到倉庫中的依賴,并使用它們。
舉個例子,項目中使用了分頁插件的依賴:
??????com.github.pagehelper
??????pagehelper-spring-boot-starter
??????1.1.0
那么它對應的倉庫路徑是這樣的:

倉庫可以以下幾種:

1)本地倉庫
當Maven在執(zhí)行編譯或測試時,如果需要使用依賴文件,它總是基于坐標使用本地倉庫的依賴文件。
默認情況下,不管是Window還是macOS,或者是 Linux,每個用戶都會在自己的用戶目錄下有一個路徑名為 .m2/repository/ 的倉庫目錄。
如果你想自定義本地倉庫目錄地址,可以編輯文件~/.m2/settings.xml,設置localRepository元素的值為你想要的倉庫地址,例如:
/path/to/local/repo
如果找不到 ~/.m2/settings.xml 的話,可以到 Maven 的安裝目錄(前文提到的 conf 目錄)下去拷貝。
2)遠程倉庫
默認情況下,本地倉庫是被注釋掉的,也就是空的,那么就必須得給 Maven 配置一個可用的遠程倉庫,否則 Maven 在 build(構建)的時候就無法去下載依賴。
中央倉庫就是這樣一個可用的遠程倉庫,里面包含了這個世界上絕大多數(shù)流行的開源 Java 類庫,以及源碼、作者信息、許可證信息等等。
不過,默認的中央倉庫訪問速度比較慢,通常我們會選擇使用阿里的 Maven 遠程倉庫。
?
??ali-maven
??http://maven.aliyun.com/nexus/content/groups/public
??
???true
??
??
???true
???always
???fail
??
?
repositories 可以包含一個或者多個repository元素,以聲明一個或者多個倉庫。 id,倉庫聲明的唯一id,需要注意的是,Maven自帶的中央倉庫使用的id為central,如果其他倉庫也使用了該id,就會覆蓋中央倉庫的配置。 url,指向了倉庫的地址。 releases和snapshots,用來控制Maven對于發(fā)布版構件和快照版構件的下載權限。 enabled子元素為 true 時表示可以從倉庫下載發(fā)布版構件和快照版構件。 updatePolicy 子元素用來配置Maven從遠處倉庫檢查更新的頻率。 默認值是daily,表示每天檢查一次; 可選值 never 表示從不檢查; 可選值always表示每次構建時檢查更新; 可選值interval表示每隔X分鐘檢查一次更新(X為任意整數(shù))。 checksumPolicy 子元素用來配置Maven檢查校驗的策略。在下載構件的時候,Maven會去校驗,如果校驗失敗, 當checksumPolicy的值為默認的warn時,Maven會在執(zhí)行構建時輸出警告信息; 值為fail 時,Maven遇到校驗錯誤就讓構建失敗; 值為ignore時,Maven將完全忽略校驗。
搭建遠程倉庫的另外一個目的是方便部署我們自己的項目構件至遠程倉庫供其他團隊成員使用,這時候需要配置distributionManagement元素:
????????
????????????releases
????????????public
????????????http://59.50.95.66:8081/nexus/content/repositories/releases
????????
????????
????????????snapshots
????????????Snapshots
????????????http://59.50.95.66:8081/nexus/content/repositories/snapshots
????????
repository表示發(fā)布版本構件的倉庫。 snapshotRepository 表示快照版本(開發(fā)測試用)的倉庫。 這兩個元素都需要配置id、name和url,id為遠程倉庫的唯一標識,name是為了方便閱讀,url表示倉庫的地址。
配置好了以后運行命令 mvn clean deploy,Maven就會將項目部署到對應的遠程倉庫。項目是快照還是發(fā)布版本通過之前遠程倉庫配置項中的 releases 和 snapshots 來區(qū)分。
3)倉庫鏡像
如果倉庫X可以提供倉庫Y存儲的所有內容,那么就可以認為X是Y的一個鏡像。通常我們會在 settings.xml 文件中添加阿里云鏡像:
????
??????alimaven
??????aliyun?maven
??????http://maven.aliyun.com/nexus/content/groups/public/
??????central ????????
????
??
其中 mirrorOf 元素的可選項有:
,匹配所有遠程倉庫。* ,匹配所有遠程倉庫,使用localhost的除外,使用external:* file://協(xié)議的除外。也就是說,匹配所有不在本機上的遠程倉庫。,匹配倉庫repo1和repo2,使用逗號分隔多個遠程倉庫。repo1,repo2 ,匹配所有遠程倉庫,repo1除外,使用感嘆號將倉庫從匹配中排除。*,!repo1
上例中 表示任何對于中央倉庫的請求都會轉至該鏡像。
4)私服
私服是一種特殊的遠程倉庫,它架設在局域網(wǎng)內中,私服代理廣域網(wǎng)上的遠程倉庫,供局域網(wǎng)內的Maven用戶使用。當Maven需要下載構件的時候,先從私服請求,如果私服上不存在該構件,則從外部的遠程倉庫下載,并緩存到私服上。
私服有以下好處:
節(jié)省外網(wǎng)訪問速度 加速Maven構建 提高穩(wěn)定性,增強控制 降低中央倉庫的負荷
5)倉庫服務搜索
推薦 2 個提供倉庫搜索服務的網(wǎng)站:
Sonatype Nexus:https://repository.sonatype.org/ MVNrepository:http://mvnrepository.com/
四、使用 Maven
1)Maven 常見命令
mvn clean:表示運行清理操作(會默認把target文件夾中的數(shù)據(jù)清理)。mvn clean compile:表示先運行清理之后運行編譯,會將代碼編譯到target文件夾中。mvn clean test:運行清理和測試。mvn clean package:運行清理和打包。mvn clean install:運行清理和安裝,會將打好的包安裝到本地倉庫中,以便其他的項目可以調用。mvn clean deploy:運行清理和發(fā)布(發(fā)布到私服上面)。
2)Maven 常用 POM 屬性
${project.build.sourceDirectory}:項目的主源碼目錄,默認為src/main/java/${project.build.testSourceDirectory}:項目的測試源碼目錄,默認為/src/test/java/${project.build.directory}:項目構建輸出目錄,默認為target/${project.build.outputDirectory}:項目主代碼編譯輸出目錄,默認為target/classes/${project.build.testOutputDirectory}:項目測試代碼編譯輸出目錄,默認為target/testclasses/${project.groupId}:項目的 groupId.${project.artifactId}:項目的 artifactId.${project.version}:項目的 version,于${version}等價${project.build.finalName}:項目打包輸出文件的名稱,默認為${project.artifactId}${project.version}
3)Intellij IDEA 配置 Maven

4)Maven 常用插件
插件是Maven的核心功能,它允許在多個項目中重用通用的構建邏輯。插件可用于:
創(chuàng)建jar文件, 創(chuàng)建war文件, 編譯代碼, 單元測試代碼, 創(chuàng)建項目文檔等。
常用的插件有:
maven-antrun-plugin,讓用戶在 Maven 項目中運行 Ant 任務。用戶可以直接在該插件的配置以 Ant 的方式編寫 Target,然后交給該插件的 run 目標去執(zhí)行。在一些由 Ant 往 Maven 遷移的項目中,該插件尤其有用。此外當你發(fā)現(xiàn)需要編寫一些自定義程度很高的任務,同時又覺得 Maven 不夠靈活時,也可以以 Ant 的方式實現(xiàn)之。maven-antrun-plugin 的 run 目標通常與生命周期綁定運行。 maven-assembly-plugin,制作項目分發(fā)包,該分發(fā)包可能包含了項目的可執(zhí)行文件、源代碼、readme、平臺腳本等等。maven-assembly-plugin 支持各種主流的格式如 zip、tar.gz、jar 和 war 等,具體打包哪些文件是高度可控的,例如用戶可以按文件級別的粒度、文件集級別的粒度、模塊級別的粒度、以及依賴級別的粒度控制打包,此外,包含和排除配置也是支持的。maven-assembly-plugin 要求用戶使用一個名為assembly.xml的元數(shù)據(jù)文件來表述打包,它的 single 目標可以直接在命令行調用,也可以被綁定至生命周期。 maven-help-plugin,一個小巧的輔助工具,最簡單的help:system可以打印所有可用的環(huán)境變量和 Java 系統(tǒng)屬性。help:effective-pom和help:effective-settings最為有用,它們分別打印項目的有效 POM 和有效 settings,有效 POM 是指合并了所有父 POM(包括 Super POM)后的 XML,當你不確定 POM 的某些信息從何而來時,就可以查看有效 POM。 maven-javadoc-plugin,javadoc 插件,將源碼的 javadoc 發(fā)布出去。
希望你能在閱讀完本篇文章后對 Maven 有一個初步的了解和掌握,并將這些技能在項目的實戰(zhàn)中加以練習,以達到項目工程化的要求。
參考鏈接:
嘟嘟MD:http://tengj.top/2018/01/01/maven/?
杭建:《Java 工程師修煉之道》
許曉斌:https://www.infoq.cn/article/2011/04/xxb-maven-7-plugin
這是《Java 程序員進階之路》專欄的第 71 篇(記得點擊「閱讀原文」鏈接去點個 star 哦)。該專欄風趣幽默、通俗易懂,對 Java 愛好者極度友好和舒適??,內容包括但不限于 Java 基礎、Java 集合框架、Java IO、Java 并發(fā)編程、Java 虛擬機、Java 企業(yè)級開發(fā)(SSM、Spring Boot)等核心知識點。
點擊上方名片,發(fā)送消息「03」 就可以獲取最新版《Java 程序員進階之路》PDF 版了,讓我們一起成為更好的 Java 工程師吧,沖!

