亚洲农村老熟妇肥BBBB_无码人妻精品一区二区蜜桃色_精品亚洲AⅤ无码午夜在线观看_中文字幕熟妇人妻在线视频_囯产色无码精品视频免费

當(dāng)前位置: 首頁(yè) > 科技新聞 >

好機(jī)會(huì),我要幫女同事解決Maven沖突問(wèn)題

時(shí)間:2020-02-13 00:16來(lái)源:網(wǎng)絡(luò)整理 瀏覽:
任何一個(gè)故事起因最重要任何一個(gè)職業(yè),女生都有絕對(duì)的優(yōu)勢(shì)。更別提IT行業(yè)了,在部門中要是有女程序猿那肯定是香餑餑,備受呵護(hù)呀。之前有一次,一位
任何一個(gè)故事起因最重要

任何一個(gè)職業(yè),女生都有絕對(duì)的優(yōu)勢(shì)。更別提IT行業(yè)了,在部門中要是有女程序猿那肯定是香餑餑,備受呵護(hù)呀。


之前有一次,一位剛來(lái)的妹子遇到問(wèn)題了,畫(huà)風(fēng)頓時(shí)就變成上面的圖片了,群起而圍之,但是最后的結(jié)果并不理想,還是得我出馬(此處有點(diǎn)小吹牛)。

妹子遇到的是Jar包沖突的問(wèn)題,錯(cuò)誤信息是 Caused by: java.lang.ClassNotFoundException,看錯(cuò)誤要么就是缺少某個(gè)Jar包,要么就是沖突了。

其實(shí)在工作中經(jīng)常會(huì)遇到這種沖突的問(wèn)題,比如:Caused by:java.lang.NoSuchMethodError 這個(gè)異常信息也是沖突導(dǎo)致的,想要解決沖突問(wèn)題就必須得知道哪里沖突了(好像是廢話)。

大部分都是用Maven來(lái)管理依賴的Jar,今天這篇文章主要是講解如何解決Maven帶來(lái)的依賴沖突問(wèn)題。

Maven回顧Maven自述

Maven 是用于構(gòu)建和管理Java項(xiàng)目的工具。對(duì)于Java方向的來(lái)說(shuō),Maven幾乎都要接觸和使用。當(dāng)然也有其他的工具來(lái)代替Maven,比如Ant和Gradle。

之前有接觸過(guò)Grails構(gòu)建的Java Web項(xiàng)目,就是用Gradle來(lái)做依賴管理的。至于Ant也在剛工作的時(shí)候在一些老項(xiàng)目中有見(jiàn)到過(guò),后面幾乎沒(méi)見(jiàn)過(guò)了。

Maven文檔地址:https://maven.apache.org

使用Maven可以讓我們快速構(gòu)建一個(gè)新的項(xiàng)目,并且很方便的可以集成和管理多個(gè)三方的框架。當(dāng)我們需要某個(gè)框架時(shí)可以去搜索一下這個(gè)框架的信息,然后配置到你的項(xiàng)目中即可。

搜索地址:https://mvnrepository.com

比如我們想要使用Spring Boot,除了在Spring的文檔中獲取依賴的版本,也可以自己去搜索,選擇對(duì)應(yīng)的版本,如下圖:


可以看到默認(rèn)就是Maven的依賴方式,只需要將dependency整段內(nèi)容復(fù)制到項(xiàng)目的pom.xml文件中即可。右側(cè)還有很多其他的依賴方式,比如Gradle等。

Maven依賴傳遞

今天主要講下如何去解決Maven做依賴管理的時(shí)候Jar包沖突的問(wèn)題,在解決之前先來(lái)了解下基本的知識(shí)。


上圖展示了Maven的依賴傳遞性,首先是項(xiàng)目B中依賴了Spring和Guava兩個(gè)框架。然后項(xiàng)目A又依賴了項(xiàng)目B,所以項(xiàng)目A也會(huì)依賴Spring和Guava兩個(gè)框架。

依賴傳遞Jar包選擇邏輯

依賴性傳遞會(huì)導(dǎo)致項(xiàng)目中依賴很多其他版本的Jar,這種情況下怎么進(jìn)行Jar包的選擇呢?

有兩個(gè)規(guī)則:

不同距離,距離近優(yōu)先相同距離,前者優(yōu)先

如下圖所示,項(xiàng)目依賴了項(xiàng)目A和項(xiàng)目B,A和B分別依賴了Guava,但是從依賴層次來(lái)看,項(xiàng)目B的層次更淺,故Guava18.0會(huì)被優(yōu)先選擇。


當(dāng)距離相同的時(shí)候,就會(huì)優(yōu)先選擇定義在前面的,如下圖所示,項(xiàng)目A和項(xiàng)目B都分別依賴了Guava15.0和Guava18.0的版本,但是項(xiàng)目A的順序在項(xiàng)目B的前面,所以會(huì)優(yōu)先選擇Guava15.0版本。


通過(guò)依賴傳遞性經(jīng)常會(huì)導(dǎo)致Jar包沖突的問(wèn)題,比如下圖的項(xiàng)目A本身依賴了Guava15.0,然后又依賴了項(xiàng)目B,項(xiàng)目B中依賴了Guava18.0,這樣項(xiàng)目A就會(huì)同時(shí)依賴Guava15.0和Guava18.0。

如果剛好用到了高版本不兼容低版本的方法和類時(shí),就會(huì)出現(xiàn)選擇錯(cuò)誤,因?yàn)镸aven會(huì)根據(jù)依賴樹(shù)的深淺來(lái)選型淺的依賴,也就是15.0。


沖突案例

下面就是一個(gè)典型的Jar包沖突問(wèn)題,當(dāng)一個(gè)Jar有多個(gè)版本的時(shí)候,就會(huì)出現(xiàn)沖突。

錯(cuò)誤信息可以看到com.google.common.collect.FluentIterable.concat這個(gè)方法找不到,目前是從guava-18.0.jar中加載的,這種問(wèn)題我們改怎么解決呢?

Description:An attempt was made to call the method com.google.common.collect.FluentIterable.concat(Ljava/lang/Iterable;Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable; but it does not exist. Its class, com.google.common.collect.FluentIterable, is available from the following locations:    jar:file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar!/com/google/common/collect/FluentIterable.classIt was loaded from the following location:    file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jarAction:Correct the classpath of your application so that it contains a single, compatible version of com.google.common.collect.FluentIterable
解決思路之懸絲診脈

找出沖突的Jar,看看當(dāng)前項(xiàng)目中依賴了哪幾個(gè)版本

Eclipse

在Eclipse中可以雙擊pom文件,進(jìn)入Dependency視圖,輸入你要搜索的jar名稱進(jìn)行搜索,就可以看出當(dāng)前項(xiàng)目中哪些框架依賴了你搜索的jar,什么版本都能知道。


Idea

Idea中可以安裝maven helper插件來(lái)查看相關(guān)依賴信息,默認(rèn)選中Conflicts會(huì)展示當(dāng)前項(xiàng)目存在沖突的依賴,當(dāng)然我們也可以直接查看樹(shù)形的依賴關(guān)系去分析沖突。


Maven命令

不用不借助于開(kāi)發(fā)工具的插件,我們可以直接用Maven命令來(lái)查看當(dāng)前項(xiàng)目的依賴關(guān)系,命令行進(jìn)入到你要分析的項(xiàng)目目錄下,執(zhí)行下面的命令將分析結(jié)果保存到文件中:

mvn dependency:tree > tree.log

執(zhí)行完之后依賴的信息結(jié)構(gòu)如下:


搜索了下guava,發(fā)現(xiàn)在smjdbctemplate中依賴了18.0版本,這個(gè)框架是我自己基于jdbctemplate封裝的一個(gè)框架。


解決思路之察言觀色

其實(shí)很明顯,錯(cuò)誤信息已經(jīng)告訴我們18.0中找不到concat方法,所以18.0肯定是不能用的,通過(guò)前面的分析,找到了直接依賴guava.18.0.jar的是smjdbctemplate,解決辦法就是將smjdbctemplate中的guava排除掉。

<dependency>    <groupId>com.github.yinjihuan</groupId>    <artifactId>smjdbctemplate</artifactId>    <version>1.1</version>    <exclusions>        <exclusion>            <groupId>com.google.guava</groupId>            <artifactId>guava</artifactId>        </exclusion>    </exclusions></dependency>

還有就是根據(jù)依賴樹(shù)的深淺度來(lái)判斷當(dāng)前項(xiàng)目依賴的是哪個(gè)版本,如下圖:


18.0是最淺的,肯定是依賴它,其實(shí)在Eclipse里面直接查看Maven Dependencies就可以指定當(dāng)前項(xiàng)目依賴哪些框架和版本信息,如下圖:


當(dāng)我們排除掉18.0后再來(lái)看依賴的版本是20.0,如下圖:


根據(jù)依賴樹(shù)的深淺度,20.0和19.0都是一樣的層級(jí),但是20.0在19.0前面,所以優(yōu)先選擇20.0版本。

再來(lái)看項(xiàng)目中的pom文件,發(fā)現(xiàn)swagger的聲明順序在apollo的前面。


如果我們把順序調(diào)整一下,那么就會(huì)依賴19.0的版本。


總結(jié)

通過(guò)我仔細(xì)耐心的講解,妹子終于自己解決了遇到的問(wèn)題,后面的事你們就猜去吧。

這種問(wèn)題其實(shí)無(wú)法避免,當(dāng)你依賴的三方框架越多的時(shí)候,沖突的可能性就越大。碰到問(wèn)題的時(shí)候沉下心來(lái)仔細(xì)分析,借助于工具幫助你排查問(wèn)題。

當(dāng)然我們?cè)谧约喉?xiàng)目中去依賴三方的框架,也是要注意版本的問(wèn)題,特別是對(duì)于多模塊的項(xiàng)目,每個(gè)子模塊都去依賴不同的版本,這樣很容易出問(wèn)題,一般建議在父pom中dependencyManagement來(lái)統(tǒng)一管理版本,子模塊直接統(tǒng)一使用父pom中定義好的版本。

還有就是可以使用optional來(lái)設(shè)置可選依賴,比如說(shuō)你要封裝一個(gè)通用的模塊Common,這個(gè)模塊中有很多通用的功能,項(xiàng)目A依賴只需要使用功能A,項(xiàng)目B依賴只需要使用功能B。每個(gè)功能都依賴了三方的Jar,這個(gè)時(shí)候如果你不做任何處理,只要依賴了你這個(gè)通用的模塊Common,那么也就會(huì)間接依賴這兩個(gè)功能的第三方Jar。這個(gè)時(shí)候可以通過(guò)設(shè)置optional=true來(lái)解決這個(gè)問(wèn)題,我依賴了你的通用模塊Common,如果我要使用A功能,那么我必須顯示依賴A功能需要的三方依賴才可以。

推薦內(nèi)容