使用Spring WebClient+JDK HttpClient时如何设置HTTP响应超时(Spring Boot3.2.3/JDK17)
解决方案:基于JDK HTTP Client的WebClient响应超时配置
针对Spring Boot 3.2.3 + JDK17组合下,WebClient使用JDK HTTP Client作为底层客户端时的响应超时配置需求,推荐以下两种方案:
一、全局默认响应超时配置
如果需要给所有请求设置统一的响应超时,可通过自定义JdkClientHttpRequestFactory实现,直接在工厂类中配置HttpRequest.Builder的超时参数:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.http.client.JdkClientHttpRequestFactory; import org.springframework.http.client.JdkClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import java.net.URI; import java.net.http.HttpRequest; import java.time.Duration; @Configuration public class WebClientConfig { @Bean public WebClient webClient() { // 自定义请求工厂,注入全局响应超时 JdkClientHttpRequestFactory requestFactory = new JdkClientHttpRequestFactory() { @Override protected HttpRequest.Builder createHttpRequestBuilder(HttpMethod httpMethod, URI uri) { return super.createHttpRequestBuilder(httpMethod, uri) // 设置全局响应超时(示例为5秒) .timeout(Duration.ofSeconds(5)); } }; // 配置连接超时(按需设置) requestFactory.setConnectTimeout(Duration.ofSeconds(3)); return WebClient.builder() .clientConnector(new JdkClientHttpConnector(requestFactory)) .build(); } }
二、单个请求级别的响应超时配置
如果需要针对不同请求设置差异化的响应超时,可通过请求属性传递+自定义工厂类读取属性的方式实现:
1. 定义超时属性标识
public class WebClientConstants { public static final String RESPONSE_TIMEOUT_ATTR = "responseTimeout"; }
2. 自定义请求工厂读取属性
import org.springframework.http.HttpMethod; import org.springframework.http.client.JdkClientHttpRequestFactory; import java.net.URI; import java.net.http.HttpRequest; import java.time.Duration; public class CustomJdkHttpRequestFactory extends JdkClientHttpRequestFactory { @Override protected HttpRequest.Builder createHttpRequestBuilder(HttpMethod httpMethod, URI uri) { HttpRequest.Builder builder = super.createHttpRequestBuilder(httpMethod, uri); // 读取当前请求的超时属性,不存在则用默认值 Duration timeout = (Duration) getAttribute(WebClientConstants.RESPONSE_TIMEOUT_ATTR); if (timeout != null) { builder.timeout(timeout); } else { builder.timeout(Duration.ofSeconds(3)); } return builder; } }
3. 配置WebClient并设置单个请求超时
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.JdkClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import java.time.Duration; @Configuration public class WebClientConfig { @Bean public WebClient webClient() { CustomJdkHttpRequestFactory requestFactory = new CustomJdkHttpRequestFactory(); requestFactory.setConnectTimeout(Duration.ofSeconds(3)); return WebClient.builder() .clientConnector(new JdkClientHttpConnector(requestFactory)) .build(); } } // 使用时为单个请求设置专属超时 webClient.get() .uri("https://example.com/api") // 设置该请求响应超时为10秒 .attribute(WebClientConstants.RESPONSE_TIMEOUT_ATTR, Duration.ofSeconds(10)) .retrieve() .bodyToMono(String.class);
关于Mono.timeout()的说明
你提到的Mono.timeout()是Reactor订阅层面的超时控制,仅会取消订阅但不会终止底层HTTP请求,可能造成资源浪费。而上述方案是在HTTP协议层面设置超时,触发时JDK HTTP Client会主动终止请求并释放资源,更符合底层资源管控逻辑。
内容的提问来源于stack exchange,提问作者user23592751
相关产品推荐
相关产品推荐

