如何使用Spring RestClient解压gzip响应体?
配置Spring RestClient自动解压Gzip响应
Spring官方文档并未提及RestClient的Gzip解压配置方法,默认情况下它不会像WebClient那样自动处理Gzip压缩的响应。要实现自动解压,可以通过以下两种方式配置:
方式一:自定义消息转换器处理解压
通过修改RestClient的消息转换器,让其在读取响应时自动解压Gzip流:
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setConnectTimeout(Duration.ofSeconds(5)); requestFactory.setReadTimeout(Duration.ofSeconds(5)); RestClient restClient = RestClient.builder() .requestFactory(requestFactory) // 添加Accept-Encoding请求头,告知服务端支持Gzip压缩 .requestInitializer(request -> request.getHeaders().set(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate") ) .messageConverters(converters -> { // 替换String消息转换器,支持Gzip解压 converters.removeIf(c -> c instanceof StringHttpMessageConverter); converters.add(new StringHttpMessageConverter() { @Override protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException { InputStream inputStream = inputMessage.getBody(); // 判断响应是否为Gzip压缩 if (isGzipEncoded(inputMessage.getHeaders())) { inputStream = new GZIPInputStream(inputStream); } return super.readInternal(clazz, wrapInputStream(inputMessage, inputStream)); } }); // 替换Jackson消息转换器,支持Gzip解压 converters.removeIf(c -> c instanceof MappingJackson2HttpMessageConverter); converters.add(new MappingJackson2HttpMessageConverter() { @Override protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException { InputStream inputStream = inputMessage.getBody(); if (isGzipEncoded(inputMessage.getHeaders())) { inputStream = new GZIPInputStream(inputStream); } return super.readInternal(clazz, wrapInputStream(inputMessage, inputStream)); } }); }) .build(); // 辅助方法:判断响应是否为Gzip编码 private boolean isGzipEncoded(HttpHeaders headers) { String encoding = headers.getFirst(HttpHeaders.CONTENT_ENCODING); return encoding != null && encoding.contains("gzip"); } // 辅助方法:包装输入流 private HttpInputMessage wrapInputStream(HttpInputMessage originalMessage, InputStream newStream) { return new HttpInputMessage() { @Override public InputStream getBody() throws IOException { return newStream; } @Override public HttpHeaders getHeaders() { return originalMessage.getHeaders(); } }; }
方式二:使用Apache HttpClient实现自动解压
借助Apache HttpClient的拦截器能力,更简洁地实现Gzip自动解压:
首先确保引入Apache HttpClient依赖:
<dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> </dependency>
然后配置RestClient:
CloseableHttpClient httpClient = HttpClientBuilder.create() // 添加请求拦截器,自动添加Accept-Encoding头 .addInterceptorFirst((HttpRequest request, HttpContext context) -> { if (!request.containsHeader(HttpHeaders.ACCEPT_ENCODING)) { request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate"); } }) // 添加响应拦截器,自动解压Gzip响应 .addInterceptorFirst((HttpResponse response, HttpContext context) -> { HttpEntity entity = response.getEntity(); if (entity != null) { Header encodingHeader = entity.getContentEncoding(); if (encodingHeader != null) { for (HeaderElement element : encodingHeader.getElements()) { if ("gzip".equalsIgnoreCase(element.getName())) { response.setEntity(new GzipDecompressingEntity(entity)); return; } } } } }) .build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); RestClient restClient = RestClient.builder() .requestFactory(requestFactory) .build();
这种方式无需修改消息转换器,由HttpClient底层自动处理压缩和解压逻辑,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Ignasi
相关产品推荐
相关产品推荐

