热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

解决maven版本冲突——mavenshade

目录背景maven-shade-plugin介绍解决问题1.环境准备2.解决方案3.引入依赖一些需要注意的坑背景在maven项目中引入新的第三方组件时,组

目录

背景

maven-shade-plugin介绍

解决问题

1.环境准备

2.解决方案

3.引入依赖

一些需要注意的坑



背景

        在maven项目中引入新的第三方组件时,组件中的依赖可能会与项目已有组件依赖的jar包(其他组件)发生冲突。

        比如新添加的milvus-sdk-java 是2.0.3,依赖的 protobuf-java 版本得是3.12.0;而项目中已有的hbase版本是1.2.0.x,依赖的 protobuf-java 版本得是2.5.0。 那么此时就会产生一下两种情况:


  • 如果用三方组件的高版本httpclient覆盖原有的低版本httpclient,有可能会导致原来项目启动运行失败。即使高版本兼容低版本,也不能允许开发人员有这样高风险的操作
  • 如果在三方maven依赖中对其对依赖的httpclient在引入时使用进行排除,使三方组件使用项目中的低版本httpclient,此时可能会因为版本不一致导致三方组件无法使用

比如 直接运行会报错:

java.lang.NoClassDefFoundError: Could not initialize class org.apache.hadoop.hbase.util.ByteStringer

缘由:

        在HBase 1.2.X版本及以前的版本HBase是强依赖于protobuf-2.5.0,若是在依赖中引入3.0.0以上版本的protobuf,其中一个类LiteralByteString从包内可访问可继承的 变为静态内部类,不可被继承。导致初始化失败。【还有其他的原因,比如方法的签名改变了等等】

      在这样的情况下我们应当如何保证不影响项目原有依赖版本的情况下正常使用三方组件呢?此时可以考虑使用maven-shade-plugin插件:


maven-shade-plugin介绍

maven-shade-plugin在maven官方网站中提供的一个插件,官方文档中定义其功能如下:


This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.


简单来说就是将依赖的包在package阶段一起打入jar包中,以及对依赖的jar包进行重命名从而达到隔离的作用。这里为了解决上面的问题我们主要使用第二个功能特性,使得相同依赖不同版本达到共存的目的。


解决问题


1.环境准备

      事实上,集成度比较高的jar包,里面的依赖链又大又深,一般会有多个问题。比如上述例子中除了protobuf-java,还会有 guava、grpc-core等jar包也会存在版本冲突。但本文重点讲如何解决问题,就挑其中一个具体讲解:


com.google.protobufprotobuf-java2.15.0

新引入一个三方依赖  milvus-sdk-java,该依赖使用3.12.0版本的 protobuf-java


com.google.protobufprotobuf-java3.12.0


2.解决方案

       因为项目中没有直接操作 protobuf-java, 都是“依赖的依赖”,所以不能在一个项目里自定义的区分选择同一个jar包的某一个版本。

     所以 原项目中已依赖的hbase 不动它,新建一个项目ds-rec-milvus,专门用来存放milvus和它依赖的jar包,然后添加maven-shade-plugin插件。

     ds-rec-milvus的pom.xml如下:

4.0.0com.ds.recds-rec-milvus1.0.0-SNAPSHOTio.milvusmilvus-sdk-java2.0.3com.google.protobufprotobuf-java3.12.0

org.apache.maven.pluginsmaven-shade-plugin3.2.4

packageshade*:*META-INF/*.SFMETA-INF/*.DSAMETA-INF/*.RSA

com.google.protobufshade.com.google.protobufxxxxxxhttp://xxxxx-snapshotxxx-snapshothttp://xxxx

       从配置文件中可以看到,由于maven-shade-plugin插件在解决这个问题上其实是通过对依赖进行重命名而达到隔离的目的,所以配置主要是集中在relocations中。这里将以shade.com.google.protobuf 开头的包全部重命名为以shade.com.google.protobuf开头。


3.引入依赖

        将ds-rec-milvus进行打包,打包好之后在原项目中引入ds-rec-milvus的依赖。


com.recrec-ds-milvus1.0.0-SNAPSHOT

        此时可以看到依赖从milvus-sdk-java-2.0.3 变为了ds-rec-milvus-1.0.0-SNAPSHOT

此时再双击shift,搜索冲突的替罪羔羊:ByteStringer,就只保留了hbase依赖的内容

运行milvus的测试类,终于成功了~


一些需要注意的坑

       集成度比较高的jar包,里面的依赖链又大又深,一般会有多个问题。比如上述例子中除了protobuf-java,还会有 guava、grpc-core等jar包也会存在版本冲突

所以建议:

         先新建一个新项目,无干扰的测试此方案是否可行。可行后,再引入原来的“屎山”,逐个问题去排查。最终让大家伙动起来~~


maven-shade-plugins的其他使用


  • 打入和排除指定jar包。maven-shade-plugins还有个功能就是打入和排除指定的jar包,通过和指定。

官方配置示例 【包含式  打入】


...

org.apache.maven.pluginsmaven-shade-plugin3.2.4

packageshadeclassworlds:classworldsjunit:junitjmock:**:xml-apisorg.apache.maven:lib:testslog4j:log4j:jar:...


官方配置示例【又包又排的 打入】


...

org.apache.maven.pluginsmaven-shade-plugin3.2.4

packageshadejunit:junitjunit/framework/**org/junit/**org/junit/experimental/**org/junit/runners/***:*META-INF/*.SFMETA-INF/*.DSAMETA-INF/*.RSA...


  • 排除包内资源。在上面的pom中使用maven-shade-plugin时,使用来对包内META-INF下的一些资源进行排除。如上面的配置中排除META-INF下的资源文件

*:*META-INF/*.SFMETA-INF/*.DSAMETA-INF/*.RSA

参考

解决项目版本冲突——maven-shade插件使用_SK_Jaco的博客-CSDN博客_shade插件

java.lang.NoClassDefFoundError: Could not initialize class org.apache.hadoop.hbase.util.ByteStringer_南子午的博客-CSDN博客


推荐阅读
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
author-avatar
青青河边羊
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有