maven多模塊和依賴衝突問題彙總記錄

目錄

前言:

今天學習和總結了一下maven的相關知識點,發現一些比較基礎的東西竟然也會忘記,這裏對於一些平常工做中可能會遇到的問題進行了一下彙總。java

idea怎麼建立maven多module的項目

首先了解上面是多module?

一句話歸納就是:一個父模塊做爲版本控制多個子模塊,子模塊負責接入到父模塊當中做爲整個項目的過程。git

多Module管理項目的幾種方式:

  1. 按照單模塊拆分爲多個子模塊,好比將MVC三層架構拆分爲 xxx-service,xxx-dao,xxx-model,不過這種方式我的感受比較二,目前以業務模塊拆分比較多,遷移到微服務好比用springcloude或者dubbo 的時候很是好用。
  2. 按照業務模塊拆分,這種模式使用的比較多,也比較多見。

建立一個多module項目(idea2019.3.3版本)

建立一個父pom項目:

  1. 打開idea,選擇create new project

  1. 選擇maven項目,同時不選任何的預加載設置

  1. 父pom配置以下:

  1. 刪除src 目錄

建立子模塊,引入到父pom裏面

  1. 一樣右擊項目工程,選擇new module,而後選擇maven,這時候會出現父模塊以及對應的子模塊名稱

  1. 此時在父模塊裏面發現引入了子模塊的內容

子父模塊的區別:

父pom.xml文件內容:

<groupId>org.zxd</groupId>
<artifactId>taglib</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>

<modules>
    <module>taglib-core</module>
</modules>

分爲兩個部分,一個部分是父pom的聲明,包含gourpId,artifactId,打包方式必須是pom,由於使用了聚合模型,同時在父pom裏面指定版本號,子模塊不填寫version會默認使用父pom的version號github

<modules>
    <module>taglib-core</module>
</modules>

上面表示當前引入的子模塊內容web

子pom.xml文件內容:

<!-- 引用自父pom -->
<parent>
    <artifactId>taglib</artifactId>
    <groupId>org.zxd</groupId>
    <version>1.0.0</version>
</parent>
<!-- 打包方式爲jar包 -->
<packaging>jar</packaging>
<modelVersion>4.0.0</modelVersion>

<artifactId>taglib-core</artifactId>
<version>1.0.0</version>

子模塊之間進行互相的依賴

在下面的pom中能夠在任意的子模塊引入對應的父模塊依賴spring

注意因爲<parent>這個標籤會遞歸繼承,因此要注意子依賴不要和依賴引入不一樣版本的依賴,這樣容易形成衝突shell

<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-core</artifactId>
    <version>1.0.0</version>
    <!-- 這裏須要註釋掉編譯的做用域 -->
    <!--<scope>compile</scope>-->
</dependency>

將上面的項目改造爲spring-boot多模塊項目:

改造父pom文件:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

parent指向springboot-startedapache

子模塊只須要引入父pom的內容api

Spring boot maven plugin問題

在打包spring boot項目時,須要使用以下插件:springboot

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

若是在用maven構建多模塊項目時,不要將此插件放到parent pom中,不然若是有sub module不是spring boot應用,在打包時就會出錯。只將該插件添加到是spring boot項目的子模塊mybatis

MAVEN依賴衝突問題:

依賴的傳遞原則:

  1. 最短路徑原則
  2. 最早聲明原則

maven的依賴引入策略

最短路徑原則:

我有下面兩個依賴jar包,A和B,他們都引入了C這個依賴,這時候若是有以下的引用

A -> C(3.3)

B -> A(3.3)

B -> C(3.4)

此時若是把B打包,獲得版本號是3.4,可是若是B去掉C的依賴,那就是走A->C的傳遞依賴,很簡單

驗證:

  1. 我假設我有一個web包引入了common-lang3,版本是3.4的版本
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>
  1. 此時又引入了一個公用包,裏面也有這個引用:
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.3</version>
</dependency>
  1. 若是此時在本地引用3.4版本,那就是3.4的版本,不然就死3.3的版本,無論聲明順序誰先誰後

最早聲明原則:

若是兩個jar包的尋址路徑一致,那麼誰先優先聲明,先引入誰

驗證:

下面兩個依賴分配對應兩個module,引入模塊的這個模塊暫定爲 C 模塊。

<!-- 引入core包內容 -->
<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-core</artifactId>
    <version>1.0.0</version>
    <!--            <scope>compile</scope>-->
</dependency>
<!-- 引入db包的內容 -->
<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-db</artifactId>
    <version>1.0.0</version>
</dependency>

此時 taglib-core 中的依賴版本以下,暫定爲 A 模塊:

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
    <version>2.5.0</version>
</dependency>

taglib-db 中的依賴版本以下,暫定爲 B 模塊:

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
    <version>4.0.1</version>
</dependency>

此時將整個web項目打包,能夠看到web項目裏面的版本以下:

能夠很明顯的看到若是引入關係是這樣的:

C -> A,B

A -> curator-client 2.5

B -> curator-client 4.1

這樣的鏈路最終打包出來的效果是 C -> A -> curator-client 2.5

這樣也就形成了不少狀況下咱們編譯運行時徹底沒有問題的,甚至有可能打包都是正常的,可是到最後運行的時候忽然報錯,要謹防這種依賴版本的問題,好在通常公司的項目都有經理負責控制版本依賴,這種錯誤算是低級錯誤,可是在現在框架滿天飛的時代,依賴管理的版本控制問題依然須要注意!!!

如何解決依賴衝突的問題

鎖定版本法

通常狀況下咱們會在父pom文件裏面管理,可使用<dependencyManagement>這個這個標籤來管理全部子模塊的版本依賴,子模塊若是指定本身的版本,這裏發現打出來的包依然是父pom指定的版本,版本管理使用以下:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>4.1.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>

鎖定版本法能夠打破2個依賴傳遞的原則,優先級爲最高

版本鎖定能夠排除一些exclude標籤,不一樣模塊用不一樣版本的jar包自己也不符合規範,因此這種方式較爲穩妥

什麼狀況下會出現Jar包衝突問題

只有高版本Jar包不向下兼容,或者新增了某些低版本沒有的API纔有可能致使這樣的問題

如何查找和發現jar包衝突?

1. 利用idea的maven視圖工具

直接使用一個圖說明一下:

能夠經過這個工具查看依賴在哪一個模塊重複引用,同時若是有衝突會顯示紅線,這個視圖很是的直觀,能夠幫助依賴管理人員去處理依賴重複引用或者引用版本不一致的問題,進行<exclude>操做

2. Idea Maven Helper 插件

如何使用?

安裝完成以後,隨便找一個pom.xml文件,按照以下的圖例提示進行操做,對於衝突的內容,右擊exclude就能夠排除依賴:

排除完依賴以後,點擊左上角的Refresh UI 刷新一下UI的界面:

3. maven命令工具:

mvn dependency:tree -Dverbose,有時候若是咱們沒有idea的狀況下,可使用這個命令來處理,執行的結果參考以下:

PS: 此處必定不要省略 -Dverbose參數,要否則是 不會顯示被 忽略的包的
or:curator-client:jar:4.1.0:compile
[INFO] |  |  +- org.apache.zookeeper:zookeeper:jar:3.5.4-beta:compile
[INFO] |  |  |  +- commons-cli:commons-cli:jar:1.2:compile
[INFO] |  |  |  +- log4j:log4j:jar:1.2.17:compile
[INFO] |  |  |  +- org.apache.yetus:audience-annotations:jar:0.5.0:compile
[INFO] |  |  |  \- io.netty:netty:jar:3.10.6.Final:compile
[INFO] |  |  +- com.google.guava:guava:jar:20.0:compile
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.30:compile
[INFO] |  +- commons-codec:commons-codec:jar:1.15:compile
[INFO] |  +- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] |  +- commons-beanutils:commons-beanutils:jar:1.9.4:compile
[INFO] |  +- commons-configuration:commons-configuration:jar:1.10:compile
[INFO] |  |  \- commons-lang:commons-lang:jar:2.6:compile

整體上來講仍是比較直觀的,很是方便和好用。

如何寫一個乾淨依賴關係的POM文件

  • 儘可能在父POM中定義<dependencyManagement>,來進行本項目一些依賴版本的管理,這樣能夠從很大程度上解決必定的衝突
  • 最少依賴jar包原則
  • 使用mvn dependency:analyze-only命令用於檢測那些聲明瞭可是沒被使用的依賴,若有有一些是你本身聲明的,那儘可能去掉
  • 使用mvn dependency:analyze-duplicate命令用來分析重複定義的依賴,清理那些重複定義的依賴

dependency:analyze-only 命令

在idea - Terminal裏面,能夠看到對應的依賴被下載

執行完以後個人運行結果以下,這裏報錯的緣由是打包時候默認去阿里雲倉庫尋找依賴,這裏須要配置一下:

[ERROR] Failed to execute goal on project taglib-web: Could not resolve dependencies for project org.zxd:taglib-web:war:1.0.0: The following artifacts could not be resolved: org.zxd:
taglib-core:jar:1.0.0, org.zxd:taglib-db:jar:1.0.0: Failure to find org.zxd:taglib-core:jar:1.0.0 in http://maven.aliyun.com/nexus/content/repositories/central/ was cached in the loc
al repository, resolution will not be reattempted until the update interval of alimaven has elapsed or updates are forced -> [Help 1]

大體意思就是說再阿里雲倉庫找不到對應的依賴引入。

解決方式以下:

找到maven的安裝路徑下的apache-maven-3.6.3\conf下面的setting.xml,找到以下配置:

<!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ${user.home}/.m2/repository
  <localRepository>/path/to/local/repo</localRepository>
  -->
<!-- 這裏配置本地倉庫的位置 -->
  <localRepository>D:\soft\apache-maven-3.6.3\rep</localRepository>

此時從新執行一下:dependency:analyze-only 命令

[INFO] --- maven-dependency-plugin:3.1.2:analyze-only (default-cli) @ taglib-web ---
[WARNING] Unused declared dependencies found:
[WARNING]    org.zxd:taglib-core:jar:1.0.0:compile
[WARNING]    org.apache.commons:commons-lang3:jar:3.4:compile
[WARNING]    org.springframework.boot:spring-boot-starter-web:jar:2.4.0:compile
[WARNING]    org.springframework.boot:spring-boot-starter-test:jar:2.4.0:test
[WARNING]    org.neo4j.driver:neo4j-java-driver:jar:1.5.0:compile
[WARNING]    commons-codec:commons-codec:jar:1.10:compile
[WARNING]    commons-collections:commons-collections:jar:3.2.2:compile
[WARNING]    commons-beanutils:commons-beanutils:jar:1.9.4:compile
[WARNING]    commons-configuration:commons-configuration:jar:1.10:compile
[WARNING]    commons-fileupload:commons-fileupload:jar:1.3:compile
[WARNING]    commons-logging:commons-logging:jar:1.2:compile
[WARNING]    org.apache.httpcomponents:httpclient:jar:4.4.1:compile
[WARNING]    org.apache.poi:poi-ooxml:jar:3.17:compile
[WARNING]    org.mybatis:mybatis:jar:3.4.0:compile
[WARNING]    org.mybatis:mybatis-spring:jar:1.3.0:compile
[WARNING]    com.github.pagehelper:pagehelper:jar:5.1.2:compile

mvn dependency:analyze-duplicate 命令

[INFO] No duplicate dependencies found in <dependencies/> or in <dependencyManagement/>

若是沒有其餘信息,表明沒有重複依賴的引入

相關文章
相關標籤/搜索