【maven】maven查看項目依賴並解決依賴沖突的問題


參考:https://timup.iteye.com/blog/1725898

參考:http://ian.wang/106.htm

參考:https://www.jianshu.com/p/7b4d3453bb14?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

參考:https://blog.csdn.net/u014515854/article/details/80407024

參考:http://www.mamicode.com/info-detail-2246820.html  (查看依賴沖突解決辦法)

maven學習筆記系列:https://blog.csdn.net/u011781521/article/details/79055605

一、問題

項目開發過程中,經常會遇到jar沖突,然后maven根據自己的規則進行沖突解決,導致項目在運行的過程中報錯。

1、maven自動解決依賴沖突的規則是什么?

2、如何查看當前項目的maven的依賴樹?

3、如何從依賴樹中找到自己預期的版本,是被那個jar給覆蓋了?

4、如何人工進行依賴沖突解決,達到使用目的?

 

 

二、解決問題

1、maven自動解決依賴沖突的規則是什么?

第一原則:路徑最近者優先

項目A有如下的依賴關系:

A->B->C->X(1.0)

A->D->X(2.0)

則該例子中,X的版本是2.0

 

第二原則:路徑相等,先聲明者優先

項目A有如下的依賴關系:

A->B->Y(1.0)

A->C->Y(2.0)

若pom文件中B的依賴坐標先於C進行聲明,則最終Y的版本為1.0

 

2、如何查看當前項目的maven依賴樹?

//進入項目的pom.xml文件的目錄下,運行如下命令
//這個是正常依賴的樹
mvn dependency:tree
//這個命令是查看maven是如何解決依賴沖突的依賴樹
mvn -Dverbose dependency:tree
//如果想將依賴樹打印到指定文件中,則命令如下
mvn -Dverbose  dependency:tree -Doutput=/Users/shangxiaofei/sxfoutput.txt
View Code

3、如何從依賴樹中找到自己預期的版本,是被那個jar給覆蓋了?

例子:

 

遞歸依賴的關系列的算是比較清楚了,每行都是一個jar包,根據縮進可以看到依賴的關系。
最后寫着compile的就是編譯成功的。
最后寫着omitted for duplicate的就是有jar包被重復依賴了,但是jar包的版本是一樣的。
最后寫着omitted for conflict with xxxx的,說明和別的jar包版本沖突了,而該行的jar包不會被引入。比如上面有一行最后寫着omitted for conflict with 3.4.6,那么該行的zookeeper:jar:3.4.8不會被引入,會引入3.4.6版本

最后寫着version managed from 2.3 ;omitted for duplicate ,表示最終使用commons-pool2最終會使用2.4.2,拒絕使用<dependencyManagement></dependencyManagement>中聲明的2.3版本

最后寫着version managed from 1.16.8 ;表示最終使用lombok:jar:1.16.22版本

 

4、如何人工進行依賴沖突解決,達到使用目的?

解決重復依賴和沖突的方法:

1,修改pom文件中兩個dependency元素的位置。如果兩個dependency都引用了一個jar包,但是版本不同,classloader只會加載jar包在pom文件中出現的第一個版本,以后出現的其他版本的jar包會被忽略。

不建議使用該方法,因為引用不同版本的jar包本身就是很危險的。

2,使用<exclusions>標簽來去掉某個dependency依賴中的某一個jar包或一堆jar包,<exclusion>中的jar包或者依賴的相關jar包都會被忽略,從而在兩個dependency都依賴某個jar包時,可以保證只使用其中的一個。

可以這么寫:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.8.3.2</version>
    <exclusions>
        <exclusion>
            <artifactId>guava</artifactId>
            <groupId>com.google.guava</groupId>
        </exclusion>
        <exclusion>
            <artifactId>spring</artifactId>
            <groupId>org.springframework</groupId>
        </exclusion>    
    </exclusions>
</dependency>
View Code

 

 

====================Maven坐標基礎知識===================

1、maven的依賴基礎

<dependency>    
<groupId>com.alibaba.share</groupId>    
<artifactId>test</artifactId>    
<version>1.4</version>    
</dependency>    
    
依賴庫命名規則:    
${groupId.part1}/${groupId.part2}/${version}    
例:com/alibaba/share/1.4    
    
依賴庫文件命名規則:    
${artifactId}-${version}-${classifier}.${type}    
例:test-1.4-source.jar    
    
注:classfier即分類器,多數的時候是用不到的,不過有寫情況需要,例:    
TestNG強制需要你提供分類器,以區別jdk14和jdk15    
<dependency>      
   <groupId>org.testng</groupId>      
   <artifactId>testng</artifactId>      
   <version>5.7</version>      
   <classifier>jdk15</classifier>      
</dependency>    
View Code

2、maven依賴范圍 

<dependency>    
      <groupId>junit</groupId>    
      <artifactId>junit</artifactId>    
      <version>3.8.1</version>    
      <scope>test</scope>    
 </dependency> 
View Code

上面的scope即約定依賴范圍。 
compile:默認值,一直可用,最后會被打包 
provided:編譯期間可用,不會被傳遞依賴,不會被打包。例:依賴於web容器中的提供的一個jar包,在編譯的時候需要加入依賴(web容器還沒有介入),運行的時候由web容器來提供。 
test:執行單元測試時可用,不會被打包,不會被傳遞依賴 
runtime:運行和測試時需要,但編譯時不需要 
system:不推薦使用 

 

3、maven依賴管理  

避免不同子模塊中依賴版本沖突 
在父pom中配置依賴 

<dependencyManagement>      
    <dependencies>      
     <dependency>      
       <groupId>mysql</groupId>      
       <artifactId>mysql-connector-java</artifactId>      
      <version>5.1.2</version>      
     </dependency>      
      ...      
   <dependencies>      
</dependencyManagement>    
View Code

在子pom中添加依賴 

<dependencies>      
   <dependency>      
    <groupId>mysql</groupId>      
    <artifactId>mysql-connector-java</artifactId>      
   </dependency>      
</dependencies>    
View Code

dependencyManagement實際上不會真正引入任何依賴,在子pom中添加之后才會。在父pom中配置了之后,子模塊只需使用簡單groupId和artifactId就能自動繼承相應的父模塊依賴配置。如果子pom中定義了version,則覆蓋management中的。 

 

4、可選依賴

<dependency>    
      <groupId>mysql</groupId>    
      <artifactId>mysql-connector-java</artifactId>    
      <version>1.5</version>    
      <optional>true</optional>    
    </dependency>   
View Code

5、依賴版本界限 

要求的依賴版本>=3.8且<4.0 

<version>[3.8,4.0)</version>   
View Code

要求的依賴版本<=3.8.1 

<version>[,3.8.1]</version>    
View Code

要求必須是3.8.1版本,如果不是的話會構建失敗,提示版本沖突。原來的寫法<version>3.8.1</version>的意思是所有版本都可以,但最好是3.8.1 

<version>[3.8.1]</version>   
View Code

 

6、排除依賴 

 依賴project-a但是排除掉對project-a中引入的project-b的依賴 

<dependency>    
  <groupId>org.sonatype.mavenbook</groupId>    
  <artifactId>project-a</artifactId>    
  <version>1.0</version>    
  <exclusions>    
    <exclusion>    
      <groupId>org.sonatype.mavenbook</groupId>    
      <artifactId>project-b</artifactId>    
    </exclusion>    
  </exclusions>    
</dependency>    
View Code

替換依賴 
直接使用上一步中的排除掉,然后添加要替換進來的依賴就可以了,沒有什么特殊的標志來標志這個是替換進來的。 

 

7、版本沖突仲裁

版本仲裁規則(在maven 2.2.1版本上測試驗證) 
• 按照項目總POM的DependencyManager版本聲明進行仲裁(覆蓋),但無警告。 
• 如無仲裁聲明,則按照依賴最短路徑確定版本。 
• 若相同路徑,有嚴格區間限定的版本優先。 
• 若相同路徑,無版本區間,則按照先入為主原則。 
View Code

 

8、依賴沖突解決辦法

查看那些jar包依賴了沖突包的命令

mvn dependency:tree -Dverbose -Dincludes=被依賴的包
View Code

 

剛才吹噓dependency:tree時,我用到了“無處遁形”,其實有時你會發現簡單地用dependency:tree往往並不能查看到所有的傳遞依賴。不過如果你真的想要看所有的,必須得加一個-Dverbose參數,這時就必定是最全的了。
全是全了,但顯示出來的東西太多,頭暈目眩,有沒有好法呢?當然有了,加上Dincludes或者Dexcludes說出你喜歡或討厭,dependency:tree就會幫你過濾出來:
引用
Dincludes=org.springframework:spring-tx
過濾串使用groupId:artifactId:version的方式進行過濾,可以不寫全啦,如:

mvn dependency:tree -Dverbose -Dincludes=asm:asm  

就會出來asm依賴包的分析信息:

[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ ridge-test ---
[INFO] com.ridge:ridge-test:jar:1.0.2-SNAPSHOT
[INFO] +- asm:asm:jar:3.2:compile
[INFO] \- org.unitils:unitils-dbmaintainer:jar:3.3:compile
[INFO]    \- org.hibernate:hibernate:jar:3.2.5.ga:compile
[INFO]       +- cglib:cglib:jar:2.1_3:compile
[INFO]       |  \- (asm:asm:jar:1.5.3:compile - omitted for conflict with 3.2)
[INFO]       \- (asm:asm:jar:1.5.3:compile - omitted for conflict with 3.2)
[INFO] ------------------------------------------------------------------------

對asm有依賴有一個直接的依賴(asm:asm:jar:3.2)還有一個傳遞進入的依賴(asm:asm:jar:1.5.3)

第二板斧:將不想要的傳遞依賴剪除掉

承上,假設我們不希望asm:asm:jar:1.5.3出現,根據分析,我們知道它是經由org.unitils:unitils-dbmaintainer:jar:3.3引入的,那么在pom.xml中找到這個依賴,做其它的調整:

    <dependency>  
        <groupId>org.unitils</groupId>  
        <artifactId>unitils-dbmaintainer</artifactId>  
        <version>${unitils.version}</version>  
        <exclusions>  
            <exclusion>  
                <artifactId>dbunit</artifactId>  
                <groupId>org.dbunit</groupId>  
            </exclusion>  
            <!-- 這個就是我們要加的片斷 -->  
            <exclusion>  
                <artifactId>asm</artifactId>  
                <groupId>asm</groupId>  
            </exclusion>  
        </exclusions>  
    </dependency>  


再分析一下,你可以看到傳遞依賴沒有了:


    [INFO]  
    [INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ ridge-test ---  
    [INFO] com.ridge:ridge-test:jar:1.0.2-SNAPSHOT  
    [INFO] \- asm:asm:jar:3.2:compile  
    [INFO] ------------------------------------------------------------------------  
    [INFO] BUILD SUCCESS  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM