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

RestTemplate整合OkHttp3如何实现gzip响应的透明处理?

问题根本原因

你当前配置未实现自动gzip解压的核心原因是:手动在拦截器添加了Accept-Encoding: gzip请求头。OkHttp默认自带透明gzip处理能力,但只要检测到用户主动设置了Accept-Encoding头,就会判定用户需要自行处理解压逻辑,自动停用内置的透明解压功能。

最优透明处理方案(和Apache HttpClient效果完全一致)

OkHttp默认就支持透明gzip,只需要移除手动加请求头的逻辑,显式指定使用OkHttp作为请求工厂即可,上层业务代码不需要任何修改,完全无感知:

1. 依赖保持不变

保留你当前的okhttp依赖即可,无需新增额外依赖:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
</dependency>

2. 修改RestTemplate Bean配置

@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
    // 可自定义OkHttpClient配置(超时、连接池等,不影响透明gzip功能)
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(Duration.ofSeconds(10))
            .readTimeout(Duration.ofSeconds(30))
            .build();
    // 构造OkHttp3请求工厂
    OkHttp3ClientHttpRequestFactory requestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClient);

    return restTemplateBuilder
            .rootUri(_endpoint)
            // 移除你之前手动添加Accept-Encoding头的拦截器!
            .requestFactory(() -> requestFactory)
            .build();
}

该方案的效果和你使用Apache HttpClient完全一致:OkHttp会自动在请求中添加Accept-Encoding: gzip头,收到响应后自动解压,同时移除响应中的Content-Encoding、Content-Length头,上层完全感知不到压缩的存在,实现完全透明处理。

备用方案:必须手动设置Accept-Encoding时的透明处理

如果你的业务场景必须手动控制Accept-Encoding头的添加,可以通过拦截器实现自动解压,也能达到透明效果:

自定义gzip解压拦截器

public class GzipDecompressInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        // 你可以在这里手动添加Accept-Encoding头
        request.getHeaders().add(HttpHeaders.ACCEPT_ENCODING, "gzip");
        ClientHttpResponse originalResponse = execution.execute(request, body);

        // 检测响应是否为gzip压缩,是则自动解压
        String contentEncoding = originalResponse.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING);
        if (contentEncoding != null && contentEncoding.contains("gzip")) {
            return new ClientHttpResponse() {
                @Override
                public HttpStatus getStatusCode() throws IOException {
                    return originalResponse.getStatusCode();
                }
                @Override
                public int getRawStatusCode() throws IOException {
                    return originalResponse.getRawStatusCode();
                }
                @Override
                public String getStatusText() throws IOException {
                    return originalResponse.getStatusText();
                }
                @Override
                public void close() {
                    originalResponse.close();
                }
                @Override
                public InputStream getBody() throws IOException {
                    return new GZIPInputStream(originalResponse.getBody());
                }
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders headers = new HttpHeaders();
                    headers.putAll(originalResponse.getHeaders());
                    // 移除压缩相关头,上层无感知
                    headers.remove(HttpHeaders.CONTENT_ENCODING);
                    headers.remove(HttpHeaders.CONTENT_LENGTH);
                    return headers;
                }
            };
        }
        return originalResponse;
    }
}

将拦截器添加到RestTemplate

@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
    OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
    OkHttp3ClientHttpRequestFactory requestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClient);

    return restTemplateBuilder
            .rootUri(_endpoint)
            .requestFactory(() -> requestFactory)
            .additionalInterceptors(new GzipDecompressInterceptor())
            .build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 17:54:03