【问题标题】:Spring WS request GZIP compressionSpring WS 请求 GZIP 压缩
【发布时间】:2019-05-07 03:11:30
【问题描述】:

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

设置 mime 标头对我没有任何作用,因为它不会压缩有效负载,在应用程序属性中设置 server.compression.enabled(以及各种 mime 类型)也不会,我知道这不是错误的服务另一端,因为它确实适用于 SoapUI。

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

【问题讨论】:

    标签: java spring-boot gzip spring-ws http-compression


    【解决方案1】:

    一个对我们有用的解决方案是制作一个 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);
            }
        }
    }
    

    在我们的 Web 配置中,我们组装了 org.apache.http.protocol.HttpProcessororg.springframework.ws.transport.http.HttpComponentsMessageSender bean:

        @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

    我想我不会介意 cmets 使用此代码,以防它可以改进并且仍然渴望听到是否有更简单的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-21
      • 2016-06-13
      • 2013-05-14
      • 2010-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多