Maven范围编译与提供给JAR打包之间的区别


260

Maven范围compileprovided将工件构建为JAR时有什么区别?如果是WAR,我会理解-该工件将包含或不包含在WEB-INF / lib中。但如果是JAR,则没关系-不包括依赖项。当范围为compile或时,它们必须位于类路径上provided。我知道provided依赖项不是可传递的-但这仅仅是一个区别吗?

Answers:


289

Maven文档中

  • 编译

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

  • 提供

    这很像编译,但是表明您希望JDK或容器在运行时提供依赖项。例如,在为Java Enterprise Edition构建Web应用程序时,您将对Servlet API和相关Java EE API的依赖关系设置为提供的范围,因为Web容器提供了这些类。该作用域仅在编译和测试类路径上可用,并且不可传递。

回顾:

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

5
是的我知道。但是我在考虑JAR packaging上下文范围的差异。Maven文档没有提及它。我使用Maven已有一段时间,但是我已经问过了自己一个问题:)因此,在JAR packaging上下文中,compileand 之间似乎没有任何区别provided(依赖转换除外)。我对吗?
emstol 2011年

3
@Jacob“在所有类路径可以使用编译范围”是什么意思?
极客

1
我认为“ NOT Transitive”是这里的大热门。因为依赖地狱是开发人员经常面临的问题,并且提供的范围可以防止依赖地狱的发生,因此与其他版本混淆至关重要。
Seetharamani Tmr

2
我认为区别在于包装阶段。使用compile时,它将包括最终战争中的jar或jar(例如spring boot可执行jar),但可能不会提供结果。因为提供的jar可能是由Web容器提供的(例如放在ext lib文件夹中),所以如果不受其他作用域,编译,运行时的依赖,则它不在war软件包中。
Addo Zhang

1
@emstol回到您的原始问题,您是对的,对于JAR,依赖项未打包在JAR本身内。但是在Maven中,JAR打包意味着您希望将其用作库。一旦将其导入到其他Maven项目中,如果范围为compile,则将引入传递依赖关系;如果范围为,则将传递传递依赖provided
LeoLuz

291

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

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

对于Web应用程序,如果应用程序服务器已提供JAR(或其功能),则使用“提供”,否则使用“编译”。

这是参考。


11
您没有回答OP的问题吗?' 当将构件构建为JAR时,使用maven范围编译和提供的区别是什么?'请注意,作者明确声明他们将包装打包为战争时知道区别。
艾伯托

如果我引用部署在同一应用程序服务器上的另一个JAR,我可以使用提供的信息吗?
萨米·奥马尔

1
很清楚,mvn exec:java运行时不会将提供的依赖项添加到类路径中,而是将已编译的依赖项添加到类路径中。
杰米

我问了这个问题-stackoverflow.com/questions/37360132/…该问题已通过将范围从提供更改为编译来解决。但是我看不到用“提供”范围编译的jar和用“编译”范围编译的jar之间的区别。你能解释为什么吗?
Pavel_K,2016年


22

如果您打算生成具有所有依赖关系的单个JAR文件(典型的xxxx-all.jar),则提供的范围很重要,因为该范围内的类不会打包在生成的JAR中。

有关更多信息,请参见maven-assembly-plugin。


7
提供的依赖关系==>依赖关系将被打包。
加布是好人

3
与打包时maven-assembly-plugin,OP的混淆已得到明显解决,有趣的是,投票最多的答案没有提及。
Henrique G. Abreu

我不明白这个答案。它看起来更像是一条评论。
reinierpost

11
  • 编译

使它可用于类路径,如果它是普通的jar,则不要将此依赖项添加到最终的jar中。但如果最终的jar是单个jar,则将此jar添加到jar中(例如,可执行jar)

  • 提供

依赖关系将在运行时环境中可用,因此无论如何都不要添加此依赖关系;甚至不在单个jar中(例如,可执行jar等)


3

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

我的烦恼之一是这两个词应具有相同的时态。编译并提供,或者编译并提供。



0

如果jar文件像可执行的spring boot jar文件一样,则所有依赖项的范围必须为 compile包括所有jar文件。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.