如何防止嵌入式netty服务器从spring-boot-starter-webflux开始?

Fra*_*ser 12 java spring spring-boot spring-webflux

我想使用Springs new reactive webflux扩展在客户端和服务器应用程序之间建立通信.

对于依赖管理,我使用gradle.我在服务器上以及客户端上的build.gradle文件基本上是:

buildscript {
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.0.BUILD-SNAPSHOT")
    }
}

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/snapshot" }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: "io.spring.dependency-management" 

dependencies {
    compile("org.springframework.boot:spring-boot-starter-webflux")
}
Run Code Online (Sandbox Code Playgroud)

(应该注意的是2.0.0.BUILD- SNAPSHOT是一个移动目标,由于依赖内部的变化,手头的问题可能会消失一天)

当我启动服务器端应用程序时,一切都启动良好,包括启动嵌入式网络服务器.

但是当启动客户端应用程序时,也启动了一个netty服务器,导致"java.net.BindException:Address in in use",因为clientside netty服务器在与serverside netty服务器相同的端口上进行侦听.

我的问题是:为什么netty首先在客户端启动,我该如何防止它?

根据Spring-Boot文档,Spring尝试确定是否需要Web支持并相应地配置Spring Application上下文.

根据Docs,可以通过调用setWebEnvironment(false)来覆盖它.我的客户端启动代码如下所示:

@SpringBootApplication(scanBasePackages = { "com.tatics.flux.main" })
public class Client {
    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(Client.class);
        app.setWebEnvironment(false);
        app.run(Client.class, args);

        WebClient webClient = WebClient.create();

        Mono<String> result = webClient
                .post()
                .uri("http://localhost:8080/fluxService")

                // This does not work any more: .body("Hallo")
                // and must be replaced by:
                .body(BodyInserters.fromObject("Hallo"))

                .accept(MediaType.TEXT_PLAIN)
                .exchange()
                .flatMap(response -> response.bodyToMono(String.class));
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,netty仍然开始.另外我注意到setWebEnvironment(false)被标记为已弃用.

任何有关如何防止netty启动但有助于保留所有webflux依赖关系的帮助表示赞赏.

以下是自动配置报告的摘录:

=========================
AUTO-CONFIGURATION REPORT
=========================

Positive matches:
-----------------
...

ReactiveWebServerAutoConfiguration matched:
  - found ReactiveWebApplicationContext (OnWebApplicationCondition)

ReactiveWebServerAutoConfiguration#defaultReactiveWebServerCustomizer matched:
  - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.reactive.DefaultReactiveWebServerCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition)

ReactiveWebServerConfiguration.ReactorNettyAutoConfiguration matched:
  - @ConditionalOnClass found required class 'reactor.ipc.netty.http.server.HttpServer'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
  - @ConditionalOnMissingBean (types: org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)

ReactorCoreAutoConfiguration matched:
  - @ConditionalOnClass found required classes 'reactor.core.publisher.Mono', 'reactor.core.publisher.Flux'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

...

Negative matches:
-----------------
...
ReactiveWebServerConfiguration.JettyAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.eclipse.jetty.server.Server' (OnClassCondition)

ReactiveWebServerConfiguration.TomcatAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.apache.catalina.startup.Tomcat' (OnClassCondition)

ReactiveWebServerConfiguration.UndertowAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'io.undertow.Undertow' (OnClassCondition)

...

ReactiveWebServerConfiguration.JettyAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.eclipse.jetty.server.Server' (OnClassCondition)

ReactiveWebServerConfiguration.TomcatAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'org.apache.catalina.startup.Tomcat' (OnClassCondition)

ReactiveWebServerConfiguration.UndertowAutoConfiguration:
  Did not match:
     - @ConditionalOnClass did not find required class 'io.undertow.Undertow' (OnClassCondition)
Run Code Online (Sandbox Code Playgroud)

Bri*_*zel 10

您的代码的主要问题是您当前正在创建一个SpringApplication,然后您自定义它 - 最终删除所有内容并运行静态方法run(Object primarySource, String... args).

以下应该有效:

@SpringBootApplication
public class Client {

    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(Client.class);
        app.setWebApplicationType(WebApplicationType.NONE);
        app.run(args);
    }

    @Bean
    public CommandLineRunner myCommandLineRunner() {
      return args -> {
        // we have to block here, since command line runners don't
        // consume reactive types and simply return after the execution
        String result = WebClient.create("http://localhost:8080")
                .post()
                .uri("/fluxService")
                .body("Hallo")
                .accept(MediaType.TEXT_PLAIN)
                .retrieve()
                .bodyToMono(String.class)
                .block();
        // print the result?
      };
    }
}
Run Code Online (Sandbox Code Playgroud)

如果没有,请使用--debug标志运行您的应用程序,并将自动配置报告的相关部分添加到您的问题中,尤其是处理服务器的自动配置.

  • 这是关于如何[禁用内部Web服务器]的spring文档(https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html#howto-禁用网络服务器)。在大多数情况下,如果有应用程序属性,也可以在Java代码中进行设置,就像@BrianClozel所示。 (2认同)

Yan*_*Pak 5

除了@Brian_Clozel答案:

您可以通过在application.yml中指定来禁用Netty(或任何其他服务器):

spring.main.web-application-type: none
Run Code Online (Sandbox Code Playgroud)

或application.properties:

spring.main.web-application-type=none
Run Code Online (Sandbox Code Playgroud)