Java 弹簧&x27;s AsyncRestTemplate不处理压缩内容,获取压缩内容而不是json对象

Java 弹簧&x27;s AsyncRestTemplate不处理压缩内容,获取压缩内容而不是json对象,java,json,spring-boot,spring-web,asyncresttemplate,Java,Json,Spring Boot,Spring Web,Asyncresttemplate,我已经在我的spring boot应用程序上启用了内容压缩,每个API的响应都被压缩了,但如果我使用RestTemplate点击这些API,我会得到如下内容 "\u001F�\b\u0000\u0000\u0000\u0000\u0000\u0000\u0000�}��8��¨OtD���1��]�m�mo��v�_LlP\u0014J�4E��(�����C�:\u0012<D\u0010����\b۲��\u0004\u0012@\" 我想建议您不要手动执行压缩,而只是告诉Sprin

我已经在我的spring boot应用程序上启用了内容压缩,每个API的响应都被压缩了,但如果我使用
RestTemplate
点击这些API,我会得到如下内容

"\u001F�\b\u0000\u0000\u0000\u0000\u0000\u0000\u0000�}��8��¨OtD���1��]�m�mo��v�_LlP\u0014J�4E��(�����C�:\u0012<D\u0010����\b۲��\u0004\u0012@\"

我想建议您不要手动执行压缩,而只是告诉Spring为您执行压缩(实际上压缩将由web服务器(例如Tomcat)完成,但Spring将为您执行)。通常在春季,像压缩这样的事情,编码可以只通过一个属性打开


请看

一个简单的解决方法是添加一个带有AsyncRestTemplate的ResponseInterceptor,它可以自动解压缩响应。您收到的ListenableFuture将已经有解压缩响应。 下面是一个例子:

AsyncRestTemplate getAsyncRestTemplate() {
    final HttpComponentsAsyncClientHttpRequestFactory httpComponentsAsyncClientHttpRequestFactory =
            new HttpComponentsAsyncClientHttpRequestFactory();

    final AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(httpComponentsAsyncClientHttpRequestFactory);
    asyncRestTemplate.setInterceptors(Collections.singletonList((httpRequest, bytes, asyncClientHttpRequestExecution) -> {
        if (!httpRequest.getHeaders().containsKey(HttpHeaders.ACCEPT_ENCODING)) {
            httpRequest.getHeaders().set(HttpHeaders.ACCEPT_ENCODING, "gzip");
        }
        final ListenableFuture<ClientHttpResponse> future = asyncClientHttpRequestExecution.executeAsync(httpRequest, bytes);
        return new ListenableFutureAdapter<ClientHttpResponse, ClientHttpResponse>(future) {
            @Override
            protected ClientHttpResponse adapt(ClientHttpResponse clientHttpResponse) throws ExecutionException {
                return new InflatedClientHttpResponse(clientHttpResponse);
            }
        };
    }));
    return asyncRestTemplate;

}

public class InflatedClientHttpResponse implements ClientHttpResponse {
    private final ClientHttpResponse clientHttpResponse;
    private final Boolean isCompressed;

    public InflatedClientHttpResponse(ClientHttpResponse clientHttpResponse) {
        this.clientHttpResponse = clientHttpResponse;
        final HttpHeaders httpHeaders = clientHttpResponse.getHeaders();

        final List<String> contentEncoding = httpHeaders.get(HttpHeaders.CONTENT_ENCODING);
        if (contentEncoding != null && contentEncoding.contains("gzip")) {
            isCompressed = true;
        } else {
            isCompressed = false;
        }

        httpHeaders.remove(HttpHeaders.CONTENT_ENCODING);
        httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
    }

    @Override
    public HttpStatus getStatusCode() throws IOException {
        return clientHttpResponse.getStatusCode();
    }

    @Override
    public int getRawStatusCode() throws IOException {
        return clientHttpResponse.getRawStatusCode();
    }

    @Override
    public String getStatusText() throws IOException {
        return clientHttpResponse.getStatusText();
    }

    @Override
    public void close() {
        clientHttpResponse.close();
    }

    @Override
    public InputStream getBody() throws IOException {
        if (isCompressed) {
            return new GZIPInputStream(clientHttpResponse.getBody());
        }
        return clientHttpResponse.getBody();
    }

    @Override
    public HttpHeaders getHeaders() {
        return clientHttpResponse.getHeaders();
    }
}
AsyncRestTemplate getAsyncRestTemplate(){
最终HttpComponents同步客户端前传工厂HttpComponents同步客户端前传工厂=
新的HttpComponentsAsyncClientHttpRequestFactory();
最终AsyncRestTemplate AsyncRestTemplate=新的AsyncRestTemplate(httpComponentsAsyncClientHttpRequestFactory);
asyncRestTemplate.setInterceptors(集合.singletonList((httpRequest,字节,AsyncClientHttPrequesteExecution)->{
如果(!httpRequest.getHeaders().containsKey(HttpHeaders.ACCEPT_编码)){
设置(HttpHeaders.ACCEPT_编码,“gzip”);
}
final ListenableFuture=AsyncClientHttPrequesteExecution.executeAsync(httpRequest,字节);
返回新的ListenableFutureAdapter(未来){
@凌驾
受保护的ClientHttpResponse adapt(ClientHttpResponse ClientHttpResponse)引发ExecutionException{
返回新的充气clientHttpResponse(clientHttpResponse);
}
};
}));
返回asyncRestTemplate;
}
公共类InflatedClientHttpResponse实现ClientHttpResponse{
私人最终客户TTpresponse客户TTpresponse;
私有最终布尔值被压缩;
公共充气ClientHttpResponse(ClientHttpResponse ClientHttpResponse){
this.clientHttpResponse=clientHttpResponse;
final HttpHeaders HttpHeaders=clientHttpResponse.getHeaders();
最终列表contentEncoding=httpHeaders.get(httpHeaders.CONTENT\u编码);
if(contentEncoding!=null&&contentEncoding.contains(“gzip”)){
isCompressed=true;
}否则{
isCompressed=假;
}
删除(httpHeaders.CONTENT\u编码);
httpHeaders.remove(httpHeaders.CONTENT\u LENGTH);
}
@凌驾
公共HttpStatus getStatusCode()引发IOException{
返回clientHttpResponse.getStatusCode();
}
@凌驾
public int getRawStatusCode()引发IOException{
返回clientHttpResponse.getRawStatusCode();
}
@凌驾
公共字符串getStatusText()引发IOException{
返回clientHttpResponse.getStatusText();
}
@凌驾
公众假期结束(){
clientHttpResponse.close();
}
@凌驾
公共InputStream getBody()引发IOException{
如果(已压缩){
返回新的gzip输入流(clientHttpResponse.getBody());
}
返回clientHttpResponse.getBody();
}
@凌驾
公共HttpHeaders getHeaders(){
返回clientHttpResponse.getHeaders();
}
}

是的,我不是手动操作,Spring是为我操作的。我刚刚在application.properties文件server.compression.enabled=true server.compression.mime types=application/javascript、application/x-javascript、application/json、application/xml、text/html、text/xml、text/css、text/plain中编写了这些属性
AsyncRestTemplate getAsyncRestTemplate() {
    final HttpComponentsAsyncClientHttpRequestFactory httpComponentsAsyncClientHttpRequestFactory =
            new HttpComponentsAsyncClientHttpRequestFactory();

    final AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(httpComponentsAsyncClientHttpRequestFactory);
    asyncRestTemplate.setInterceptors(Collections.singletonList((httpRequest, bytes, asyncClientHttpRequestExecution) -> {
        if (!httpRequest.getHeaders().containsKey(HttpHeaders.ACCEPT_ENCODING)) {
            httpRequest.getHeaders().set(HttpHeaders.ACCEPT_ENCODING, "gzip");
        }
        final ListenableFuture<ClientHttpResponse> future = asyncClientHttpRequestExecution.executeAsync(httpRequest, bytes);
        return new ListenableFutureAdapter<ClientHttpResponse, ClientHttpResponse>(future) {
            @Override
            protected ClientHttpResponse adapt(ClientHttpResponse clientHttpResponse) throws ExecutionException {
                return new InflatedClientHttpResponse(clientHttpResponse);
            }
        };
    }));
    return asyncRestTemplate;

}

public class InflatedClientHttpResponse implements ClientHttpResponse {
    private final ClientHttpResponse clientHttpResponse;
    private final Boolean isCompressed;

    public InflatedClientHttpResponse(ClientHttpResponse clientHttpResponse) {
        this.clientHttpResponse = clientHttpResponse;
        final HttpHeaders httpHeaders = clientHttpResponse.getHeaders();

        final List<String> contentEncoding = httpHeaders.get(HttpHeaders.CONTENT_ENCODING);
        if (contentEncoding != null && contentEncoding.contains("gzip")) {
            isCompressed = true;
        } else {
            isCompressed = false;
        }

        httpHeaders.remove(HttpHeaders.CONTENT_ENCODING);
        httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
    }

    @Override
    public HttpStatus getStatusCode() throws IOException {
        return clientHttpResponse.getStatusCode();
    }

    @Override
    public int getRawStatusCode() throws IOException {
        return clientHttpResponse.getRawStatusCode();
    }

    @Override
    public String getStatusText() throws IOException {
        return clientHttpResponse.getStatusText();
    }

    @Override
    public void close() {
        clientHttpResponse.close();
    }

    @Override
    public InputStream getBody() throws IOException {
        if (isCompressed) {
            return new GZIPInputStream(clientHttpResponse.getBody());
        }
        return clientHttpResponse.getBody();
    }

    @Override
    public HttpHeaders getHeaders() {
        return clientHttpResponse.getHeaders();
    }
}