最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Maven JAR包沖突問題排查及解決方案

 更新時(shí)間:2021年03月03日 08:39:42   作者:RobertoHuang  
這篇文章主要介紹了Maven JAR包沖突問題排查及解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

寫這篇文章的初衷是因?yàn)榻裉煸谑褂胢vn dependency:tree命令時(shí),突然想起一年前面試阿里的一道面試題。面試題是說(shuō)假設(shè)線上發(fā)生JAR包沖突,應(yīng)該怎么排查?我那時(shí)候的回答是IDEA有個(gè)Maven Helper的插件,可以幫忙分析依賴沖突,然后還有一種辦法是如果一個(gè)類import的時(shí)候提示兩個(gè)地方可導(dǎo)入,那就說(shuō)明有沖突?,F(xiàn)在回頭想想確實(shí)太不專業(yè)了,以下是一次JAR包沖突的一個(gè)比較正規(guī)的流程,是通過整理幾篇博客后總結(jié)的希望對(duì)大家也有幫助,如果有錯(cuò)誤的地方也歡迎指出

GitHub地址:https://github.com/RobertoHuang

JAR沖突產(chǎn)生的原因

   Pom.xml
   /  \
  B    C
 / \   / \
 X  Y  X  M

在以上依賴關(guān)系中項(xiàng)目除了會(huì)引入B、C還會(huì)引入X、Y、M的依賴包,但是如果B依賴的X版本會(huì)1.0而C依賴的X版本為2.0時(shí),那最后項(xiàng)目使用的到底是X的1.0版本還是2.0版本就無(wú)法確定了。這是就要看ClassLoader的加載順序,假設(shè)ClassLoader先加載1.0版本那就不會(huì)加載2.0版本,反之同理

使用mvn -Dverbose dependency:tree排查沖突

[INFO] +- org.apache.tomcat:tomcat-servlet-api:jar:7.0.70:compile
[INFO] +- org.apache.tomcat:tomcat-jsp-api:jar:7.0.70:compile
[INFO] | +- org.apache.tomcat:tomcat-el-api:jar:7.0.70:compile
[INFO] | \- (org.apache.tomcat:tomcat-servlet-api:jar:7.0.70:compile - omitted for duplicate)
[INFO] +- net.sf.jasperreports:jasperreports:jar:5.6.0:compile
[INFO] | +- (commons-beanutils:commons-beanutils:jar:1.8.0:compile - omitted for conflict with 1.8.3)
[INFO] | +- commons-collections:commons-collections:jar:3.2.1:compile
[INFO] | +- commons-digester:commons-digester:jar:2.1:compile
[INFO] | | +- (commons-beanutils:commons-beanutils:jar:1.8.3:compile - omitted for duplicate)
[INFO] | | \- (commons-logging:commons-logging:jar:1.1.1:compile - omitted for duplicate)

遞歸依賴的關(guān)系列的算是比較清楚了,每行都是一個(gè)jar包,根據(jù)縮進(jìn)可以看到依賴的關(guān)系

  • 最后寫著compile的就是編譯成功的
  • 最后寫著omitted for duplicate的就是有JAR包被重復(fù)依賴了,但是JAR包的版本是一樣的
  • 最后寫著omitted for conflict with xx的,說(shuō)明和別的JAR包版本沖突了,該行的JAR包不會(huì)被引入

該命令可配合-Dincludes和-Dexcludes進(jìn)行使用,只輸出自己感興趣/不感興趣的JAR
參數(shù)格式為:[groupId]:[artifactId]:[type]:[version]
每個(gè)部分(冒號(hào)分割的部分)是支持*通配符的,如果要指定多個(gè)格式則可以用,分割,如:

mvn dependency:tree -Dincludes=javax.servlet,org.apache.*

解決沖突,使用exclusion標(biāo)簽將沖突的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>

解決了沖突后的樹(解決沖突的策略是:就近原則,即離根近的依賴被采納)

查看運(yùn)行期類來(lái)源的JAR包

有時(shí)你以為解決了但是偏偏還是報(bào)類包沖突,典型癥狀是java.lang.ClassNotFoundException或Method不兼容等異常,這時(shí)你可以設(shè)置一個(gè)斷點(diǎn),在斷點(diǎn)處通過下面這個(gè)工具類來(lái)查看Class所來(lái)源的JAR包

public class ClassLocationUtils {
  public static String where(final Class clazz) {
    if (clazz == null) {
      throw new IllegalArgumentException("null input: cls");
    }
    URL result = null;
    final String clazzAsResource = clazz.getName().replace('.', '/').concat(".class");
    final ProtectionDomain protectionDomain = clazz.getProtectionDomain();
    if (protectionDomain != null) {
      final CodeSource codeSource = protectionDomain.getCodeSource();
      if (codeSource != null) result = codeSource.getLocation();
      if (result != null) {
        if ("file".equals(result.getProtocol())) {
          try {
            if (result.toExternalForm().endsWith(".jar") || result.toExternalForm().endsWith(".zip")) {
              result = new URL("jar:".concat(result.toExternalForm()).concat("!/").concat(clazzAsResource));
            } else if (new File(result.getFile()).isDirectory()) {
              result = new URL(result, clazzAsResource);
            }
          } catch (MalformedURLException ignore) {

          }
        }
      }
    }
    if (result == null) {
      final ClassLoader clsLoader = clazz.getClassLoader();
      result = clsLoader != null ? clsLoader.getResource(clazzAsResource) : ClassLoader.getSystemResource(clazzAsResource);
    }
    return result.toString();
  }
}

然后隨便寫一個(gè)測(cè)試設(shè)置好斷點(diǎn),在執(zhí)行到斷點(diǎn)出使用ALT+F8動(dòng)態(tài)執(zhí)行代碼,如

ClassLocationUtils.where(Logger.class)

即可馬上找到對(duì)應(yīng)的JAR,如果這個(gè)JAR不是你期望的就說(shuō)明是IDE緩存造成的,清除緩存后重試即可

到此這篇關(guān)于詳解Maven JAR包沖突問題排查及解決方案的文章就介紹到這了,更多相關(guān)Maven JAR包沖突 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 由@NotNull注解引出的關(guān)于Java空指針的控制

    由@NotNull注解引出的關(guān)于Java空指針的控制

    這是一些很容易學(xué)會(huì)的簡(jiǎn)單技術(shù),但是對(duì)于代碼質(zhì)量和健壯性來(lái)說(shuō)確實(shí)很重要。以我的經(jīng)驗(yàn),僅是第一個(gè)小技巧就已經(jīng)對(duì)改進(jìn)代碼質(zhì)量具有很大的作用了
    2016-09-09
  • Java高級(jí)特性基礎(chǔ)之反射五連問

    Java高級(jí)特性基礎(chǔ)之反射五連問

    反射賦予了我們?cè)谶\(yùn)行時(shí)分析類以及執(zhí)行類中方法的能力。通過反射你可以獲取任意一個(gè)類的所有屬性和方法,你還可以調(diào)用這些方法和屬性。本文就來(lái)和大家詳細(xì)聊聊Java中的反射,感興趣的可以了解一下
    2023-01-01
  • Java圖形化界面編程介紹

    Java圖形化界面編程介紹

    這篇文章主要介紹了Java圖形化界面編程,形化界面編程可以直接的看到每一步操作帶來(lái)的效果,相對(duì)于傳統(tǒng)編程盯著黑框框?qū)W起來(lái)是非常非常有意思的,想了解更多的小伙伴請(qǐng)參考下面文章的詳細(xì)內(nèi)容
    2022-01-01
  • Java數(shù)組與二維數(shù)組及替換空格實(shí)戰(zhàn)真題講解

    Java數(shù)組與二維數(shù)組及替換空格實(shí)戰(zhàn)真題講解

    數(shù)組對(duì)于每一門編程語(yǔ)言來(lái)說(shuō)都是重要的數(shù)據(jù)結(jié)構(gòu)之一,當(dāng)然不同語(yǔ)言對(duì)數(shù)組的實(shí)現(xiàn)及處理也不盡相同。Java?語(yǔ)言中提供的數(shù)組是用來(lái)存儲(chǔ)固定大小的同類型元素,這篇文章主要介紹了Java數(shù)組與二維數(shù)組及替換空格實(shí)戰(zhàn)真題講解
    2022-07-07
  • 如何定位java程序中占用cpu最高的線程堆棧信息

    如何定位java程序中占用cpu最高的線程堆棧信息

    這篇文章主要介紹了如何定位java程序中占用cpu最高的線程堆棧信息方法的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • java中double類型運(yùn)算結(jié)果異常的解決方法

    java中double類型運(yùn)算結(jié)果異常的解決方法

    下面小編就為大家?guī)?lái)一篇java中double類型運(yùn)算結(jié)果異常的解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2016-12-12
  • SpringBoot整合Swagger2的完整過程記錄

    SpringBoot整合Swagger2的完整過程記錄

    Swagger是一款RESTful接口的文檔在線自動(dòng)生成、功能測(cè)試功能框架,這篇文章主要給大家介紹了關(guān)于SpringBoot整合Swagger2的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • java 發(fā)送http和https請(qǐng)求的實(shí)例

    java 發(fā)送http和https請(qǐng)求的實(shí)例

    下面小編就為大家分享一篇java 發(fā)送http和https請(qǐng)求的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2018-01-01
  • idea中使用(Revert Commit)圖解

    idea中使用(Revert Commit)圖解

    這篇文章主要介紹了idea中使用(Revert Commit)圖解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 解決static類使用@Value獲取yml文件獲取不到的問題

    解決static類使用@Value獲取yml文件獲取不到的問題

    在靜態(tài)類中直接使用@Value注解無(wú)法獲取yml文件中的配置,解決方案是在工具類Utils中創(chuàng)建靜態(tài)的setter方法,并從外部類ServiceClass中調(diào)用這個(gè)方法來(lái)設(shè)置值,這種方法通過外部調(diào)用來(lái)間接設(shè)置靜態(tài)變量的值,從而成功讀取yml配置
    2024-09-09

最新評(píng)論

阳泉市| 尖扎县| 商河县| 阿瓦提县| 抚州市| 普定县| 侯马市| 平谷区| 镇江市| 青铜峡市| 嘉荫县| 南和县| 鄂托克旗| 轮台县| 称多县| 吉水县| 曲麻莱县| 章丘市| 银川市| 呼玛县| 雷山县| 鞍山市| 井冈山市| 安多县| 潜山县| 天台县| 虞城县| 安岳县| 榆中县| 前郭尔| 军事| 金湖县| 鞍山市| 吉水县| 大荔县| 鄂州市| 德阳市| 邹平县| 富平县| 松溪县| 前郭尔|