当前位置: 首页 > 知识库问答 >
问题:

Maven scope提供,但spring-boot-starter-webflux依赖关系包含在编译的JAR中。为什么?

郭炳
2023-03-14

我想建立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+兆字节大小。

[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
  <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>

家长更新

<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-ractor-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>

共有1个答案

马祺
2023-03-14

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

Spring Boot的Maven插件的文档中描述了这种行为,其中说明如下:

上面的示例重新打包了在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插件,并排除一些依赖项。

 类似资料:
  • 我目前正在尝试将一个通过RFC连接到SAP系统的旧Java EE解决方案迁移到Quarkus。由于项目使用maven,我再次面临sapjco3的问题。来自SAP的jar库,防止该库被重命名。如果我像那样添加库作为依赖项 它将被添加到lib目录中,名称为com.sap.sapjco3-3.1.jar.不幸的是,最终以异常结束 JAVAlang.ExceptionInInitializerError:

  • 我有一个jar,build-plugins.jar和一个gradle插件,它是用build.gradle中的这个插件构建的: 这将构建build-plugins.jar。并且使用插件的项目按文件引用插件jar 问题是当我运行第二个项目的任何任务时,我得到的是“class proxy created for class XYZ”,根本原因是四个依赖项(joda-time、commons-io、str

  • 目前我的项目使用Spring启动测试如下: 但是,尽管有测试范围,它还是引入了sping-core(这是此版本中易受攻击的tpl)作为编译范围传递依赖项,并且它出现在我编译的二进制文件中。 我知道我可以通过使用测试范围显式拉动Spring核心来解决这个问题: 然而,这不应该是必要的。为什么只有在将依赖项拉入编译范围的测试中才有依赖项?

  • 我正在尝试用maven-shade插件2.1构建一个uber-jar。我希望它包括我的jar和依赖jar中的所有类。但我发现它不包括依赖jar中的类。我可能做错了什么?以下是我在pom.xml中对maven-shade插件的用法。可能是因为finalName与project.artifactid相同吗?

  • 如果我创建了一个定制的spring boot starter模块,是否需要包含依赖关系spring boot starter? 在Spring Boots的github中: 一些启动器将依赖项添加到其pom中。xml(spring boot starter web,spring boot starter thymeleaf) 其他一些起动机没有(spring-boot-starter-log4j2

  • 我正在尝试构建一个Bukkit插件。该插件还使用exp4j。最终结果需要在发布的jar中包含exp4j代码,但不包含Bukkit代码。 我按照这个答案的建议将依赖项复制到中,并使用这个答案将Bukkit声明为已提供。我的build.gradle现在看起来像这样: 这非常有效,我可以从命令行使用Gradle愉快地构建和运行项目。问题在于Intellij(或者可能是Gradle idea插件)无法识别