詳解Maven的架構,用法,坑點介紹的清清楚楚

點關注,不迷路;持續(xù)更新Java架構相關技術及資訊熱文?。。?/strong>

沒有Maven之前的日子

個人的一個小感受,學習一個新技術,應該以歷史的眼光開看待這個新技術出現(xiàn)的原因,以及幫我們解決了什么問題。我們來回憶一下沒有Maven的日子是怎么樣的?

開發(fā)一個項目,需要用別人寫好的jar包,我們先把開源的jar包下載下來放到項目的lib目錄下,并把這個目錄添加到CLASSPATH(告訴Java執(zhí)行環(huán)境,在哪些目錄下可以找到你要執(zhí)行的Java程序需要的類或者包)

我們下載了a.jar發(fā)現(xiàn)a.jar還需要依賴b.jar,結果又去把b.jar包下載下來開始運行

如果運氣夠好,我們的項目在添加完所有的依賴后,能正產運行了。如果運氣差點,還會遇到版本的問題,例如a.jar在調用b.jar的時候發(fā)現(xiàn)b.jar根本沒有這個方法,在別的版本中才有,現(xiàn)在好了,光找依賴和適配版本就能花上不少時間

而且我們往git上上傳代碼的時候,還必須把這些lib都上傳上去。別人下載我們的代碼時也必須把lib下載下來,這個真心耗費時間

這時候Maven作為Java世界的包管理工具出現(xiàn)了,當然Java世界還有其他包管理工具,例如gradle等。就像yum是Linux世界的包管理工具,webpack是前端世界的包管理工具一樣

Maven倉庫的種類

Maven找jar包的過程是這樣的,先在本地倉庫找,找不到再去私服(如果配置了的話),再找不到去中央倉庫(http://repo1.maven.org/maven2/,maven團隊負責維護)

從中央倉庫找到后,會在私服和本地倉庫放一份,從私服找到后也會在本地倉庫放一份

當你安裝在好了Maven以后,在conf目錄下有個settings.xml文件,這個里面配置的項很多,后文會詳細介紹這個配置文件。

<!--localRepository
|Thepathtothelocalrepositorymavenwillusetostoreartifacts.
|
|Default:${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->

在這個配置文件下有這樣一段話,說了Maven默認的本地倉庫地址為${user.home}/.m2/repository(當然你可以重新設置本地倉庫的地址,上面就是模板),我是window電腦,來看看這個目錄

看到有很多jar包被存到本地,當然如果你想配置私服也是在settings.xml上進行配置,隨便一搜很多教程,不再贅述

搭建私服好處多多,在一個公司內部可以開發(fā)一些公共的基礎組件放到私服上,方便其他同事使用

Maven的默認配置

一個Maven的項目的整體結構是這樣的

為什么一個Maven項目的文件結構是這種的呢?
這就不得不說到Maven的一個特性,約定優(yōu)于配置。

Maven默認配置了{project.basedir}/src/main/java為項目的源代碼目錄{project.basedir}/src/main/test為項目的測試代碼目錄
${project.basedir}/target為項目的編譯輸出目錄等

spring boot就是約定優(yōu)于配置的體現(xiàn),想想我們用spring mvc的時候還得配置視圖解析器,包的自動掃描,而用了spring boot框架,我們就完全不用再配置了

Maven項目詳解

安裝還是挺簡單的,我就不再介紹,我也沒有單獨下載,一般就用了Idea自帶的Maven了,下載完后目錄結構如下:

bin目錄
該目錄包含了mvn運行的腳本,這些腳本用來配置java命令,準備好classpath和相關的Java系統(tǒng)屬性,然后執(zhí)行Java命令。

boot目錄:
該目錄只包含一個文件,該文件為plexus-classworlds-2.5.2.jar。plexus-classworlds是一個類加載器框架,相對于默認的java類加載器,它提供了更加豐富的語法以方便配置,Maven使用該框架加載自己的類庫。

conf目錄:
該目錄包含了一個非常重要的文件settings.xml。直接修改該文件,就能在機器上全局地定制maven的行為,即對所有用戶都生效。一般情況下,我們更偏向于復制該文件至/.m2/目錄下(表示用戶家目錄,windows下~就是C:UsersPeng,Peng是小編的用戶名),然后修改該文件,在用戶級別定制Maven的行為。

lib目錄:
該目錄包含了所有Maven運行時需要的Java類庫,Maven本身是分模塊開發(fā)的,因此用戶能看到諸如maven-core-3.0.jar、maven-model-3.0.jar之類的文件,此外這里還包含一些Maven用到的第三方依賴如commons-cli-1.2.jar、commons-lang-2.6.jar等等。、

settings.xml配置文件詳解

我們來詳細說一下settings.xml這個文件,這個文件可以定制Maven的行為,上面已經說到settings.xml可以放在2個位置,~/.m2/setting.xml(默認沒有,需要我們自己復制)和${maven.home}/conf/setting.xml

這2個配置文件的加載順序為~/.m2/setting.xml>${maven.home}/conf/setting.xml,為了不影響他人,所以我們將conf下的settings.xml復制到家目錄,在用戶級別定制Maven的行為。

這個和配置環(huán)境變量有點類似,Windos和Linux都可以配置系統(tǒng)級別的環(huán)境變量和用戶級別的環(huán)境變量,這里單說一下Linux的吧,在/etc/profile里面配置的就是系統(tǒng)級別的環(huán)境變量,在~/.bash_profile里面配置的就是用戶級別的環(huán)境變量

各種配置項還是挺多的,設置鏡像倉庫(國內用阿里云的比較多),設置代理,不再贅述

  • maven常用命令 命令 描述 mvn -version 顯示版本信息 mvn clean 刪除target目錄 mvn compile 編譯src/main/java下的源代碼 mvn package 打包,在target下生成jar包或者war包 mvn test 執(zhí)行src/test/java下以Test開頭或者以Test結尾的類的測試用例 mvn install 打包,并把jar包或者war包復制到本地倉庫,供其他模塊使用 mvn deploy 將打包的文件發(fā)布到私服 mvn dependency:tree 打印出項目的整個依賴樹
  • 當然也可以連著使用
  • mvn clean package 清理打包
  • mvn clean package -DskipTests=true 清理打包,并跳過測試用例
  • mvn clean install 清理打包,并將jar包或者war包復制到本地倉庫

運行單測的時候也沒必要一個一個點測試方法,mvn test 一個命令跑完所有測試用例,
要注意的是只會執(zhí)行以Test開頭或者結尾的測試類,也沒必要自己寫測試類,我在推薦閱讀第一篇文章中演示了快速生成測試類的方法,可以去看看,生成的測試類都是以Test結尾的

mvn dependency:tree > show.txt 將依賴輸出重定向到文件中,方便查看

  • pom.xml詳解
  • groupId 公司域名倒過來
  • artifactId 功能命名
  • version 版本號

這三個維度確定一個jar包,就像用(x,y,z)坐標在三維空間中唯一確定一個點。

packaging 打包方式,jar,war,maven-plugin(開發(fā)maven插件)

scope詳解 參數(shù) 解釋 是否會被打入最終的jar包 compile 默認的scope 是 test 測試使用 否 provided 編譯需要 否 runtime 編譯不需要,運行時需要(接口與實現(xiàn)分離) 是 system 加載本地jar 否
類似如下這種,沒有指定scope,說明scope是compile

<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>

test是指在運行測試用例的時候才會用到,沒必要打入到最后的jar里面,所以你看到的測試框架的scope基本上都是test

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

provided,編譯的時候會用到,但不會被打入最后的jar包

例如想把spring boot項目以war包的形式放在tomcat中運行,首先得加入如下依賴

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>

或者你寫了一個放在Storm集群或者Flink集群上運行的任務,最后都要把Storm的依賴或者Flink的依賴設置成provided,因為集群上已經都有這些環(huán)境的jar包、

如果你用到lombok插件的話,你會發(fā)現(xiàn)lombok的Maven是如下形式,說明它只會編譯的時候會用到。

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
<scope>provided</scope>
</dependency>

我寫了如下一個測試類

@Data
publicclassTest{
    privateStringname;
    privateintage;
}

生成的class文件反編譯后的如下,驗證了我們的想法,編譯之后確實沒有必要再用lombok這個jar包

publicclassTest{
    privateStringname;
    privateintage;
    publicTest(){
    }
    publicStringgetName(){
        returnthis.name;
    }
    publicintgetAge(){
        returnthis.age;
    }
    publicvoidsetName(Stringname){
        this.name=name;
    }
    publicvoidsetAge(intage){
        this.age=age;
    }
}

runtime,運行時才會用到。例如,如果你的項目有對數(shù)據(jù)庫的操作,但沒有加入相應的JDBC的實現(xiàn)jar包,如mysql-connector-java,是可以編譯成功的,只有運行時才會報錯。所以你看到的JDBC實現(xiàn)的jar包scope為runtime,表明這個jar包在運行時才會用到

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
<scope>runtime</scope>
</dependency>

system,本地加載jar,當你和第三方公司合作,他們只是給了你一個jar包時,你可以有三種選擇

  • mvn install到本地倉庫
  • mvn deploy到私服
  • 指定jar包路徑,從本地加載,例如如下pom形式
<dependency>
<groupId>com.tievd.third</groupId>
<artifactId>arcvideo</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${
    basedir
}
/lib/face-api-1.0.jar</systemPath>
</dependency>

前文已經說到scope為system的依賴不會被打入最終的jar包,得通過配置插件等方式將依賴打入最終的jar包,所以這種方式一般很少使用。

依賴傳遞

假設我們現(xiàn)在有一個多模塊項目,依賴關系如圖,我們在st-web模塊中引入st-dal依賴時,st-common-lib這個依賴也會被我們引入,這個就是依賴傳遞,下表中列出了scope在依賴過程中發(fā)生的變化,列標題為被依賴的模塊的scope

compile test provided runtime compile compile - - runtime test test - - test provided provided - provided provided runtime runtime - - runtime 依賴仲裁

依賴仲裁就是當項目中引入的jar包,groupId (公司域名倒過來)和artifactId (功能命令)一樣,但是version不一樣,應該選用哪一個version?也經常被人叫做依賴沖突

最短路徑原則

假如說我們現(xiàn)在的項目依賴關系如圖?那么maven會選用st-common-lib的那個版本呢?

答案是1.1這個版本,st-web到st-common-lib(1.1)的距離為1,st-web到st-common-lib(1.0)的距離為2,選擇距離短的,即最短路徑原則

如何看依賴的距離關系呢?前文說過,執(zhí)行如下命令打印出全局的依賴樹,層級關系特別清楚

mvndependency:tree>show.txt

聲明優(yōu)先原則

項目依賴如圖,路徑一樣,會選用st-common-lib的哪個版本呢?這就得看你在pom文件中先聲明是哪個依賴,如果在pom.xml中,st-remote-invoker寫在前面,就會用1.0這個版本,如果st-dal寫在前面,則會用1.1這個版本

依賴排除

去掉間接引入的jar包

如不想用spring boot默認提供的log,想集成第三方的log時,或者說上面依賴仲裁的第二個例子中,只想用st-common-lib的1.1版本,就可以把1.0版本排除掉

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
  • 編號962,輸入編號直達本文

  • 輸入m獲取文章目錄

寫在最后

點關注,不迷路;持續(xù)更新Java架構相關技術及資訊熱文?。?!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容