You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot3中RestTemplate的HttpComponentsClientHttpRequestFactory与HttpClient兼容问题求助

Spring Boot 3 下 RestTemplate 结合 HttpClient 4.5.2 的兼容方案

问题原因

Spring Boot 3 依赖的 Spring Framework 6 中,org.springframework.http.client.HttpComponentsClientHttpRequestFactory 仅适配 Apache HttpClient 5.x(对应类org.apache.hc.client5.http.classic.HttpClient),但你当前使用的是 Apache HttpClient 4.5.2(对应类org.apache.http.client.HttpClient),两者类型不兼容,导致构造方法参数匹配失败。

解决方案(保留 HttpClient 4.5.2 依赖)

由于无法升级 HttpClient 版本,提供以下可行方案:

方案1:自定义适配 HttpClient 4.x 的请求工厂

自己封装一个实现 ClientHttpRequestFactory 接口的类,适配 HttpClient 4.x 的 API,代码示例如下:

首先,确保你的 HttpClient 实例是 4.x 版本的:

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;

public HttpClient httpClient() {
    // 可根据需求添加连接池、超时等配置
    return HttpClients.createDefault();
}

然后编写自定义请求工厂类:

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ByteArrayEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.AbstractClientHttpRequest;
import org.springframework.http.client.AbstractClientHttpRequestFactoryWrapper;
import org.springframework.http.client.AbstractClientHttpResponse;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;

public class HttpComponents4ClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper {

    private final HttpClient httpClient;

    public HttpComponents4ClientHttpRequestFactory(HttpClient httpClient) {
        super(null);
        this.httpClient = httpClient;
    }

    @Override
    protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) throws IOException {
        HttpUriRequest httpRequest = buildHttpUriRequest(httpMethod, uri);
        return new HttpComponents4ClientHttpRequest(httpClient, httpRequest);
    }

    private HttpUriRequest buildHttpUriRequest(HttpMethod httpMethod, URI uri) {
        return switch (httpMethod) {
            case GET -> new HttpGet(uri);
            case POST -> new HttpPost(uri);
            case PUT -> new HttpPut(uri);
            case DELETE -> new HttpDelete(uri);
            case HEAD -> new HttpHead(uri);
            case OPTIONS -> new HttpOptions(uri);
            case PATCH -> new HttpPatch(uri);
            default -> throw new IllegalArgumentException("Unsupported HTTP method: " + httpMethod);
        };
    }

    private static class HttpComponents4ClientHttpRequest extends AbstractClientHttpRequest {

        private final HttpClient httpClient;
        private final HttpUriRequest httpRequest;

        public HttpComponents4ClientHttpRequest(HttpClient httpClient, HttpUriRequest httpRequest) {
            this.httpClient = httpClient;
            this.httpRequest = httpRequest;
        }

        @Override
        protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] body) throws IOException {
            // 复制请求头
            headers.forEach((name, values) -> httpRequest.setHeader(name, String.join(", ", values)));
            // 处理请求体
            if (body.length > 0 && httpRequest instanceof HttpEntityEnclosingRequestBase enclosingRequest) {
                enclosingRequest.setEntity(new ByteArrayEntity(body));
            }
            // 执行请求
            org.apache.http.HttpResponse httpResponse = httpClient.execute(httpRequest);
            return new HttpComponents4ClientHttpResponse(httpResponse);
        }

        @Override
        public HttpMethod getMethod() {
            return HttpMethod.valueOf(httpRequest.getMethod());
        }

        @Override
        public URI getURI() {
            return httpRequest.getURI();
        }
    }

    private static class HttpComponents4ClientHttpResponse extends AbstractClientHttpResponse {

        private final org.apache.http.HttpResponse httpResponse;

        public HttpComponents4ClientHttpResponse(org.apache.http.HttpResponse httpResponse) {
            this.httpResponse = httpResponse;
        }

        @Override
        public int getRawStatusCode() throws IOException {
            return httpResponse.getStatusLine().getStatusCode();
        }

        @Override
        public String getStatusText() throws IOException {
            return httpResponse.getStatusLine().getReasonPhrase();
        }

        @Override
        public HttpHeaders getHeaders() {
            HttpHeaders headers = new HttpHeaders();
            httpResponse.getAllHeaders().forEach(header -> headers.add(header.getName(), header.getValue()));
            return headers;
        }

        @Override
        protected InputStream getBodyInternal() throws IOException {
            return httpResponse.getEntity().getContent();
        }

        @Override
        protected void closeInternal() throws IOException {
            try {
                if (httpResponse.getEntity() != null) {
                    httpResponse.getEntity().getContent().close();
                }
            } catch (IOException ex) {
                // 忽略关闭时的异常
            }
        }
    }
}

最后在初始化 RestTemplate 时使用这个自定义工厂:

RestTemplate restTemplate = new RestTemplate(new HttpComponents4ClientHttpRequestFactory(httpClient()));

方案2:降级 Spring Web 版本(不推荐)

可以尝试将 spring-web 版本降级到 5.x(Spring Boot 2.x 对应的版本),但这会导致 Spring Boot 3 的其他功能出现兼容性问题,仅适合临时测试,不建议用于生产环境。

注意事项

  • 自定义工厂已实现常用 HTTP 方法的支持,若需要连接池、超时时间等高级配置,可在 httpClient() 方法中对 HttpClient 实例进行相应配置。
  • Spring Framework 6 已官方放弃对 HttpClient 4.x 的支持,长期来看建议升级到 HttpClient 5.x 版本以获得更好的兼容性和维护性。

内容的提问来源于stack exchange,提问作者Waseem Ishaq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 10:35:01