Java maven依赖插件忽略依赖版本?

Java maven依赖插件忽略依赖版本?,java,maven,dependencies,maven-dependency-plugin,Java,Maven,Dependencies,Maven Dependency Plugin,在我看来,maven依赖插件在计算依赖列表时表现不好 假设这3个项目: 基准1: <?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>

在我看来,maven依赖插件在计算依赖列表时表现不好

假设这3个项目:

基准1:

<?xml version="1.0" encoding="UTF-8"?>                                                                                                                            
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>mygroup</groupId>
    <artifactId>base1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
      <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.3</version>
      </dependency>
    </dependencies>
</project>
它甚至没有使用版本号最高的公共语言,而是使用它最先找到的语言


我怎样才能避免这种情况?我需要所有依赖项。

Maven从上到下扫描pom,并使用它遇到的第一个版本

假设您确实需要这两个版本的commons-lang,您可以将这两个版本放在您的项目中,并使用maven将它们打包到您的jar中

然而,编译器如何知道调用
StringUtils.isEmpty()
是否调用版本2.3或2.6


.

Maven总是使用“最近的胜利”策略解决冲突。您可以运行以下命令来查看使用特定版本的原因:

mvn dependency:tree -Dverbose -Dincludes=commons-lang
有关更多信息,请参见以下内容:

根据此(相关部分以粗体突出显示):

依赖项中介-这决定了当遇到工件的多个版本时,将使用哪个版本的依赖项。目前,Maven 2.0只支持使用“最近的定义”,这意味着它将使用依赖关系树中与项目最接近的依赖关系的版本。您总是可以通过在项目的POM中显式声明来保证版本请注意,如果两个依赖项版本在依赖项树中处于同一深度,则在Maven 2.0.8之前,没有定义哪一个版本将获胜,但由于Maven 2.0.9,则重要的是声明中的顺序:第一个声明获胜。

因此,Maven选择版本2.3,因为它是在依赖项解析过程中首先遇到的。请注意,如果在
combined
模块上运行
mvn dependency:tree
,它将显示使用了哪个版本以及省略了哪个版本

最好的解决方案是通过在其POM中声明依赖项,明确地在
组合的
工件中选择您想要的版本,以便Maven优先于其他版本:

<?xml version="1.0" encoding="UTF-8"?>
<project>
   <modelVersion>4.0.0</modelVersion>
   <groupId>mygroup</groupId>
   <artifactId>combined</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>

   <dependencies>
     <dependency>
       <groupId>mygroup</groupId>
       <artifactId>base1</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>mygroup</groupId>
       <artifactId>base2</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>    <!-- This will override the versions in base1 and base2 -->
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
       <version>2.6</version>
     </dependency>
   </dependencies>

4.0.0
mygroup
合二为一
1.0-快照
罐子
mygroup
base1
1.0-快照
mygroup
二进制数字系统
1.0-快照
公地郎
公地郎
2.6


请注意,Maven无法选择两个版本,因为在这种情况下,项目的类路径上会有相同类的两个定义,这可能会在运行时导致意外问题。

最好是更改需要依赖commons lang:2.3的代码。抱歉…@otonglet如果base1和base2是第三方模块,我不能这么做。@radlan您是否有可能将
mvn依赖项:list
与?@nullpointer混淆?否,我将更多地讨论用于计算依赖项的实际算法<代码>mvn依赖项:复制依赖项是实际使用的。但由于这与mvn dependency:list相同,我提到了这一点,因为它更容易放在示例中。实际上,这似乎是唯一的解决方案。这并不是我想要的,因为例如base1和base2是可执行的应用程序,它们的类路径是在构建时生成的,并且它们的组合只是那些组装所有依赖项的应用程序的容器,base2将不可运行,因为它的类路径的依赖项不包含在组装的依赖项中。然而,我似乎被困在这里,你的建议可能是最好的解决方案。@radlan我可能遗漏了一些东西,但根据你的描述,你说“base1和base2是可执行的应用程序”,似乎你应该将构建分为两个独立的构建,其中build#1构建base1,build#2构建base2,在这种情况下,每个构建都使用它自己的独立版本的依赖项。无论如何,这里有一个帖子似乎是相关的:。我碰巧也回答了。在这种情况下,您可以使用Maven概要文件。每个概要文件都可以声明自己的依赖项。base1和base2有单独的版本。但还有另一个组合的构建,它将这些其他构建捆绑在一起,以简化整个捆绑包的部署。
[INFO] The following files have been resolved:
[INFO]    commons-lang:commons-lang:jar:2.3:compile
[INFO]    mygroup:base1:jar:1.0-SNAPSHOT:compile
[INFO]    mygroup:base2:jar:1.0-SNAPSHOT:compile
mvn dependency:tree -Dverbose -Dincludes=commons-lang
<?xml version="1.0" encoding="UTF-8"?>
<project>
   <modelVersion>4.0.0</modelVersion>
   <groupId>mygroup</groupId>
   <artifactId>combined</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>

   <dependencies>
     <dependency>
       <groupId>mygroup</groupId>
       <artifactId>base1</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>mygroup</groupId>
       <artifactId>base2</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>    <!-- This will override the versions in base1 and base2 -->
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
       <version>2.6</version>
     </dependency>
   </dependencies>