Maven 虐我千百遍个唧,我待 Maven 如初戀

前言

在如今的互聯(lián)網(wǎng)項(xiàng)目開發(fā)當(dāng)中江解,特別是Java領(lǐng)域,可以說Maven隨處可見徙歼。Maven的倉庫管理犁河、依賴管理鳖枕、繼承和聚合等特性為項(xiàng)目的構(gòu)建提供了一整套完善的解決方案,可以說如果你搞不懂Maven桨螺,那么一個(gè)多模塊的項(xiàng)目足以讓你頭疼,依賴沖突就會(huì)讓你不知所措灭翔,甚至搞不清楚項(xiàng)目是如何運(yùn)行起來的.....OK魏烫,博主就曾經(jīng)被Maven“傷害”過,那么該專題的目的就是:徹底搞定Maven!

Thinking in Maven

回想一下呐赡,當(dāng)你新到一家公司罚舱,安裝完JDK后就會(huì)安裝配置Maven(MAVEN_HOME管闷、path),很大可能性你需要修改settings.xml文件窃肠,比如你會(huì)修改本地倉庫地址路徑包个,比如你很可能會(huì)copy一段配置到你的settings.xml中(很可能就是私服的一些配置)。

接下來冤留,你會(huì)到IDEA或者Eclipse中進(jìn)行Maven插件配置碧囊,然后你就可以在工程中的pom.xml里面開始添加<dependency>標(biāo)簽來管理jar包,在Maven規(guī)范的目錄結(jié)構(gòu)下進(jìn)行編寫代碼纤怒,最后你會(huì)通過插件的方式來進(jìn)行測試糯而、打包(jar or war)、部署泊窘、運(yùn)行熄驼。

上面描述了我們對Maven的一些使用方式,下面我們進(jìn)行一些思考:

本地倉庫烘豹?Maven到底有哪些倉庫瓜贾?它們什么關(guān)系?
Maven倉庫
本地倉庫路徑配

你要jar包携悯,不可能每次都要聯(lián)網(wǎng)去下載吧祭芦,多費(fèi)勁,所以本地倉庫就是相當(dāng)于加了一層jar包緩存憔鬼,先到這里來查龟劲。如果這里查不到胃夏,那么就去私服上找,如果私服也找不到咸灿,那么去中央倉庫去找构订,找到j(luò)ar后侮叮,會(huì)把jar的信息同步到私服和本地倉庫中避矢。

私服,就是公司內(nèi)部局域網(wǎng)的一臺服務(wù)器而已囊榜,你想一下审胸,當(dāng)你的工程Project-A依賴別人的Project-B的接口,怎么做呢卸勺?沒有Maven的時(shí)候砂沛,當(dāng)然是copy Project-B jar到你的本地lib中引入,那么Maven的方式曙求,很顯然需要其他人把Project-B deploy到私服倉庫中供你使用碍庵。因此私服中存儲了本公司的內(nèi)部專用的jar!不僅如此悟狱,私服還充當(dāng)了中央倉庫的鏡像静浴,說白了就是一個(gè)代理!

中央倉庫:該倉庫存儲了互聯(lián)網(wǎng)上的jar挤渐,由Maven團(tuán)隊(duì)來維護(hù)苹享,地址是:http://repo1.maven.org/maven2/

關(guān)于<dependency>的使用
依賴管理

其實(shí)這個(gè)標(biāo)簽揭示了jar的查找坐標(biāo):groupId浴麻、artifactId得问、version。

一般而言软免,我們可以到私服上輸入artifactId進(jìn)行搜索宫纬,或者到http://search.maven.org/http://mvnrepository.com/上進(jìn)行查找確定坐標(biāo)膏萧。

version分為開發(fā)版本(Snapshot)和發(fā)布版本(Release)漓骚,那么為什么要分呢?
在實(shí)際開發(fā)中向抢,我們經(jīng)常遇到這樣的場景认境,比如A服務(wù)依賴于B服務(wù),A和B同時(shí)開發(fā)挟鸠,B在開發(fā)中發(fā)現(xiàn)了BUG叉信,修改后,將版本由1.0升級為2.0艘希,那么A必須也跟著在POM.XML中進(jìn)行版本升級硼身。過了幾天后硅急,B又發(fā)現(xiàn)了問題,進(jìn)行修改后升級版本發(fā)布佳遂,然后通知A進(jìn)行升級...可以說這是開發(fā)過程中的版本不穩(wěn)定導(dǎo)致了這樣的問題营袜。

Maven,已經(jīng)替我們想好了解決方案丑罪,就是使用Snapshot版本荚板,在開發(fā)過程中B發(fā)布的版本標(biāo)志為Snapshot版本,A進(jìn)行依賴的時(shí)候選擇Snapshot版本吩屹,那么每次B發(fā)布的話跪另,會(huì)在私服倉庫中,形成帶有時(shí)間戳的Snapshot版本煤搜,而A構(gòu)建的時(shí)候會(huì)自動(dòng)下載B最新時(shí)間戳的Snapshot版本免绿!

既然Maven進(jìn)行了依賴管理,為什么還會(huì)出現(xiàn)依賴沖突擦盾?處理依賴沖突的手段是嘲驾?
依賴的版本

首先來說,對于Maven而言迹卢,同一個(gè)groupId同一個(gè)artifactId下辽故,只能使用一個(gè)version!

根據(jù)上圖的依賴順序婶希,將使用1.2版本的jar榕暇。

現(xiàn)在,我們可以思考下了喻杈,比如工程中需要引入A彤枢、B,而A依賴1.0版本的C筒饰,B依賴2.0版本的C缴啡,那么問題來了,C使用的版本將由引入A瓷们、B的順序而定业栅?這顯然不靠譜!如果A的依賴寫在B的依賴后面谬晕,將意味著最后引入的是1.0版本的C碘裕,很可能在運(yùn)行階段出現(xiàn)類(ClassNotFoundException)、方法(NoSuchMethodError)找不到的錯(cuò)誤(因?yàn)锽使用的是高版本的C)攒钳!

這里其實(shí)涉及到了2個(gè)概念:依賴傳遞(transitive)帮孔、Maven的最近依賴策略。

依賴傳遞:如果A依賴B,B依賴C文兢,那么引入A晤斩,意味著B和C都會(huì)被引入。

Maven的最近依賴策略:如果一個(gè)項(xiàng)目依賴相同的groupId姆坚、artifactId的多個(gè)版本澳泵,那么在依賴樹(mvn dependency:tree)中離項(xiàng)目最近的那個(gè)版本將會(huì)被使用。(從這里可以看出Maven是不是有點(diǎn)小問題呢兼呵?能不能選擇高版本的進(jìn)行依賴么兔辅?據(jù)了解,Gradle就是version+策略)

現(xiàn)在萍程,我們可以想想如何處理依賴沖突呢幢妄?

想法1:要使用哪個(gè)版本兔仰,我們是清楚的茫负,那么能不能不管如何依賴傳遞,都可以進(jìn)行版本鎖定呢乎赴?

使用<dependencyManagement> [這種主要用于子模塊的版本一致性中]

想法2:在依賴傳遞中忍法,能不能去掉我們不想依賴的?

使用<exclusions> [在實(shí)際中我們可以在IDEA中直接利用插件幫助我們生成]

想法3:既然是最近依賴策略榕吼,那么我們就直接使用顯式依賴指定版本饿序,那不就是最靠近項(xiàng)目的么?

使用<dependency>

引入依賴的最佳實(shí)踐羹蚣,提前發(fā)現(xiàn)問題原探!

在工程中,我們避免不了需要加一些依賴顽素,也許加了依賴后運(yùn)行時(shí)才發(fā)現(xiàn)存在依賴沖突在去解決咽弦,似乎有點(diǎn)晚!那么能不能提前發(fā)現(xiàn)問題呢胁出?

如果我們新加入一個(gè)依賴的話型型,那么先通過mvn dependency:tree命令形成依賴樹,看看我們新加入的依賴全蝶,是否存在傳遞依賴闹蒜,傳遞依賴中是否和依賴樹中的版本存在沖突,如果存在多個(gè)版本沖突抑淫,利用上文的方式進(jìn)行解決绷落!

Maven規(guī)范化目錄結(jié)構(gòu)

這里需要注意2點(diǎn):
第一:src/main下內(nèi)容最終會(huì)打包到Jar/War中,而src/test下是測試內(nèi)容始苇,并不會(huì)打包進(jìn)去砌烁。

第二:src/main/resources中的資源文件會(huì)COPY至目標(biāo)目錄,這是Maven的默認(rèn)生命周期中的一個(gè)規(guī)定動(dòng)作埂蕊。(想一想往弓,hibernate/mybatis的映射XML需要放入resources下疏唾,而不能在放在其他地方了)

Maven的生命周期

我們只需要注意一點(diǎn):執(zhí)行后面的命令時(shí),前面的命令自動(dòng)得到執(zhí)行函似。

實(shí)際上槐脏,我們最常用的就是這么幾個(gè):

  • clean:有問題,多清理撇寞!
  • package:打成Jar or War包顿天,會(huì)自動(dòng)進(jìn)行clean+compile
  • install:將本地工程Jar上傳到本地倉庫
  • deploy:上傳到私服
關(guān)于scope依賴范圍

既然,Maven的生命周期存在編譯蔑担、測試牌废、運(yùn)行這些過程,那么顯然有些依賴只用于測試啤握,比如junit鸟缕;有些依賴編譯用不到,只有運(yùn)行的時(shí)候才能用到排抬,比如mysql的驅(qū)動(dòng)包在編譯期就用不到(編譯期用的是JDBC接口)懂从,而是在運(yùn)行時(shí)用到的;還有些依賴蹲蒲,編譯期要用到番甩,而運(yùn)行期不需要提供,因?yàn)橛行┤萜饕呀?jīng)提供了届搁,比如servlet-api在tomcat中已經(jīng)提供了缘薛,我們只需要的是編譯期提供而已。

總結(jié)來說:
  • compile:默認(rèn)的scope卡睦,運(yùn)行期有效宴胧,需要打入包中。
  • provided:編譯期有效么翰,運(yùn)行期不需要提供牺汤,不會(huì)打入包中。
  • runtime:編譯不需要浩嫌,在運(yùn)行期有效檐迟,需要導(dǎo)入包中。(接口與實(shí)現(xiàn)分離)
  • test:測試需要码耐,不會(huì)打入包中追迟。
  • system:非本地倉庫引入、存在系統(tǒng)的某個(gè)路徑下的jar骚腥。(一般不使用)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敦间,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌廓块,老刑警劉巖厢绝,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異带猴,居然都是意外死亡昔汉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門拴清,熙熙樓的掌柜王于貴愁眉苦臉地迎上來靶病,“玉大人,你說我怎么就攤上這事口予÷χ埽” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵沪停,是天一觀的道長煤辨。 經(jīng)常有香客問我,道長牙甫,這世上最難降的妖魔是什么掷酗? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮窟哺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘技肩。我一直安慰自己且轨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布虚婿。 她就那樣靜靜地躺著旋奢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪然痊。 梳的紋絲不亂的頭發(fā)上至朗,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天,我揣著相機(jī)與錄音剧浸,去河邊找鬼锹引。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唆香,可吹牛的內(nèi)容都是我干的嫌变。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼躬它,長吁一口氣:“原來是場噩夢啊……” “哼腾啥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤倘待,失蹤者是張志新(化名)和其女友劉穎疮跑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凸舵,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祸挪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贞间。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贿条。...
    茶點(diǎn)故事閱讀 40,146評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖增热,靈堂內(nèi)的尸體忽然破棺而出整以,到底是詐尸還是另有隱情,我是刑警寧澤峻仇,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布公黑,位于F島的核電站,受9級特大地震影響摄咆,放射性物質(zhì)發(fā)生泄漏凡蚜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一吭从、第九天 我趴在偏房一處隱蔽的房頂上張望朝蜘。 院中可真熱鬧,春花似錦涩金、人聲如沸谱醇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽副渴。三九已至,卻和暖如春全度,著一層夾襖步出監(jiān)牢的瞬間煮剧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工将鸵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留勉盅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓咨堤,卻偏偏與公主長得像菇篡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子一喘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容

  • |-1-更新內(nèi)容[6.從倉庫解析依賴的機(jī)制(重要)] 1Maven倉庫作用 倉庫用來存儲所有項(xiàng)目使用到構(gòu)件驱还,在ma...
    zlcook閱讀 6,064評論 0 25
  • 在 Maven 的術(shù)語中嗜暴,倉庫是一個(gè)位置(place)。Maven 倉庫是項(xiàng)目中依賴的第三方庫议蟆,這個(gè)庫所在的位置叫...
    41uLove閱讀 6,995評論 2 3
  • Maven的基本了解 什么是Maven闷沥? Maven就是Apache下的一個(gè)開源項(xiàng)目。它是用純java開發(fā)的咐容。是一...
    Bcome閱讀 2,825評論 0 7
  • 逅弈 轉(zhuǎn)載請注明原創(chuàng)出處舆逃,謝謝! 以前的日子 以前我們寫代碼時(shí)戳粒,jar包都默認(rèn)放在一個(gè)叫 /lib 的目錄下路狮,然后...
    逅弈閱讀 2,888評論 3 45
  • 在2018年的最后一天,再次前往青城后山游覽蔚约。白雪皚皚奄妨,山路崎嶇,誰說四川沒有大雪漫天苹祟? 路上的積雪砸抛,由于被行人踩...
    一笑2019閱讀 298評論 0 3