搞懂這7個(gè)Maven問(wèn)題蚯妇,帶你吊打面試官!(49)

01 10 17 19 22 38 42

在如今的互聯(lián)網(wǎng)項(xiàng)目開發(fā)當(dāng)中暂筝,特別是Java領(lǐng)域箩言,可以說(shuō)Maven隨處可見。Maven的倉(cāng)庫(kù)管理焕襟、依賴管理陨收、繼承和聚合等特性為項(xiàng)目的構(gòu)建提供了一整套完善的解決方案,可以說(shuō)如果你搞不懂Maven,那么一個(gè)多模塊的項(xiàng)目足以讓你頭疼务漩,依賴沖突就會(huì)讓你不知所措拄衰,甚至搞不清楚項(xiàng)目是如何運(yùn)行起來(lái)的....

OK,博主就曾經(jīng)被Maven“傷害”過(guò)饵骨,那么該專題的目的就是:徹底搞定Maven翘悉!

回想一下,當(dāng)你新到一家公司居触,安裝完JDK后就會(huì)安裝配置Maven(MAVEN_HOME妖混、path),很大可能性你需要修改settings.xml文件饼煞,比如你會(huì)修改本地倉(cāng)庫(kù)地址路徑源葫,比如你很可能會(huì)copy一段配置到你的settings.xml中(很可能就是私服的一些配置)。

接下來(lái)砖瞧,你會(huì)到IDEA或者Eclipse中進(jìn)行Maven插件配置息堂,然后你就可以在工程中的pom.xml里面開始添加<dependency>標(biāo)簽來(lái)管理jar包,在Maven規(guī)范的目錄結(jié)構(gòu)下進(jìn)行編寫代碼块促,最后你會(huì)通過(guò)插件的方式來(lái)進(jìn)行測(cè)試荣堰、打包(jar or war)、部署竭翠、運(yùn)行振坚。

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

1. 本地倉(cāng)庫(kù)斋扰?Maven到底有哪些倉(cāng)庫(kù)渡八?它們什么關(guān)系?

Maven倉(cāng)庫(kù)

本地倉(cāng)庫(kù)路徑配置

你要jar包传货,不可能每次都要聯(lián)網(wǎng)去下載吧屎鳍,多費(fèi)勁,所以本地倉(cāng)庫(kù)就是相當(dāng)于加了一層jar包緩存问裕,先到這里來(lái)查逮壁。如果這里查不到,那么就去私服上找粮宛,如果私服也找不到窥淆,那么去中央倉(cāng)庫(kù)去找,找到j(luò)ar后巍杈,會(huì)把jar的信息同步到私服和本地倉(cāng)庫(kù)中忧饭。

私服,就是公司內(nèi)部局域網(wǎng)的一臺(tái)服務(wù)器而已秉氧,你想一下眷昆,當(dāng)你的工程Project-A依賴別人的Project-B的接口,怎么做呢?沒(méi)有Maven的時(shí)候亚斋,當(dāng)然是copy Project-B jar到你的本地lib中引入作媚,那么Maven的方式,很顯然需要其他人把Project-B deploy到私服倉(cāng)庫(kù)中供你使用帅刊。因此私服中存儲(chǔ)了本公司的內(nèi)部專用的jar纸泡!不僅如此,私服還充當(dāng)了中央倉(cāng)庫(kù)的鏡像赖瞒,說(shuō)白了就是一個(gè)代理女揭!如何創(chuàng)建私服,可以關(guān)注Java技術(shù)棧微信公眾號(hào)栏饮,回復(fù):maven吧兔,即可獲取。

中央倉(cāng)庫(kù):該倉(cāng)庫(kù)存儲(chǔ)了互聯(lián)網(wǎng)上的jar袍嬉,由Maven團(tuán)隊(duì)來(lái)維護(hù)境蔼,地址是:http://repo1.maven.org/maven2/。

2. 關(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)常遇到這樣的場(chǎng)景弦叶,比如A服務(wù)依賴于B服務(wù),A和B同時(shí)開發(fā)妇多,B在開發(fā)中發(fā)現(xiàn)了BUG,修改后燕侠,將版本由1.0升級(jí)為2.0者祖,那么A必須也跟著在POM.XML中進(jìn)行版本升級(jí)。過(guò)了幾天后绢彤,B又發(fā)現(xiàn)了問(wèn)題七问,進(jìn)行修改后升級(jí)版本發(fā)布,然后通知A進(jìn)行升級(jí)...可以說(shuō)這是開發(fā)過(guò)程中的版本不穩(wěn)定導(dǎo)致了這樣的問(wèn)題茫舶。

Maven械巡,已經(jīng)替我們想好了解決方案,就是使用Snapshot版本,在開發(fā)過(guò)程中B發(fā)布的版本標(biāo)志為Snapshot版本讥耗,A進(jìn)行依賴的時(shí)候選擇Snapshot版本有勾,那么每次B發(fā)布的話,會(huì)在私服倉(cāng)庫(kù)中古程,形成帶有時(shí)間戳的Snapshot版本蔼卡,而A構(gòu)建的時(shí)候會(huì)自動(dòng)下載B最新時(shí)間戳的Snapshot版本!

3. 既然Maven進(jìn)行了依賴管理挣磨,為什么還會(huì)出現(xiàn)依賴沖突雇逞?處理依賴沖突的手段是?

依賴的版本茁裙?

首先來(lái)說(shuō)塘砸,對(duì)于Maven而言,同一個(gè)groupId同一個(gè)artifactId下晤锥,只能使用一個(gè)version掉蔬!

根據(jù)上圖的依賴順序,將使用1.2版本的jar查近。

現(xiàn)在眉踱,我們可以思考下了,比如工程中需要引入A霜威、B谈喳,而A依賴1.0版本的C,B依賴2.0版本的C戈泼,那么問(wèn)題來(lái)了婿禽,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)小問(wèn)題呢?能不能選擇高版本的進(jìn)行依賴么前酿?據(jù)了解患雏,Gradle就是version+策略)

現(xiàn)在,我們可以想想如何處理依賴沖突呢薪者?

想法1:要使用哪個(gè)版本纵苛,我們是清楚的,那么能不能不管如何依賴傳遞言津,都可以進(jìn)行版本鎖定呢攻人?

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

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

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

想法3:既然是最近依賴策略怀吻,那么我們就直接使用顯式依賴指定版本,那不就是最靠近項(xiàng)目的么初婆?Maven繼承與聚合蓬坡,這個(gè)你需要掌握。

使用<dependency>

4. 引入依賴的最佳實(shí)踐磅叛,提前發(fā)現(xiàn)問(wèn)題屑咳!

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

如果我們新加入一個(gè)依賴的話紫皇,那么先通過(guò)mvn dependency:tree命令形成依賴樹,看看我們新加入的依賴腋寨,是否存在傳遞依賴聪铺,傳遞依賴中是否和依賴樹中的版本存在沖突,如果存在多個(gè)版本沖突萄窜,利用上文的方式進(jìn)行解決铃剔!

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

簡(jiǎn)單Java工程目錄結(jié)構(gòu)

這里需要注意2點(diǎn):

第一:src/main下內(nèi)容最終會(huì)打包到Jar/War中,而src/test下是測(cè)試內(nèi)容查刻,并不會(huì)打包進(jìn)去番宁。

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

6. Maven的生命周期

Maven生命周期

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

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

clean:有問(wèn)題苇侵,多清理赶盔!

package:打成Jar or War包,會(huì)自動(dòng)進(jìn)行clean+compile

install:將本地工程Jar上傳到本地倉(cāng)庫(kù)

deploy:上傳到私服

7. 關(guān)于scope依賴范圍

既然榆浓,Maven的生命周期存在編譯于未、測(cè)試、運(yùn)行這些過(guò)程陡鹃,那么顯然有些依賴只用于測(cè)試烘浦,比如junit;有些依賴編譯用不到萍鲸,只有運(yùn)行的時(shí)候才能用到闷叉,比如mysql的驅(qū)動(dòng)包在編譯期就用不到(編譯期用的是JDBC接口),而是在運(yùn)行時(shí)用到的脊阴;還有些依賴握侧,編譯期要用到,而運(yùn)行期不需要提供嘿期,因?yàn)橛行┤萜饕呀?jīng)提供了品擎,比如servlet-api在tomcat中已經(jīng)提供了,我們只需要的是編譯期提供而已备徐。

總結(jié)來(lái)說(shuō):

compile:默認(rèn)的scope萄传,運(yùn)行期有效,需要打入包中坦喘。

provided:編譯期有效盲再,運(yùn)行期不需要提供,不會(huì)打入包中瓣铣。

runtime:編譯不需要答朋,在運(yùn)行期有效,需要導(dǎo)入包中棠笑。(接口與實(shí)現(xiàn)分離)

test:測(cè)試需要梦碗,不會(huì)打入包中。

system:非本地倉(cāng)庫(kù)引入蓖救、存在系統(tǒng)的某個(gè)路徑下的jar洪规。(一般不使用)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市循捺,隨后出現(xiàn)的幾起案子斩例,更是在濱河造成了極大的恐慌,老刑警劉巖从橘,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件念赶,死亡現(xiàn)場(chǎng)離奇詭異础钠,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)叉谜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門旗吁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人停局,你說(shuō)我怎么就攤上這事很钓。” “怎么了董栽?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵码倦,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我裆泳,道長(zhǎng)叹洲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任工禾,我火速辦了婚禮运提,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闻葵。我一直安慰自己民泵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布槽畔。 她就那樣靜靜地躺著栈妆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪厢钧。 梳的紋絲不亂的頭發(fā)上鳞尔,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音早直,去河邊找鬼寥假。 笑死,一個(gè)胖子當(dāng)著我的面吹牛霞扬,可吹牛的內(nèi)容都是我干的糕韧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼喻圃,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼萤彩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起斧拍,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤雀扶,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后肆汹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愚墓,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窍侧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了转绷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硼啤,死狀恐怖议经,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谴返,我是刑警寧澤煞肾,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站嗓袱,受9級(jí)特大地震影響籍救,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜渠抹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一蝙昙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梧却,春花似錦奇颠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至广鳍,卻和暖如春荆几,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赊时。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工吨铸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蛋叼。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓焊傅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親狈涮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狐胎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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

  • |-1-更新內(nèi)容[6.從倉(cāng)庫(kù)解析依賴的機(jī)制(重要)] 1Maven倉(cāng)庫(kù)作用 倉(cāng)庫(kù)用來(lái)存儲(chǔ)所有項(xiàng)目使用到構(gòu)件,在ma...
    zlcook閱讀 6,052評(píng)論 0 25
  • 來(lái)源:http://www.reibang.com/p/20b39ab6a88c 在如今的互聯(lián)網(wǎng)項(xiàng)目開發(fā)當(dāng)中,特...
    程序員BUG閱讀 1,281評(píng)論 1 47
  • 在 Maven 的術(shù)語(yǔ)中松却,倉(cāng)庫(kù)是一個(gè)位置(place)暴浦。Maven 倉(cāng)庫(kù)是項(xiàng)目中依賴的第三方庫(kù)溅话,這個(gè)庫(kù)所在的位置叫...
    41uLove閱讀 6,965評(píng)論 2 3
  • Maven的基本了解 什么是Maven? Maven就是Apache下的一個(gè)開源項(xiàng)目歌焦。它是用純java開發(fā)的飞几。是一...
    Bcome閱讀 2,814評(píng)論 0 7
  • 逅弈 轉(zhuǎn)載請(qǐng)注明原創(chuàng)出處,謝謝独撇! 以前的日子 以前我們寫代碼時(shí)屑墨,jar包都默認(rèn)放在一個(gè)叫 /lib 的目錄下,然后...
    逅弈閱讀 2,883評(píng)論 3 45