【问题标题】:Difference between maven scope compile and provided for JAR packagingmaven 范围编译和提供给 JAR 打包的区别
【发布时间】:2011-10-02 13:58:19
【问题描述】:

当工件构建为 JAR 时,maven 范围 compileprovided 有什么区别?如果是 WAR,我会理解 - 工件将包含或不包含在 WEB-INF/lib 中。但在 JAR 的情况下,这并不重要——不包括依赖项。当它们的作用域为compileprovided 时,它们必须在类路径中。我知道 provided 依赖项不具有传递性 - 但它只是一个区别吗?

【问题讨论】:

    标签: maven jar


    【解决方案1】:

    编译意味着您需要 JAR 来编译和运行应用程序。 对于 Web 应用程序,例如,JAR 放在WEB-INF/lib目录下。

    提供意味着您需要 JAR 进行编译,但在运行时环境已经提供了一个 JAR,因此您不需要将它与您的应用程序打包。对于 Web 应用程序,这意味着 JAR 文件不会放入 WEB-INF/lib 目录中。

    对于网络应用,如果应用服务器已经提供了 JAR(或其功能),则使用“provided”,否则使用“compile”。

    Here is the reference.

    【讨论】:

    • 你不是在回答 OP 的问题吗? '当工件构建为 JAR 时,使用 maven 范围编译和提供有什么区别?' 请注意,作者明确声明他们知道打包为战争时的区别。
    • 如果我引用部署在同一应用服务器上的另一个 JAR,我可以使用提供吗??
    • 所以要明确一点,当mvn exec:java 运行时,提供的依赖项不会添加到类路径中,而是编译的依赖项。
    • 我问了这个问题 - stackoverflow.com/questions/37360132/… 通过将范围从提供更改为编译来解决问题。但我看不出用“提供”范围编译的 jar 和用“编译”范围编译的 jar 之间有什么区别。你能解释一下原因吗?
    【解决方案2】:

    如果 jar 文件类似于可执行的 spring boot jar 文件,则所有依赖项的范围必须为 compile 以包含所有 jar 文件。

    但如果jar文件用于其他包或应用程序,则不需要在jar文件中包含所有依赖项,因为这些包或应用程序可以自己提供其他依赖项。

    【讨论】:

      【解决方案3】:

      来自Maven Doc

      • 编译

        这是默认范围,如果未指定则使用。编译 依赖项在项目的所有类路径中都可用。 此外,这些依赖项会传播到相关项目。

      • 提供

        这很像 compile,但表示您期望 JDK 或 容器在运行时提供依赖。例如,当 为 Java 企业版构建一个 Web 应用程序,您将 将 Servlet API 和相关 Java EE API 的依赖设置为 提供范围是因为 Web 容器提供了这些类。这 范围仅在编译和测试类路径上可用,并且是 不及物。

      回顾:

      • 依赖项不是传递的(如您所述)
      • 提供的范围仅适用于编译和测试类路径,而编译范围适用于所有类路径。
      • 提供的依赖项未打包

      【讨论】:

      • 是的,我知道。但我思考JAR packaging 上下文中范围的差异。 Maven 文档没有提到它。我使用 Maven 有一段时间了,但我刚刚问过自己 :) 所以在 JAR packaging 上下文中,compileprovided 之间似乎没有任何区别(依赖转换除外)。我说的对吗?
      • @Jacob “而编译范围在所有类路径中都可用。”是什么意思?
      • 我认为“不传递”是这里的一大亮点。因为依赖地狱是开发人员经常面临的问题,并且提供的范围可以防止它发生并且与其他版本混淆是至关重要的。
      • 我认为区别在于包装阶段。编译时会包含final war或jar中的jar(如spring boot可执行jar),提供的结果可能不包含。因为提供的jar可能是web容器提供的(比如放在ext lib文件夹中),如果不依赖其他作用域、编译、运行时,就不在war包中。
      • @emstol 回到你最初的问题,你是对的,在 JAR 的情况下,依赖项没有打包在 JAR 本身中。但在 maven 中,JAR 包装意味着您希望将其用作库。一旦你将它导入到其他一些 maven 项目中,如果范围是 compile,则传递依赖项将被引入,如果范围是 provided,则不会。
      【解决方案4】:

      对于 jar 文件,如果在 maven-jar-plugin 配置中将 addClassPath 设置为 true,则差异在于 jar 中包含的 MANIFEST.MF 文件中列出的类路径。 “编译”依赖项将出现在清单中,“提供”依赖项不会出现。

      我最讨厌的一个问题是这两个词应该有相同的时态。要么编译提供,要么编译提供。

      【讨论】:

        【解决方案5】:
        • 编译

        在类路径中可用,如果是普通jar,不要将此依赖添加到final jar中;但如果最终 jar 是单个 jar(例如,可执行 jar),则将此 jar 添加到 jar 中

        • 提供

        依赖将在运行时环境中可用,因此在任何情况下都不要添加此依赖;甚至不在单个 jar 中(即可执行 jar 等)

        【讨论】:

          【解决方案6】:

          如果您计划生成一个包含所有依赖项的 JAR 文件(典型的 xxxx-all.jar),那么提供的范围很重要,因为此范围内的类不会被打包到生成的 JAR 中。

          查看 maven-assembly-plugin 了解更多信息

          【讨论】:

          • 提供的依赖 ==> 依赖将被打包。
          • 当你使用maven-assembly-plugin 打包时,OP 的困惑显然​​得到了解决,有趣的是投票最多的答案没有提到它。
          • 我不明白这个答案。它看起来更像是一条评论。
          • 在我的项目中,依赖 jar 被打包在具有两个范围(编译和提供)的最终 jar 中。我不知道为什么会这样。
          • 尝试计算有效的 pom.xml。大多数 IDE 都有这个选项。在这里,您将看到是否有人覆盖了您的范围。
          猜你喜欢
          • 2017-06-01
          • 2015-06-05
          • 1970-01-01
          • 2013-05-30
          • 2011-05-31
          • 2019-07-15
          • 2017-01-01
          • 2016-05-28
          相关资源
          最近更新 更多