当前位置: 首页 > 面试题库 >

如何使用Spring RestTemplate压缩HTTP请求?

凤明朗
2023-03-14
问题内容

如何gzip HTTP 请求 ,由创建org.springframework.web.client.RestTemplate?

我正在使用Spring 4.2.6Spring Boot 1.3.5(Java SE,而不是Web浏览器中的Android或Javascript)。

我正在提出一些非常大的POST请求,并且我希望压缩 请求正文


问题答案:

我提出了两种解决方案,一种更简单,无需流传输,另一种支持流传输。

如果您 不需要流式传输 ,请使用custom
ClientHttpRequestInterceptor,一个Spring功能。

RestTemplate rt = new RestTemplate();
rt.setInterceptors(Collections.singletonList(interceptor));

interceptor可能在哪里:

ClientHttpRequestInterceptor interceptor = new ClientHttpRequestInterceptor() {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
            throws IOException {
        request.getHeaders().add("Content-Encoding", "gzip");
        byte[] gzipped = getGzip(body);
        return execution.execute(request, gzipped);
    } 
 }

getGzip我复制了

    private byte[] getGzip(byte[] body) throws IOException {

        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        try {
            GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
            try {
                zipStream.write(body);
            } finally {
                zipStream.close();
            }
        } finally {
            byteStream.close();
        }

        byte[] compressedData = byteStream.toByteArray();
        return compressedData;

    }

配置拦截器后,所有请求将被压缩。

这种方法的缺点是它不支持流式传输,因为ClientHttpRequestInterceptor将内容作为byte[]

如果您 需要流式传输,请 创建一个custom
ClientHttpRequestFactory,说出来GZipClientHttpRequestFactory,然后像这样使用它:

    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setBufferRequestBody(false);
    ClientHttpRequestFactory gzipRequestFactory = new GZipClientHttpRequestFactory(requestFactory);
    RestTemplate rt = new RestTemplate(gzipRequestFactory);

哪里GZipClientHttpRequestFactory是:

public class GZipClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper {

    public GZipClientHttpRequestFactory(ClientHttpRequestFactory requestFactory) {
        super(requestFactory);
    }

    @Override
    protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory)
            throws IOException {
        ClientHttpRequest delegate = requestFactory.createRequest(uri, httpMethod);
        return new ZippedClientHttpRequest(delegate);
    }

}

并且ZippedClientHttpRequest是:

public class ZippedClientHttpRequest extends WrapperClientHttpRequest
{
    private GZIPOutputStream zip;

    public ZippedClientHttpRequest(ClientHttpRequest delegate) {
        super(delegate);
        delegate.getHeaders().add("Content-Encoding", "gzip");
        // here or in getBody could add content-length to avoid chunking
        // but is it available ? 
        // delegate.getHeaders().add("Content-Length", "39");

    }

    @Override
    public OutputStream getBody() throws IOException {
        final OutputStream body = super.getBody();
        zip = new GZIPOutputStream(body);
        return zip;
    }

    @Override
    public ClientHttpResponse execute() throws IOException {
        if (zip!=null) zip.close();
        return super.execute();
    }

}

最后WrapperClientHttpRequest是:

public class WrapperClientHttpRequest implements ClientHttpRequest {

    private final ClientHttpRequest delegate;

    protected WrapperClientHttpRequest(ClientHttpRequest delegate) {
        super();
        if (delegate==null)
            throw new IllegalArgumentException("null delegate");
        this.delegate = delegate;
    }

    protected final ClientHttpRequest getDelegate() {
        return delegate;
    }

    @Override
    public OutputStream getBody() throws IOException {
        return delegate.getBody();
    }

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

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

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

    @Override
    public ClientHttpResponse execute() throws IOException {
        return delegate.execute();
    }
}

这种方法使用分块传输编码创建请求,如果知道大小,则可以设置内容长度标头来更改此请求。

ClientHttpRequestInterceptor和/或自定义ClientHttpRequestFactory方法的优点是它可以与RestTemplate的任何方法一起使用。另一种方法,传递一个RequestCallback能够仅与execute方法,这是因为RestTemplate的其它方法在内部创建他们自己的RequestCallback(S)产生的内容。



 类似资料:
  • 问题内容: 一般用例 想象一个客户端正在上传大量JSON。Content-Type应该保留,application/json因为它描述了实际数据。Accept-Encoding和Transfer-Encoding似乎是在告诉服务器应如何格式化响应。看来,响应为此目的明确使用了Content-Encoding头,但这不是有效的请求头。 我有什么想念的吗?有没有人找到一个优雅的解决方案? 具体用例 我

  • 由于我不是专家,我有一个关于HTTP/2的一般问题。 因此,众所周知,HTTP2压缩报头以减小消息大小。这只适用于响应还是也适用于请求?如果做一个小实验,运行两个小型HTTP服务器,一个使用版本1.1,另一个使用版本2,让两个服务器发送完全相同的内容,然后在Firefox中请求两个页面,我可以看到HTTP/2版本的响应头大小大大减小。但是,请求头的大小几乎相同。在我看来,这是有道理的,因为浏览器事

  • 问题内容: 我想问大家在请求HTTP Post消息时如何控制gzip压缩。Http请求标头中的“ Accept- Encoding:gzip”始终添加到我发送的HTTP请求中。但是我不想使用gzip压缩。我该如何处理? 我在执行http.NewRequest之前一直使用DisableCompression传输类型。而且我已经尝试将值true和false都设置为DisableCompression。

  • 我正在使用Camel的RESTendpoint来实现HTTPendpoint。我想在响应上启用HTTP有效负载压缩,但还没有找到实现它的方法。如果我向路由中添加位,它确实会压缩有效负载,但我最终会得到一个压缩文件! 有人设法在Camel中实现HTTP压缩吗? 非常感谢。 美联社

  • 问题内容: 我正在写一个分析页面,该页面将帮助我找出应用程序中的错误。从本质上讲,它允许直观地比较实际数据和日志条目,并对数据进行一些分析。 由于这仅用于调试,并且由于我将其部署在实时站点中,因此我希望它具有尽可能小的服务器负载。一些分析选项将包括相当繁重的子字符串搜索或n 2个操作,因此我将其分流给客户端。 这意味着PHP页面将仅从表和日志中获取数据,对其中的一些进行JSON并将其写出。然后,客

  • 问题内容: 我正在使用php的功能来执行HTTP请求。为了节省带宽,我决定使用添加标题。 显然,输出一个gzip编码的字符串,所以我用来解码该编码的字符串,但是将作为参数传递的数据出错。 我知道还有另一个功能可以解压缩压缩后的数据,但是它不包含在我的PHP版本中(也许仅在SVN上可用)。 我知道cUrl可以即时解码gzip流(没有任何问题),但是有人建议我使用它而不是cUrl。 您是否知道以其他方