Maven范围-提供,但已编译jar中包含spring-boot-starter-webflux依赖项。为什么?

时间:2019-02-21 17:27:04

标签: maven spring-boot spring-webflux

我想构建jar文件库,并且不包括依赖项,因为它们将在使用该库的应用程序的类路径中。我为此使用了 maven范围-提供的,并且排除了所有依赖项,但仍然很少。我发现它们来自 spring-boot-starter-webflux 。为什么会这样呢?我该怎么做才能摆脱它们?

这里是依赖示例

<dependencies>
    <!-- Nevertheless provided scope some jars from this dependency
     are in compiled jar file. Why ? -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

仅具有这种依赖性的示例项目位于https://github.com/pavelmorozov/MavenProvidedTest/blob/master/pom.xml

空的已编译项目jar的大小超过5 MB。

更新在提出 JF Meier 建议之后,我尝试了 mvndependency:tree ,发现了两个具有范围编译功能的库

[INFO]    +- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.1.3.RELEASE:provided
[INFO]    |  \- io.projectreactor.netty:reactor-netty:jar:0.8.5.RELEASE:compile
[INFO]    |     +- io.netty:netty-codec-http:jar:4.1.33.Final:compile
[INFO]    |     |  +- io.netty:netty-common:jar:4.1.33.Final:compile
[INFO]    |     |  +- io.netty:netty-buffer:jar:4.1.33.Final:compile
[INFO]    |     |  +- io.netty:netty-transport:jar:4.1.33.Final:compile
[INFO]    |     |  |  \- io.netty:netty-resolver:jar:4.1.33.Final:compile
[INFO]    |     |  \- io.netty:netty-codec:jar:4.1.33.Final:compile
[INFO]    |     +- io.netty:netty-codec-http2:jar:4.1.33.Final:compile
[INFO]    |     +- io.netty:netty-handler:jar:4.1.33.Final:compile
[INFO]    |     +- io.netty:netty-handler-proxy:jar:4.1.33.Final:compile
[INFO]    |     |  \- io.netty:netty-codec-socks:jar:4.1.33.Final:compile
[INFO]    |     \- io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.33.Final:compile
[INFO]    |        \- io.netty:netty-transport-native-unix-common:jar:4.1.33.Final:compile
...
[INFO]    +- org.springframework:spring-webflux:jar:5.1.5.RELEASE:provided
[INFO]    |  \- io.projectreactor:reactor-core:jar:3.2.6.RELEASE:compile
[INFO]    |     \- org.reactivestreams:reactive-streams:jar:1.0.2:compile

例如,我看到一个POM文件

  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-reactor-netty</artifactId>
  <version>2.1.3.RELEASE</version>
  ...
  <dependencies>
    <dependency>
      <groupId>io.projectreactor.netty</groupId>
      <artifactId>reactor-netty</artifactId>
      <version>0.8.5.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

现在我仍然不明白为什么其他Spring Boot包含的库没有覆盖作用域编译。这是否意味着这两个库构建错误,还是出于某种原因以这种方式构建?而且我仍然不清楚如何以简单的方式删除似乎具有覆盖范围的依赖项?

我试图将版本号放入我的POM依赖项中-但这没有效果-编译的项目jar中包含相同的jar:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <version>2.1.3.RELEASE</version>
    <scope>provided</scope>
</dependency>

有关父母的更新

父pom文件 spring-boot-starter-parent 不包含任何 dependencyManagement 部分,但又有一个父- spring-boot-dependencies -它确实具有 dependencyManagement 部分,但未提供其中已编译的范围。一些依赖项虽然具有作用域导入。我不知道这种导入范围内的依赖关系是否对我有效。来自这里的一些示例:

<dependencyManagement>
    <dependencies>
        ...
        <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-reactor-netty</artifactId>
           <version>2.1.3.RELEASE</version>
       </dependency>
       ...
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-bom</artifactId>
            <version>${reactor-bom.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
       ...
    </dependencies>
</dependencyManagement>

我在以前的更新中发布的 spring-boot-starter-reactor-netty 的部分内容。

更新 Andy Wilkinson 回答后只是为了澄清-jar中不包含此类依赖项,似乎spring boot maven插件在这里的工作方式有所不同:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <scope>provided</scope>
</dependency>

3 个答案:

答案 0 :(得分:1)

父pom可能有一个dependencyManagement部分会覆盖作用域/版本。

答案 1 :(得分:1)

Spring Boot胖罐旨在包含运行该应用程序所需的所有内容。启动JVM时,您不能同时使用-jar-classpath,这意味着jar需要包含提供的依赖项,并且没有其他方法可以使它们进入类路径

Spring Boot的Maven插件在documentation中对此行为进行了说明,其中指出以下内容:

  

上面的示例重新打包了在Maven生命周期的打包阶段构建的jar或war,包括项目中定义的所有提供的依赖项。

如果您不希望应用程序的jar打包任何依赖项,即您希望它是普通的jar,而不是胖的jar,那么您可能不想使用Spring Boot的Maven插件来构建它。如果从示例项目的pom.xml文件中删除它,然后对其进行构建,则所得的jar将具有以下内容:

$ unzip -l target/MavenProvidedTest-0.0.1-SNAPSHOT.jar 
Archive:  target/MavenProvidedTest-0.0.1-SNAPSHOT.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
      329  02-22-2019 11:33   META-INF/MANIFEST.MF
        0  02-22-2019 11:33   META-INF/
        0  02-22-2019 11:33   META-INF/maven/
        0  02-22-2019 11:33   META-INF/maven/io.spring/
        0  02-22-2019 11:33   META-INF/maven/io.spring/MavenProvidedTest/
        1  02-22-2019 11:33   application.properties
     1403  02-22-2019 11:33   META-INF/maven/io.spring/MavenProvidedTest/pom.xml
      101  02-22-2019 11:33   META-INF/maven/io.spring/MavenProvidedTest/pom.properties
---------                     -------
     1834                     8 files

如果您希望包括一些但不是全部依赖项,则可以继续使用Spring Boot的Maven插件和exclude一些依赖项。

答案 2 :(得分:0)

根据您的问题,我知道您需要一个瘦的可执行jar。因为您可以使用spring-thin-launcher插件。它将排除打包为jar的一部分的依赖项,但会在首次运行时从maven下载,或者您可以提供自己的本地仓库,可以在其中找到所有jar文件。

有关详细信息,请参阅此tutorial