Maven怎么处理引用的jar版本冲突?

peizhyi 2013-07-11
cosmo1987 写道
peizhyi 写道
cosmo1987 写道
peizhyi 写道
bastengao 写道
peizhyi 写道
有同样的问题,当项目中依赖的两个包版本不一致的时候出现问题,我用的包是com.google.protobuffer,2.1和2.3冲突,用了一楼的做法,没有效果呀。

首先在 自己的 pom 中,人为不可能引入两个版本不同的依赖。冲突最可能的就是你依赖的依赖可能产生了冲突。
比如 A 依赖 版本为2.0 的 C ,B 依赖 版本为3.0的 C。在你的pom中,你同时依赖了 A 和 B ,这时就会产生冲突。这时候你就要判断,哪个版本能同时让A和B工作(如果可以的话),然后排除掉另一个就行了。我通常都是排除掉较低的版本。

<dependencies>
        <dependency>
            <groupId>A</groupId>
            <artifactId>A</artifactId>
            <version>xxx</version>
            <exclusions>
                <exclusion>
                    <groupId>C</groupId>
                    <artifactId>C</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>B</groupId>
            <artifactId>B</artifactId>            
        </dependency>
</dependencies>


比较让人郁闷的问题是,用了2.0的缺方法一,用了3.0的缺方法二。。这种问题还有解吗?

同求啊。发生了同样的问题。 两个版本,高版本不兼容低版本的方法。目前的方案有两个 。一个是把其中的一个版本的maven坐标更换了,让两个都加载。不过还没有验证过。应该也会有问题。另外一个方法就是把低版本的包路径全部更换,再更换低版本的maven坐标,防止冲突。但是这些方法太繁琐,而且感觉不靠谱呀!有没有更好的方法解决?


现在想想看,有一个方法相对可行。把应用这两个版本不同方法的部分,拆成两个子项目,两个子项目各自引用不同版本的包。这样就能够同时引用,也不会冲突。

拆成两个子项目,如果是指maven项目下的两个module的话,最后构建maven的web项目时两个module所依赖的jar会打包到一个war中。问题没有解决。而如果是指两个maven项目并且分别部署的话,这样仅仅为了隔离jar依赖而拆项目,这个项目也不好拆。毕竟拆项目的依据还是在当一个应用过大,需要降低耦合划分成两个子系统的时候才需要做。之前又想到两个解决方案。不过还有待权衡。1.引入OSGI架构。架构的引入可以很好的以组件的形式可插拔的更换模块,并且可以很好的做到jar隔离。但是OGSI的引入又会带来很多其他的麻烦。学习成本增加,OSGI的引入必然带来整个项目结构的变动,而且引入OSGI后,所有的模块都必须以OSGI的方式进行,对于一些觉得很简单且没有必要使用OSGI方式编写的代码,不能被OSGI引用。2.自己实现web container下一级的application classloader。对于一些特殊的jar使用配置的方式让自己实现的classloader进行加载。在classloader这一层做到隔离后的jar相互调用问题。这个classloader的实现确实是一个技术活。需要解决很多问题。开发成本提高很多。目前为止还是没有想出简单方便的方法解决这个问题。


的确,我之前没想到整体打包以后的冲突。不过有个疑问啊,maven依赖是有版本号的,每个module依赖不同的版本,最后打包的时候两个module会引用各自的版本吧?
cosmo1987 2013-07-12
peizhyi 写道
cosmo1987 写道
peizhyi 写道
cosmo1987 写道
peizhyi 写道
bastengao 写道
peizhyi 写道
有同样的问题,当项目中依赖的两个包版本不一致的时候出现问题,我用的包是com.google.protobuffer,2.1和2.3冲突,用了一楼的做法,没有效果呀。

首先在 自己的 pom 中,人为不可能引入两个版本不同的依赖。冲突最可能的就是你依赖的依赖可能产生了冲突。
比如 A 依赖 版本为2.0 的 C ,B 依赖 版本为3.0的 C。在你的pom中,你同时依赖了 A 和 B ,这时就会产生冲突。这时候你就要判断,哪个版本能同时让A和B工作(如果可以的话),然后排除掉另一个就行了。我通常都是排除掉较低的版本。

<dependencies>
        <dependency>
            <groupId>A</groupId>
            <artifactId>A</artifactId>
            <version>xxx</version>
            <exclusions>
                <exclusion>
                    <groupId>C</groupId>
                    <artifactId>C</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>B</groupId>
            <artifactId>B</artifactId>            
        </dependency>
</dependencies>


比较让人郁闷的问题是,用了2.0的缺方法一,用了3.0的缺方法二。。这种问题还有解吗?

同求啊。发生了同样的问题。 两个版本,高版本不兼容低版本的方法。目前的方案有两个 。一个是把其中的一个版本的maven坐标更换了,让两个都加载。不过还没有验证过。应该也会有问题。另外一个方法就是把低版本的包路径全部更换,再更换低版本的maven坐标,防止冲突。但是这些方法太繁琐,而且感觉不靠谱呀!有没有更好的方法解决?


现在想想看,有一个方法相对可行。把应用这两个版本不同方法的部分,拆成两个子项目,两个子项目各自引用不同版本的包。这样就能够同时引用,也不会冲突。

拆成两个子项目,如果是指maven项目下的两个module的话,最后构建maven的web项目时两个module所依赖的jar会打包到一个war中。问题没有解决。而如果是指两个maven项目并且分别部署的话,这样仅仅为了隔离jar依赖而拆项目,这个项目也不好拆。毕竟拆项目的依据还是在当一个应用过大,需要降低耦合划分成两个子系统的时候才需要做。之前又想到两个解决方案。不过还有待权衡。1.引入OSGI架构。架构的引入可以很好的以组件的形式可插拔的更换模块,并且可以很好的做到jar隔离。但是OGSI的引入又会带来很多其他的麻烦。学习成本增加,OSGI的引入必然带来整个项目结构的变动,而且引入OSGI后,所有的模块都必须以OSGI的方式进行,对于一些觉得很简单且没有必要使用OSGI方式编写的代码,不能被OSGI引用。2.自己实现web container下一级的application classloader。对于一些特殊的jar使用配置的方式让自己实现的classloader进行加载。在classloader这一层做到隔离后的jar相互调用问题。这个classloader的实现确实是一个技术活。需要解决很多问题。开发成本提高很多。目前为止还是没有想出简单方便的方法解决这个问题。


的确,我之前没想到整体打包以后的冲突。不过有个疑问啊,maven依赖是有版本号的,每个module依赖不同的版本,最后打包的时候两个module会引用各自的版本吧?

两个版本都会被打包到war中。但是当jvm启动加载jar的时候是不管module的版本引用的。它会按照一定的加载顺序去加载jar到classpath中,之后在代码中的依赖都是按照包路径为依据的(同一个加载的classloader下)。所以,两个不同版本的同类型jar后加载的内容会覆盖之前加载的。导致依赖之前加载的jar的module运行出错。
Mr.TianShu 2016-12-15
解压jar 将不同版本的class集合起来,重新打jar,自定义maven坐标,引入。兼容性,不是maven要解决的一大问题么,做的不咋地
Global site tag (gtag.js) - Google Analytics