Java 提供了依赖项和JBOSS EAP 7

Java 提供了依赖项和JBOSS EAP 7,java,maven,jboss,Java,Maven,Jboss,我知道提供的依赖项是由容器“提供”的,应用程序不需要生成这个JAR 1) 因此,我正在使用JBOSS EAP 7.0.0.GA,这个模块文件夹中有以下jar:hibernate-core-5.0.9.Final-redhat-1.jar 在我的项目中,我使用以下依赖项: <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernat

我知道提供的依赖项是由容器“提供”的,应用程序不需要生成这个JAR

1) 因此,我正在使用JBOSS EAP 7.0.0.GA,这个模块文件夹中有以下jar:hibernate-core-5.0.9.Final-redhat-1.jar

在我的项目中,我使用以下依赖项:

<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.0.9.Final-redhat-1</version>
        </dependency>

org.hibernate
冬眠核心
5.0.9.Final-redhat-1
它工作正常,没有错误。但我知道我应该使用“提供的”范围,因为这个jar是由容器提供的。为什么有效

2) 我还有一个例子。在Jboss Eap 7.0.0.GA中,我有以下jar:Jboss-servlet-api_3.1\u spec-1.0.0.Final-redhat-1.jar。但在我的项目中,我有以下几点:

 <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
            <optional>true</optional>
        </dependency>

javax.servlet
javax.servlet-api
3.0.1
假如
真的

它也很好用,但我不明白为什么。对我来说,正确的依赖关系应该是servlet-api_3.1_spec-1.0.0.Final-redhat-1,并提供。为什么它也能工作?

在构建时,Maven将解析依赖项,并将相关包提供给编译器。例如,您的appserver可能会提供JAR,其中包含
javax.servlet
中的类和接口,但这些类对编译器不一定有用,因为它不知道它们在哪里。通过向Maven提供依赖项,您可以让Maven找到这些依赖项的自己的实现,只在编译时使用

在运行时,如果您已将依赖项标记为提供的,则应用程序将使用appserver提供的版本,而不是Maven已知的版本。这可能是一件坏事,但它通常是有效的,因为编译器只需要知道方法签名,而不需要知道它们的实现。受规范控制的类的方法签名(例如
javax.servlet
中的类)很少更改,因此编译时JAR和运行时JAR之间的不匹配可能不会引起注意。与OSGi兼容的JAR不同,为JEE构建的JAR不包含指定特定兼容依赖版本的元数据——JEE类加载器将使用它们发现的内容,无论是好是坏

但是,您可能会被发现,特别是在不匹配严重的情况下。问题在运行时可能非常明显,例如与缺少类或方法相关的异常,但它们可能很微妙


因此,在可行的情况下,最好使用与运行时可用版本相同的依赖项编译时版本。对于EAP,我记得Red Hat分发了一个Maven BOM(bill of materials,BOM)文件,该文件指定了特定EAP版本的所有EAP JAR的所有版本。

在构建时,Maven将解析依赖项,并使相关包可供编译器使用。例如,您的appserver可能会提供JAR,其中包含
javax.servlet
中的类和接口,但这些类对编译器不一定有用,因为它不知道它们在哪里。通过向Maven提供依赖项,您可以让Maven找到这些依赖项的自己的实现,只在编译时使用

在运行时,如果您已将依赖项标记为提供的,则应用程序将使用appserver提供的版本,而不是Maven已知的版本。这可能是一件坏事,但它通常是有效的,因为编译器只需要知道方法签名,而不需要知道它们的实现。受规范控制的类的方法签名(例如
javax.servlet
中的类)很少更改,因此编译时JAR和运行时JAR之间的不匹配可能不会引起注意。与OSGi兼容的JAR不同,为JEE构建的JAR不包含指定特定兼容依赖版本的元数据——JEE类加载器将使用它们发现的内容,无论是好是坏

但是,您可能会被发现,特别是在不匹配严重的情况下。问题在运行时可能非常明显,例如与缺少类或方法相关的异常,但它们可能很微妙


因此,在可行的情况下,最好使用与运行时可用版本相同的依赖项编译时版本。对于EAP,我记得Red Hat分发了一个Maven BOM表(BOM)文件,该文件指定了特定EAP版本的所有EAP JAR的所有版本。

您能给我一个真实的例子来更好地理解这种情况吗?那么,如果我的所有依赖项都在没有“提供”范围的情况下工作,为什么我需要提供?仅针对轻量级JAR?如果您将自己的依赖项添加到JAR中,那么应用程序可能会使用名称相同但版本不同的类。除非您非常详细地研究JEE类加载规则——appserver实际上尊重这一点——否则很难判断在运行时加载哪个类。所以这不仅仅是一个更轻的JAR,而且在运行时具有一致性。我有一个JAR,负责所有hibernate的东西。这个jar在我所有的项目中都使用,我不需要重新声明hibernate依赖项。因为我在所有依赖项中设置了编译范围。你看到另一个解决方案了吗?我想你在JAR中包含了Hibernate类,对吗?它们与EAP提供的版本相同还是不同?如果它们不同,你可能会侥幸逃脱,这取决于它们的不同程度。如果您使用提供的
以便使用EAP版本,会发生什么情况?你的应用程序不工作吗?你能给我一个真实的例子来更好地理解这种情况吗?那么,如果我所有的依赖项都在没有“提供”范围的情况下工作,为什么我需要提供?只是为了一个轻量级JAR?如果您添加自己的依赖项int