Maven - 同一依赖项的多个版本

26

我有一个Web应用程序,其中依赖项引入了两个JAR文件:

  1. javassist-3.9.0.GA.jar
  2. javassist-3.20.0-GA.jar

当我打包WAR文件时,这两个文件都在WEB-INF/lib目录中,我的问题是应用程序正在运行,为什么我不会遇到任何问题,因为显然我在两个JAR文件中拥有相同的类,所以应该会出现问题,对吗?


1
如果您在war中真的有两个相同版本的构件,那么您正在做一些错误的事情...使用默认的Maven和maven-war-plugin,您的lib文件夹中不应该有重复的jar文件...(这听起来像是您手动操作了一些本应由Maven完成的任务)... - khmarbaise
谢谢,如果我使用“package”目标来构建war文件,那么它不是使用maven war插件来完成的吗?如果不是,那么maven-war-plugin与“package”目标有什么不同呢? - Toseef Zafar
package 不是一个目标,而是一个生命周期。如果您在pom文件中设置了正确的 <packaging>war</packaging>,那么这应该可以直接使用...最好查看您正在使用的pom文件。 - khmarbaise
可能是如何包含同一依赖项的两个不同版本?的重复问题。 - Flow
2个回答

34
对于Java来说,提供了多少个版本的类并不重要。默认的类加载器只会选择它能够找到的classpath上的第一个类。
既然你可以在没有错误的情况下运行应用程序,这意味着以下之一:
- 如果javassist-3.9.0.GA.jar是classpath上的第一个:你的应用程序不依赖于javassist-3.20.0-GA.jar中的新API或补丁修复。还没有使用此库的API在这些版本之间发生了变化(库不应该在次要版本之间进行更改)。 - 如果javassist-3.20.0-GA.jar是classpath上的第一个:该库支持向后兼容。
建议如下:
- 如果这些依赖项是应用程序不同部分的直接依赖项,请确保在各处都使用相同的版本。最好的方法是在父POM的dependencyManagement部分中修复版本,然后在dependencies部分中省略版本属性。 - 如果这些依赖项是传递性依赖项,则排除你不想使用的那个,以确保你的最终应用程序中只有一个库的版本。还要考虑为仍使用旧版本的项目提交问题,并要求他们升级依赖项的版本。 - 如果您需要使用两个不兼容的同一库的版本,其包和类名称相同,请考虑使用模块系统,例如OSGi,它在某种程度上支持运行不同版本的同一库。

我理解这个解释很合乎逻辑,但这是否意味着应用程序真的处于风险之中?因为如果我有一个依赖项,它依赖于3.9.0.GA版本的类,并且该类在3.20.2-GA和3.20.0-GA中得到更新,而且3.20.0-GA是第一个出现在classpath中的版本,那么这个依赖项需要3.9.0.GA版本的特定类吗? - Toseef Zafar
1
另一个问题是如何找出 classpath 中哪一个是第一个? - Toseef Zafar
@Puce,感谢您的帮助。我已经成功摆脱了我手动放置在POM中的依赖项,这使我依赖于依赖项,该依赖项依赖于javaassist-3.20,但现在一切都很好!谢谢。 - Toseef Zafar
@Tefa 如果你的代码中有直接依赖于像javaassist这样的库,最好还是声明它。只需确保版本与其他间接依赖项的javaassist匹配即可。 - Puce
确定为什么您的应用程序中有多个给定工件的版本,这意味着出现了某些问题... - khmarbaise
显示剩余4条评论

6

针对“有什么建议如何修复它?”的问题,可以查看使用依赖树解决冲突。通过命令mvn dependency:tree,您可以知道任何依赖项来自哪里。当您知道哪些工件取决于javassist时,您可以添加一个排除条目以避免其中一个javassist版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接