Spring WS请求GZIP压缩

Spring WS request GZIP compression

我正在构建一个 Spring 引导应用程序,它充当另一个 Web 服务的客户端。使用 WebServiceTemplate 发送 SOAP 消息,我有一个请求足够大以至于目标服务需要对其进行 gzip 压缩的情况。据我了解,处理压缩响应是在客户端默认完成的,但不是请求,因为这不是标准。我正在使用 Java 8、Spring Boot 2.1 和 Spring WS 3.0.3

设置 mime headers 对我来说没有用,因为它没有压缩有效负载,在应用程序中设置 server.compression.enabled(以及各种 mime-types)也没有属性,我知道它在另一端不是错误的服务,因为它确实适用于 SoapUI。

所以我的问题是 - 如何为传出请求启用 gzip 压缩?

一个对我们有用的解决方案是制作一个执行压缩的 Http 拦截器,并使用该拦截器为 WebServiceTemplate 提供一个新的 HttpComponentMessageSender。这是拦截器的样子:

import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.entity.GzipCompressingEntity;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;

import java.net.URI;
import java.net.URISyntaxException;

public class GzipHttpRequestInterceptor implements HttpRequestInterceptor {

    private final String targetHost;

    public GzipHttpRequestInterceptor(String targetUrl) throws URISyntaxException {
        this.targetHost = getDomainName(targetUrl);
    }

    private String getDomainName(String url) throws URISyntaxException {
        URI uri = new URI(url);
        String domain = uri.getHost() + ":" + uri.getPort();
        return domain.startsWith("www.") ? domain.substring(4) : domain;
    }

    @Override
    public void process(HttpRequest httpRequest, HttpContext httpContext) {
        final HttpEntityEnclosingRequest entityRequest = (HttpEntityEnclosingRequest) httpRequest;
        final HttpEntity entity = entityRequest.getEntity();
        if (entity != null) {
            final GzipCompressingEntity zippedEntity = new GzipCompressingEntity(entity);
            entityRequest.setEntity(zippedEntity);

            httpRequest.removeHeaders(HTTP.CONTENT_ENCODING);
            httpRequest.addHeader(zippedEntity.getContentEncoding());

            httpRequest.removeHeaders(HTTP.CONTENT_LEN);
            httpRequest.removeHeaders("Accept");

            httpRequest.removeHeaders(HTTP.TRANSFER_ENCODING);
            httpRequest.addHeader(HTTP.TRANSFER_ENCODING, HTTP.CHUNK_CODING);
            httpRequest.addHeader(HTTP.TARGET_HOST, targetHost);
        }
    }
}

在我们的网络配置中,我们 assemble org.apache.http.protocol.HttpProcessororg.springframework.ws.transport.http.HttpComponentsMessageSender beans:

    @Bean
    public HttpProcessor httpRequestCompressionProcessor(String url) throws URISyntaxException {
        return HttpProcessorBuilder.create()
                .add(new GzipHttpRequestInterceptor(url))
                .build();
    }

    @Bean
    public HttpComponentsMessageSender messageGzipSender(String url) throws URISyntaxException {
        return new HttpComponentsMessageSender(HttpClients.custom()
                .addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
                .setHttpProcessor(httpRequestCompressionProcessor(url))
                .build());
    }

然后使用setMessageSender(messageGzipSender(url)

将该消息发件人分配给我们的WebServiceTemplate

我想我不介意对这段代码发表评论,以防它可以得到改进并且仍然渴望听到是否有更简单的方法。