【问题标题】:Maven scope - provided, but spring-boot-starter-webflux dependencies included in compiled jar. Why?Maven 范围 - 已提供,但 spring-boot-starter-webflux 依赖项包含在已编译的 jar 中。为什么?
【发布时间】:2019-07-15 17:05:30
【问题描述】:

我想构建 jar 文件库而不包含依赖项,因为它们将位于将使用该库的应用程序的类路径中。我为此使用 ma​​ven scope - provided 并且所有依赖项都被排除在外,但仍然很少。我发现它们来自 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 兆字节。

更新JF Meier的建议下,我尝试了mvn dependency:tree,发现两个库的作用域为compile

[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 包含的库没有将 scope 覆盖为 compile。这是否意味着这两个库构建错误或出于某种原因以这种方式构建?而且我仍然不清楚如何以简单的方式删除似乎具有覆盖范围的依赖项?

我尝试将版本号放入我的 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>

【问题讨论】:

    标签: maven spring-boot spring-webflux


    【解决方案1】:

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

    documentation for Spring Boot's Maven Plugin 中描述了此行为,其中说明如下:

    上面的示例重新打包了在 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.1.3.RELEASE,而我将 1.5.6.RELEASE 与 MODULE 一起使用。我仍在使用 java 8 并且曾经以这种方式拥有库 jar。此模块布局不在 2.x 版本中(请记住我们与您讨论过文档更新)。布局模块意味着不是可运行的 jar - 而是库。所以我根本不需要 java -jar 。无论如何我都会尝试你的想法来删除 Spring Boot Maven 插件。
    • 如果你需要模块布局,你应该到处使用 Spring Boot 1.5,而不是使用 Spring Boot 2.1 并且只降级 Maven 插件。作为记录,1.5 文档还描述了 provided 依赖项的行为。
    • 这意味着 Spring Boot Maven 插件 1.x 与 Spring Boot 2.x 不兼容。这对我来说是新的——可能我错过了一些东西。我在 Spring Boot 2.x 上工作了一段时间,但无法找到使用 Spring Boot 插件 2.x 构建 jar 库并返回 1.x 插件的方法(我仍在使用 java 8)。另请参阅我的问题中的更新 - 我只是尝试使用其他依赖项,但它们不包含在 jar 中。
    • 我不明白你还在使用 Java 8 的意义。Spring Boot 2.x 支持 Java 8。
    • 据我了解,模块布局已在 spring boot maven 插件 2.x 中删除,因为较新的 java 9 有模块。
    【解决方案2】:

    父 pom 可能有一个覆盖范围/版本的 dependencyManagement 部分。

    【讨论】:

    • 你好。谢谢你的想法。我试图检查依赖项 pom 文件并更新了我的问题。我仍然不清楚为什么仅在少数库中覆盖范围以及如何处理它。
    • 坦率地说,我不明白您尝试了什么(在您的编辑中)。我的建议是:去 spring-boot-starter-parent ,这是你的父母,看看它是否有 &lt;dependencyManagement&gt; 部分。查看它是否设置了一些意外“编译”而不是“提供”的依赖项。
    • 你好。是的,我可能做了一些奇怪的事情,因为不明白这一切。父级没有 这样的部分,但它还有一个父级和编译的范围根本没有使用。不过,一些依赖项具有范围导入。
    • 没有范围的依赖项具有隐式范围编译。 Scope import 从定义的文件中导入一个列表(所以在那里查找依赖项)。
    • 不幸的是,我无法理解它的工作原理并放弃了。不过感谢您的努力。
    【解决方案3】:

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

    详情请参考此tutorial

    【讨论】:

      猜你喜欢
      • 2017-01-01
      • 2016-05-28
      • 1970-01-01
      • 2022-12-18
      • 2012-11-11
      • 2017-06-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-18
      相关资源
      最近更新 更多