如何防止嵌入式 netty 服务器以 [=10=]-boot-starter-webflux 启动?
How to prevent embedded netty server from starting with spring-boot-starter-webflux?
我想使用 Spring 的新反应式 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")
}
(需要注意的是 2.0.0.BUILD-SNAPSHOT 是一个移动的目标,手头的问题可能有一天会消失到依赖项内的更改)
当我启动服务器端应用程序时,一切都正常启动,包括嵌入式 netty 服务器的启动。
但是当启动客户端应用程序时也会启动一个 netty 服务器,导致 "java.net.BindException: Address already in use",因为客户端 netty 服务器侦听与服务器端 netty 服务器相同的端口。
我的问题是:为什么 netty 首先在客户端启动,我该如何防止它?
根据 Spring-引导文档 Spring 尝试确定是否需要 Web 支持并相应地配置 Spring 应用程序上下文。
根据文档,这可以通过调用 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));
}
}
可惜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)
您的代码的主要问题是您当前正在创建一个 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?
};
}
}
如果不是,请运行您的应用程序使用 --debug
标志并在您的问题中添加自动配置报告的相关部分,尤其是与服务器相关的自动配置。
@Brian_Clozel补充回答:
您可以通过在 application.yml:
中指定来禁用 Netty(或任何其他服务器)
spring.main.web-application-type: none
或application.properties:
spring.main.web-application-type=none
我想使用 Spring 的新反应式 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")
}
(需要注意的是 2.0.0.BUILD-SNAPSHOT 是一个移动的目标,手头的问题可能有一天会消失到依赖项内的更改)
当我启动服务器端应用程序时,一切都正常启动,包括嵌入式 netty 服务器的启动。
但是当启动客户端应用程序时也会启动一个 netty 服务器,导致 "java.net.BindException: Address already in use",因为客户端 netty 服务器侦听与服务器端 netty 服务器相同的端口。
我的问题是:为什么 netty 首先在客户端启动,我该如何防止它?
根据 Spring-引导文档 Spring 尝试确定是否需要 Web 支持并相应地配置 Spring 应用程序上下文。
根据文档,这可以通过调用 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));
}
}
可惜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)
您的代码的主要问题是您当前正在创建一个 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?
};
}
}
如果不是,请运行您的应用程序使用 --debug
标志并在您的问题中添加自动配置报告的相关部分,尤其是与服务器相关的自动配置。
@Brian_Clozel补充回答:
您可以通过在 application.yml:
中指定来禁用 Netty(或任何其他服务器)spring.main.web-application-type: none
或application.properties:
spring.main.web-application-type=none