Spring Boot 2.7迁移至Spring Boot 3的HttpClient适配问题
Spring Boot 2 迁移至 Spring Boot 3 时 RestTemplate 配置问题解决
问题背景
将Spring Boot 2项目迁移至Spring Boot 3后,原RestTemplate的HttpClient配置代码出现报错,替换为HttpClient5相关类后,又遇到setDefaultSocketConfig方法不存在的问题。
原Spring Boot 2配置代码
import java.net.InetSocketAddress; import java.net.Proxy; import java.net.Proxy.Type; import java.util.concurrent.TimeUnit; import org.apache.http.HttpHost; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.config.SocketConfig; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.HttpClients; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @Configuration @RefreshScope public class RestTemplateConfig{ int timeout=10000; int readTimeout=10000; int retryCount=3; int timeToLive=5000; String rProxy="proxy.test.com"; String rPort="80"; public RestTemplate restTemplate() { return new RestTemplate(getClientHttpRequestFactory()); } private ClientHttpRequestFactory getClientHttpRequestFactory() { HttpHost proxy = new HttpHost(rProxy, Integer.parseInt(rPort)); SocketConfig socketConfig=SocketConfig.custom() .setSoTimeout(timeout) .build(); RequestConfig requestConfig=RequestConfig.custom() .setConnectionRequestTimeout(timeout) .setConnectTimeout(timeout) .setSocketTimeout(timeout) .build(); HttpClient httpClient=HttpClients.custom().setProxy(proxy) .setDefaultSocketConfig(socketConfig) .setDefaultRequestConfig(requestConfig) .setRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, true)) .setConnectionTimeToLive(timeToLive, TimeUnit.MILLISECONDS) .build(); HttpComponentsClientHttpRequestFactory rf=new HttpComponentsClientHttpRequestFactory(httpClient); rf.setConnectTimeout(timeout); rf.setReadTimeout(readTimeout); rf.setConnectionRequestTimeout(timeout); return rf; } }
第一次报错
The constructor HttpComponsentsClientHttpRequestFactory(HttpClient) is undefined.
原因是Spring Boot 3中HttpComponentsClientHttpRequestFactory的构造方法仅接受org.apache.hc.client5.http.classic.HttpClient类型,因此需要将相关类替换为HttpClient5的版本。
替换后的新报错
替换导入的HttpClient相关类为:
import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.HttpHost; import org.apache.hc.client5.http.impl.classic.HttpClients;
此时出现新报错:
The method setDefaultSocketConfig(SocketConfig) is undefined for the type HttpClientBuilder
解决方案
在HttpClient5中,SocketConfig相关配置已整合到RequestConfig或ConnectionConfig中,同时多个API名称也发生了变化,以下是适配后的完整配置代码:
import java.util.concurrent.TimeUnit; import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.HttpHost; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy; import org.apache.hc.core5.util.Timeout; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @Configuration @RefreshScope public class RestTemplateConfig{ int timeout=10000; int readTimeout=10000; int retryCount=3; int timeToLive=5000; String rProxy="proxy.test.com"; String rPort="80"; @Bean public RestTemplate restTemplate() { return new RestTemplate(getClientHttpRequestFactory()); } private ClientHttpRequestFactory getClientHttpRequestFactory() { // 配置代理 HttpHost proxy = new HttpHost(rProxy, Integer.parseInt(rPort)); // 配置请求参数,包含原SocketConfig的soTimeout设置 RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(Timeout.ofMilliseconds(timeout)) .setConnectionRequestTimeout(Timeout.ofMilliseconds(timeout)) .setResponseTimeout(Timeout.ofMilliseconds(timeout)) // 对应原SocketConfig的soTimeout .build(); // 配置连接池及连接存活时间 var connectionManager = PoolingHttpClientConnectionManagerBuilder.create() .setConnectionTimeToLive(timeToLive, TimeUnit.MILLISECONDS) .build(); // 构建HttpClient HttpClient httpClient = HttpClients.custom() .setProxy(proxy) .setDefaultRequestConfig(requestConfig) .setConnectionManager(connectionManager) .setRetryStrategy(new DefaultHttpRequestRetryStrategy(retryCount, Timeout.ofSeconds(1))) // 替换原DefaultHttpRequestRetryHandler .build(); HttpComponentsClientHttpRequestFactory rf = new HttpComponentsClientHttpRequestFactory(httpClient); rf.setConnectTimeout(timeout); rf.setReadTimeout(readTimeout); rf.setConnectionRequestTimeout(timeout); return rf; } }
关键变化说明
- SocketConfig替代:原
SocketConfig的soTimeout已整合到RequestConfig的setResponseTimeout方法中,使用Timeout.ofMilliseconds()设置超时时间。 - 重试处理器替换:
DefaultHttpRequestRetryHandler替换为DefaultHttpRequestRetryStrategy,构造参数需传入重试次数和重试间隔超时。 - 连接存活时间配置:原
setConnectionTimeToLive需通过PoolingHttpClientConnectionManagerBuilder来配置,不再直接在HttpClientBuilder上设置。 - 超时参数类型:HttpClient5中部分超时参数使用
Timeout类型替代原有的int毫秒值,需用Timeout.ofMilliseconds()或Timeout.ofSeconds()转换。
内容的提问来源于stack exchange,提问作者Kalai Selvan
相关产品推荐
相关产品推荐

