Spring Webflux从Netty切换Tomcat嵌入式服务器后报错排查
问题分析:Spring Webflux切换嵌入式服务器到Tomcat后出现ClientHttpConnector异常
我通过修改pom.xml将Spring Webflux项目的嵌入式服务器从Netty切换为Tomcat,配置如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.fer</groupId> <artifactId>DemoReactive</artifactId> <version>0.0.1-SNAPSHOT</version> <name>DemoReactive</name> <description>Demo project for Reactive</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-reactor-netty</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
但现在出现错误:java.lang.IllegalStateException: No suitable default ClientHttpConnector found,此前使用Netty时一切正常。
原因说明
- Spring Webflux的
WebClient等客户端组件默认依赖Reactor Netty作为ClientHttpConnector的实现,用来处理客户端HTTP请求。 - 你排除了
spring-boot-starter-reactor-netty依赖后,没有提供其他替代的客户端连接器实现,导致Spring无法找到合适的默认连接器。 - 切换Tomcat只是替换了服务器端的嵌入式容器,但Webflux的客户端部分依然需要对应的HTTP连接器支持,两者是独立的组件。
解决方案
方案1:保留Reactor Netty客户端依赖(推荐)
如果只是想替换服务器端为Tomcat,无需完全移除Netty,只需保留客户端依赖即可。修改pom.xml的依赖配置:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <exclusions> <!-- 只排除Netty的服务器启动器,保留客户端相关依赖 --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-reactor-netty</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <!-- 手动添加Reactor Netty客户端依赖 --> <dependency> <groupId>io.projectreactor.netty</groupId> <artifactId>reactor-netty-http</artifactId> </dependency>
方案2:替换为Tomcat客户端连接器
如果想完全移除Netty,可以使用Tomcat的HTTP客户端实现,需要手动添加依赖并配置连接器:
- 添加Tomcat客户端依赖到pom.xml:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webflux</artifactId> </dependency> <!-- 版本需和项目中Tomcat的版本匹配,此处以2.7.5对应的Tomcat 9.0.68为例 --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-httpclient</artifactId> <version>9.0.68</version> </dependency>
- 配置
TomcatClientHttpConnector作为WebClient的连接器:
import org.apache.tomcat.httpclient.TomcatHttpClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.reactive.TomcatClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; @Configuration public class WebClientConfig { @Bean public WebClient webClient() { TomcatHttpClient tomcatHttpClient = TomcatHttpClient.create(); TomcatClientHttpConnector connector = new TomcatClientHttpConnector(tomcatHttpClient); return WebClient.builder() .clientConnector(connector) .build(); } }
内容的提问来源于stack exchange,提问作者Stefano Maglione
相关产品推荐
相关产品推荐

