【发布时间】:2011-10-02 13:58:19
【问题描述】:
当工件构建为 JAR 时,maven 范围 compile 和 provided 有什么区别?如果是 WAR,我会理解 - 工件将包含或不包含在 WEB-INF/lib 中。但在 JAR 的情况下,这并不重要——不包括依赖项。当它们的作用域为compile 或provided 时,它们必须在类路径中。我知道 provided 依赖项不具有传递性 - 但它只是一个区别吗?
【问题讨论】:
当工件构建为 JAR 时,maven 范围 compile 和 provided 有什么区别?如果是 WAR,我会理解 - 工件将包含或不包含在 WEB-INF/lib 中。但在 JAR 的情况下,这并不重要——不包括依赖项。当它们的作用域为compile 或provided 时,它们必须在类路径中。我知道 provided 依赖项不具有传递性 - 但它只是一个区别吗?
【问题讨论】:
编译意味着您需要 JAR 来编译和运行应用程序。 对于 Web 应用程序,例如,JAR 将放在WEB-INF/lib目录下。
提供意味着您需要 JAR 进行编译,但在运行时环境已经提供了一个 JAR,因此您不需要将它与您的应用程序打包。对于 Web 应用程序,这意味着 JAR 文件不会放入 WEB-INF/lib 目录中。
对于网络应用,如果应用服务器已经提供了 JAR(或其功能),则使用“provided”,否则使用“compile”。
【讨论】:
mvn exec:java 运行时,提供的依赖项不会添加到类路径中,而是编译的依赖项。
如果 jar 文件类似于可执行的 spring boot jar 文件,则所有依赖项的范围必须为 compile 以包含所有 jar 文件。
但如果jar文件用于其他包或应用程序,则不需要在jar文件中包含所有依赖项,因为这些包或应用程序可以自己提供其他依赖项。
【讨论】:
来自Maven Doc:
编译
这是默认范围,如果未指定则使用。编译 依赖项在项目的所有类路径中都可用。 此外,这些依赖项会传播到相关项目。
提供
这很像 compile,但表示您期望 JDK 或 容器在运行时提供依赖。例如,当 为 Java 企业版构建一个 Web 应用程序,您将 将 Servlet API 和相关 Java EE API 的依赖设置为 提供范围是因为 Web 容器提供了这些类。这 范围仅在编译和测试类路径上可用,并且是 不及物。
回顾:
【讨论】:
JAR packaging 上下文中范围的差异。 Maven 文档没有提到它。我使用 Maven 有一段时间了,但我刚刚问过自己 :) 所以在 JAR packaging 上下文中,compile 和 provided 之间似乎没有任何区别(依赖转换除外)。我说的对吗?
compile,则传递依赖项将被引入,如果范围是 provided,则不会。
对于 jar 文件,如果在 maven-jar-plugin 配置中将 addClassPath 设置为 true,则差异在于 jar 中包含的 MANIFEST.MF 文件中列出的类路径。 “编译”依赖项将出现在清单中,“提供”依赖项不会出现。
我最讨厌的一个问题是这两个词应该有相同的时态。要么编译提供,要么编译提供。
【讨论】:
- 编译
在类路径中可用,如果是普通jar,不要将此依赖添加到final jar中;但如果最终 jar 是单个 jar(例如,可执行 jar),则将此 jar 添加到 jar 中
- 提供
依赖将在运行时环境中可用,因此在任何情况下都不要添加此依赖;甚至不在单个 jar 中(即可执行 jar 等)
【讨论】:
如果您计划生成一个包含所有依赖项的 JAR 文件(典型的 xxxx-all.jar),那么提供的范围很重要,因为此范围内的类不会被打包到生成的 JAR 中。
查看 maven-assembly-plugin 了解更多信息
【讨论】:
maven-assembly-plugin 打包时,OP 的困惑显然得到了解决,有趣的是投票最多的答案没有提到它。