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

Spring RestTemplate中getResponseBodyAsString返回乱码问题求助

解决RestTemplate捕获HttpClientErrorException后响应体乱码问题

问题原因

响应头包含Content-Encoding: gzip,说明服务器返回的错误响应体是gzip压缩格式,但HttpClientErrorException的getResponseBodyAsString()方法默认不会自动解压gzip内容,直接读取压缩后的字节流就会出现乱码。Postman能正常显示是因为它默认支持自动识别并解压gzip响应。

解决方案

方法一:手动解压异常响应体

直接从异常中获取原始字节数组,判断是否为gzip压缩后手动解压:

catch(HttpStatusCodeException he) {
    log.error("Exception Status: {} -  {}", he.getStatusCode(), he.getStatusText());
    log.error("Exception - header {} ", he.getResponseHeaders());
    
    try {
        byte[] responseBody = he.getResponseBodyAsByteArray();
        String decodedMsg;
        // 检查响应是否为gzip压缩
        if ("gzip".equalsIgnoreCase(he.getResponseHeaders().getFirst(HttpHeaders.CONTENT_ENCODING))) {
            try (GzipInputStream gzipIn = new GzipInputStream(new ByteArrayInputStream(responseBody))) {
                decodedMsg = new String(gzipIn.readAllBytes(), StandardCharsets.UTF_8);
            }
        } else {
            // 非压缩情况直接转字符串
            decodedMsg = new String(responseBody, StandardCharsets.UTF_8);
        }
        log.error("Exception - message {} ", decodedMsg);
    } catch (IOException e) {
        log.error("Failed to decode response body", e);
    }
}

方法二:配置RestTemplate自动处理压缩

提前配置RestTemplate,让它自动发送支持gzip的请求头,并自动解压所有响应(包括异常响应):

@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    
    // 添加请求头,告知服务器可接收gzip压缩响应
    restTemplate.getInterceptors().add((request, body, execution) -> {
        request.getHeaders().add(HttpHeaders.ACCEPT_ENCODING, "gzip");
        return execution.execute(request, body);
    });
    
    // 配置请求工厂,启用自动解压
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new GzipHandlingRequestFactory(factory)));
    
    return restTemplate;
}

// 自定义请求工厂,实现响应自动解压
class GzipHandlingRequestFactory extends SimpleClientHttpRequestFactory {
    private final ClientHttpRequestFactory delegate;

    public GzipHandlingRequestFactory(ClientHttpRequestFactory delegate) {
        this.delegate = delegate;
    }

    @Override
    protected ClientHttpResponse createResponse(HttpURLConnection connection, String httpMethod) throws IOException {
        return new GzipHandlingResponse(super.createResponse(connection, httpMethod));
    }

    private static class GzipHandlingResponse implements ClientHttpResponse {
        private final ClientHttpResponse delegate;

        public GzipHandlingResponse(ClientHttpResponse delegate) {
            this.delegate = delegate;
        }

        @Override
        public InputStream getBody() throws IOException {
            InputStream body = delegate.getBody();
            String encoding = delegate.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING);
            if ("gzip".equalsIgnoreCase(encoding)) {
                return new GzipInputStream(body);
            }
            return body;
        }

        // 以下方法直接委托给原始响应实现
        @Override
        public HttpHeaders getHeaders() { return delegate.getHeaders(); }
        @Override
        public HttpStatus getStatusCode() throws IOException { return delegate.getStatusCode(); }
        @Override
        public int getRawStatusCode() throws IOException { return delegate.getRawStatusCode(); }
        @Override
        public String getStatusText() throws IOException { return delegate.getStatusText(); }
        @Override
        public void close() { delegate.close(); }
    }
}

配置完成后,无论是正常响应还是异常响应,RestTemplate都会自动处理gzip压缩,调用getResponseBodyAsString()时就能直接得到正常的JSON字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:34:58