java中的依赖冲突问题一直比较头疼,特别是做公用包给其他系统用的时候,现在都不敢引入太多的依赖,基本上每次都要帮别人解决依赖冲突的问题,非常麻烦。

特别是碰到一些老系统还不是用maven管理的,人家用你的一个功能还要拷一堆jar包过去,然后排出哪些包在系统中已经有了,版本是否兼容等问题,非常蛋疼。为了方便人家使用就想把所有依赖打成一个jar包提供出去,但这样潜在的依赖冲突问题就会更严重,以后出现冲突时都不知道哪个jar包含了冲突的类。

更不想引入OSGi这种重量级的东西来隔离依赖。

一种解决方法

尝试了多种途径后,发现还是用maven-shade-plugin的relocation方式比较能够满足需要,对于提供基础类库的场景下比较友好。

原理就是可能把依赖的class重命名包路径,并打包到一个jar中。maven-shade-plugin主要帮我们做了三件事情:

  • 把依赖的class重新放到指定的包下;
  • 改写相关class的字节码,对应于重定义的包路径;
  • 把相关依赖的class打进一个jar包;

    这样我们对外提供一个jar包就可以了,显得非常干净,依赖的类被定义到指定的包路径中(比如以当前项目路径为前缀),可以避免跟使用者系统的包冲突。

    有时候我们并不希望把所有的依赖都打到一个包中,只想把一部分容易引起冲突的依赖重定义包路径后包含进来,幸运的是maven-shade-plugin很容易做到,并且会把要发布到maven库的pom.xml中的依赖关系都自动改写掉。(通过配置artifactSet中的include和exclude来指定要包含和排除的依赖)

简单例子

比如我们有这么一个需求:

  • 假设commons-collections这个包非常容易跟其他系统引起冲突,我们想把它重定义路径后包含到主jar包中;
  • 假设我们认为mapdb这个类库一般不会跟别人冲突,不想把它打进主jar包里;

    在pom.xml中定义plugin:

    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.1</version>
    <executions>
    <execution>
    <phase>package</phase>
    <goals>
    <goal>shade</goal>
    </goals>
    <configuration>
    <shadedArtifactAttached>false</shadedArtifactAttached>
    <!--<shadedClassifierName>standalone</shadedClassifierName>-->
    <!--<createDependencyReducedPom>true</createDependencyReducedPom>-->
    <!--<shadedArtifactId>jconvert-pinyin-standalone</shadedArtifactId>-->
    <!--<shadeSourcesContent>true</shadeSourcesContent>-->
    <createSourcesJar>true</createSourcesJar>
    <artifactSet>
    <excludes>
    <exclude>org.mapdb:*</exclude>
    </excludes>
    </artifactSet>
    <relocations>
    <relocation>
    <pattern>org.apache.commons.collections</pattern>
    <shadedPattern>com.mycompany.myproject.org.apache.commons.collections</shadedPattern>
    </relocation>
    </relocations>
    </configuration>
    </execution>
    </executions>
    </plugin>

其中shadedArtifactAttached设为false,表示把shade过的jar作为项目默认的包(发布到maven库时也是shade后的包,发布上去的pom也是改写过的)。如果设为true,则默认的包还是不变,会生成一个独立的shade后的包(这样可以提供2种格式的包,比如让maven工程用户依赖普通的包,非maven用户使用shade过的包)。

其他详细的参数设置参考 maven-shade-plugin官网 :

潜在的问题

如果第三方包中有反射相关的代码,则shade后可能出现不能正常工作,所以要仔细检查确保不会出现问题

避免jar依赖冲突的一种办法的更多相关文章

  1. Maven中解决jar包冲突的三种方式

    首先我们在idea中创建一个maven工程,我们只关注pom.xml以及External Libraries中导入的jar包 导入spring-beans.jar <dependency> ...

  2. Maven中 jar包冲突原理与解决办法

    Maven中jar包冲突是开发过程中比较常见而又令人头疼的问题,我们需要知道 jar包冲突的原理,才能更好的去解决jar包冲突的问题.本文将从jar包冲突的原理和解决两个方面阐述Maven中jar包冲 ...

  3. Maven 知识点总结以及解决jar报冲突的几种方法

    1.常见的命令 Compile Test Package Install Deploy Clean 2.坐标的书写规范 groupId 公司或组织域名的倒序 artifactId 项目名或模块名 ve ...

  4. idea解决Maven jar依赖冲突(四)

    首先点击右侧的MavenProjects打开以下界面: 这个界面是maven的命令界面: 点击这个图标会进入如下界面: 左上角可以缩放,点击线可以取消冲突依赖,红色线为冲突依赖. 上图为无依赖冲突的s ...

  5. log4j-over-slf4j.jar AND slf4j-log4j12.jar 依赖冲突解决方案

    使用maven构建项目时,如果项目中有log4j的依赖,在运行程序时可能会出现在同一个类中log4j-over-slf4j.jar和 slf4j-log4j12.jar冲突的问题: 项目报错内容为: ...

  6. Maven搭建hadoop环境报Missing artifact jdk.tools:jdk.tools:jar:1.7(5种办法,2种正解)

    刚刚写的那一篇,是网上比较主流的解决办法. 鉴于实际情况,有伙伴的机器上没有遇到这个问题,我们再探究原因,最终还有4种情况需要说明. 先说,另外一种"正解". <depend ...

  7. 安装percona-xtrabackup一直提示依赖冲突的一个解决办法

    我的Mysql是5.6版本,通过自己下载的rpm包执行安装: yum instal percona-xtrabackup-2.1.7-721.rhel6.x86_64.rpm 会出现如下的安装错误提示 ...

  8. [转]hash冲突的四种办法

    原文地址:http://blog.csdn.net/qq_27093465/article/details/52269862 一)哈希表简介 非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的 ...

  9. 使用maven-shade-plugin插件解决spark依赖冲突问题

    依赖冲突:NoSuchMethodError,ClassNotFoundException   当用户应用于Spark本身依赖同一个库时可能会发生依赖冲突,导致程序奔溃.依赖冲突表现为在运行中出现No ...

随机推荐

  1. Openerp 修改 tree view 的列宽

    在 tree 的后边添加自定义css 列:“my_class" 然后在对应的css文件中,添加样式: 保存,重新刷新页面即可.

  2. 修改Eclipse jdk环境

    原因:由于项目原因,要将原有的工程从jdk1.6迁移到jdk1.7 问题:Eclipse默认的jdk环境为jdk1.6 解决方法: 1)首先是安装jdk1.7,以及配置环境变量,在这里就不再说了 2) ...

  3. Cassandra概念学习系列之Cassandra是什么?

    不多说,直接上干货! http://cassandra.apache.org/ Apache Cassandra是一套开源分布式NoSQL数据库系统.它最初由Facebook开发,用于储存收件箱等简单 ...

  4. leetcode简单题目两道(2)

    Problem Given an integer, write a function to determine if it is a power of three. Follow up: Could ...

  5. 有关索引的DMV

    转自:http://www.cnblogs.com/CareySon/archive/2012/05/17/2505981.html#commentform 有关索引的DMV 1.查看那些被大量更新, ...

  6. Mathematik

    Ausdruck auf Deutsch Lösen Problem der Abteilung. 求导. Die Abteilung von 3x ist 3. 3x的导数是3 Lösen Prob ...

  7. JVM内存模型和垃圾回收

    Java开发有个很基础的问题,虽然我们平时接触的不多,但是了解它却成为Java开发的必备基础——这就是JVM.在C++中我们需要手动申请内存然后释放内存,否则就会出现对象已经不再使用内存却仍被占用的情 ...

  8. jQuery事件篇---高级事件

    内容提纲: 1.模拟操作 2.命名空间 3.事件委托 4.on.off 和 one 发文不易,转载请注明出处! 一.模拟操作 在事件触发的时候,有时我们需要一些模拟用户行为的操作.例如:当网页加载完毕 ...

  9. Java - 方法的参数声明

    给方法的参数加上限制是很常见的,比如参数代表索引时不能为负数.对于某个关键对象引用不能为null,否则会进行一些处理,比如抛出相应的异常信息. 对于这些参数限制,方法的提供者必须在文档中注明,并且在方 ...

  10. Java学习网址

    JAVA学习记录均参考自爱慕课网址: 爱慕课:http://www.imooc.com/course/list?c=java