【问题标题】:Avoiding major/minor version conflicts with Java/Maven dependencies避免与 Java/Maven 依赖项的主要/次要版本冲突
【发布时间】:2019-09-26 12:07:00
【问题描述】:

使用这种方案发布 Maven 项目是否是个好主意:

<groupId>com.oresoftware</groupId>
<artifactId>async.1</artifactId>

<groupId>com.oresoftware</groupId>
<artifactId>async.2</artifactId>

<groupId>com.oresoftware</groupId>
<artifactId>async.3</artifactId>

这些代表项目的主要版本在哪里?这不是创建不同命名空间的有效方法,以便树中的不同依赖项可能依赖于该库的不同版本吗?有没有人这样做或者这是一种不好的做法?

我什至也在考虑通过次要版本来命名它们:

<groupId>com.oresoftware</groupId>
<artifactId>async.1.1</artifactId>

<groupId>com.oresoftware</groupId>
<artifactId>async.1.2</artifactId>

<groupId>com.oresoftware</groupId>
<artifactId>async.1.3</artifactId>

更新,据说这是 Apache Commons 在版本 3 和 4 之间所做的,这里有两个不同的导入:

第 3 版:

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.2</version>
</dependency>

第 4 版:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>

所以我的问题是 - 要拥有不同的包名称或命名空间,使用不同的 artifactId 是否就足够了,还是我们还需要不同的 groupId ?

【问题讨论】:

  • 对此的简单回答:否。使用完全符合预期的版本标签并使用语义版本控制...
  • 我的理解是版本标签not实际上允许在一个应用程序中使用两个不同版本的“相同”依赖项?
  • 这是不允许的,因为它没有意义,因为你不能在类路径上有重复的类,也不能像 Java 模块这样的东西不起作用。并且需要拥有同一工件的不同版本是一个真正的问题..还有一个问题:您为什么需要这样的东西?
  • 不是我的代码需要不同的版本(尽管这种情况在极少数情况下会发生)——相反,我的一些依赖依赖于不同的版本。这叫做依赖地狱,是可以避免的,Java没有很好的避免。
  • "要拥有不同的包名或命名空间,使用不同的 artifactId 就足够了,还是我们还需要不同的 groupId?" 使用不同的就足够了工件 ID。更改一项或两项之间没有功能差异,它仅用于组织目的。请参阅Guide to naming conventions on groupId, artifactId, and version,这可能有助于您确定是否应该同时更改两者。

标签: java maven


【解决方案1】:

不,如果类的名称也不同,这只是一个不同的命名空间

因为它们可能不是,您只是在为自己设置更多麻烦,因为您现在可以添加多个版本的类。鉴于类路径顺序通常是无序的(例如在 web 应用程序中),您将在编译时和/或运行时实际看到哪个是任意的,从而导致不可预测的行为。

现在,如果您还重命名了包,就像 Apache Commons Collections 在版本 3.x 和 4.x 之间所做的那样,那么您也应该重命名 maven 组/工件,这样您就可以在类路径中同时拥有这两者。

否则,您应该尝试使代码向后兼容,以便可以使用更新版本的库而不会引起问题。

【讨论】:

  • 您能否展示 groupId/artifactId 的实际示例,说明该做什么与​​不做什么?谢谢。如果我按照你说的做,我可以这样做com.oresoftware.async1.1.async?不确定那里是否允许数字/点。
  • @AlexanderMills 您询问的是您图书馆的版本。 “发布”是“版本”的另一个词,因此您应该只更改库的新 发布&lt;version&gt; 值。现在,如果您更改所有 Java 包名称,那么它就不再是同一个库了,应该更改 &lt;groupId&gt; 和/或 &lt;artifactId&gt; 值。
  • 好吧,你知道我想要做什么——我正在尝试使用不同的包命名空间,这样如果一个项目想要使用两个不同版本的库,它就可以了。所以我会有类似import com.oresoftware.async1.Async 的东西,在另一个文件中我会有类似import com.oresoftware.async2.Async 的东西,对吧?但我该如何设置,或者这是一个坏主意?
  • @AlexanderMills 你读过我的回答吗?让我总结一下:如果你重命名包,你应该重命名 maven 组/工件。你如何重命名它们完全取决于你。 --- 问题是您的问题只询问了关于重命名组/工件而没有提及 Java 包名称的问题。如果你的问题更清楚,你就会得到更清楚的答案。
  • 兄弟,你知道我想要做什么(对吧?)。如果有办法做我想做的事,请告诉我如何做。我不知道如何,坦率地说,你的回答不够好​​。这个问题本来可以更清楚一点,但我认为它已经足够清楚了,改变它为时已晚。
【解决方案2】:

可以这样做,正如 Andreas 在另一个答案中所说的那样。但很少这样做。

我自己也想过这样的概念,我想主要原因是从版本 n 升级到 n+1 变得更加困难。您需要浏览所有代码并替换导入。此外,如果您在接口中使用库中的对象,则将方法参数绑定到库的特定版本(通过导入),并使互操作性更加困难。

通常,从 n 升级到 n+1 并不意味着一切都会中断,但可能只是一点点,因此遍历所有代码可能比接受通常版本方案的问题更难。

【讨论】:

  • 没错,但我认为一个简单的模式替换器可以为您的所有文件做。但我另外同意,所以也许只有主要版本我们才会增加数量。
  • 我更新了 OP,如果你能回答 OP 底部的问题,我想你会帮助别人,而不仅仅是我自己。
  • 如果两个工件具有不同的 groupId 和/或不同的 artifactId,它们是(在 maven 的意义上)不同的工件。 groupId 在技术上与工件中的类的打包没有任何关系。因此,要让 Maven 允许您同时拥有两个工件,您需要更改 groupId 或 artifactId(或两者)。为避免类名冲突,您需要重命名包。
  • 好吧,这就是我感到困惑的地方,我认为通过重命名 groupId/artifiactId 你实际上是在重命名包,但我猜不是?
  • 不,通常 groupId 用于包装的第一部分,artifactId 也经常在那里使用,但这只是惯例。更改 groupId 或 artifactId 不会更改包名称(反之亦然)。
【解决方案3】:

如果你这样做了,那么你还必须改变你的类的包;否则你会给你的客户带来更多的冲突。查看公共收藏的罐子;版本 3 的包是 org\apache\commons\collections\..,在版本 4 中,他们将包更改为 org\apache\commons\collections4\..

这样客户端就可以导入两个库并在运行时同时使用它们,并且仍然没有冲突。


所以要回答您的问题,仅更改 groupId/artifactId 是不够的。要么升级版本(并保持 groupId/artifactId 不变);这样 maven/gradle 将选择例如。版本 1,如果导入了版本 1 和 2。但是如果你改变了artifactId,你就绕过了基于version-s的冲突解决机制;并且客户可以同时导入两者。然后为了不发生冲突,您必须更改包名称(对于包含在您的 jar 中的所有类)。

【讨论】:

  • 是的,我之前的计划是保持 groupId 不变,将 artifactId 从 async1 更改为 async2async3 以进行每个主要版本更改,并且版本字段将为 1.x.x 和然后是2.x.x,然后是3.x.x,并且在代码库中,目录结构需要从/src/main/java/com/oresoftware/async1 更改为/src/main/java/com/oresoftware/async2/src/main/java/com/oresoftware/async3,仅此而已.. AFAICT
【解决方案4】:

好的,计划就到这里

  1. 保持groupId不变

  2. artifactIdasync1 更改为 async2 更改为 async3 对于每个主要版本更改,版本字段将是 1.x.x,然后是 2.x.x,然后是 @ 987654326@

  3. 在代码库中,目录结构需要从src/main/java/com/oresoftware/async1 更改为src/main/java/com/oresoftware/async2src/main/java/com/oresoftware/async3

就是这样......AFAICT

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多