ksoap2:实现gzip压缩发送request data

33 篇文章 0 订阅

ksoap能不能支持gzip数据压缩传输?

我们知道webservice调用生成的xml数据挺大的,如果能压缩传输可以显著减少网络延迟,提高系统的整体性能。那么ksoap2支持gzip压缩传输么?这就是我这两天要搞清楚的问题。

接收response数据

ksoap2用于数据发送接收的类是由继承抽象类org.ksoap2.transport.Transport实现的HttTransportSE实现的
这里写图片描述
通过研究HttpTransportSE的call方法List org.ksoap2.transport.HttpTransportSE.call(String soapAction, SoapEnvelope envelope, List headers, File outputFile)
可以发现HttpTransportSE可以接收gzip压缩的数据。如果收到的是gzip,会自动将数据解压缩,以下为call方法的代码片段(中文注释为本文作者添加):


            retHeaders = connection.getResponseProperties();

            for (int i = 0; i < retHeaders.size(); i++) {
                HeaderProperty hp = (HeaderProperty)retHeaders.get(i);
                // HTTP response code has null key
                if (null == hp.getKey()) {
                    continue;
                }

                // If we know the size of the response, we should use the size to initiate vars
                if (hp.getKey().equalsIgnoreCase("content-length") ) {
                    if ( hp.getValue() != null ) {
                        try {
                            contentLength = Integer.parseInt( hp.getValue() );
                        } catch ( NumberFormatException nfe ) {
                            contentLength = 8192;
                        }
                    }
                }


                // Check the content-type header to see if we're getting back XML, in case of a
                // SOAP fault on 500 codes
                if (hp.getKey().equalsIgnoreCase("Content-Type")
                        && hp.getValue().contains("xml")) {
                    xmlContent = true;
                }


                // ignoring case since users found that all smaller case is used on some server
                // and even if it is wrong according to spec, we rather have it work..
                //判断是否为gzip压缩数据
                if (hp.getKey().equalsIgnoreCase("Content-Encoding")	                
                     && hp.getValue().equalsIgnoreCase("gzip")) {
                    gZippedContent = true;
                }
            }

            //first check the response code....
            if (status != 200) {
                //throw new IOException("HTTP request failed, HTTP status: " + status);
                throw new HttpResponseException("HTTP request failed, HTTP status: " + status, status);
            }

            if (contentLength > 0) {
                if (gZippedContent) {
	                //对gzip压缩数据解压缩
                    is = getUnZippedInputStream(
                            new BufferedInputStream(connection.openInputStream(),contentLength));
                } else {
                    is = new BufferedInputStream(connection.openInputStream(),contentLength);
                }
            }
        

发送request数据

那么发送数据呢?ksoap能不能对发送的请求数据进行gzip压缩?

下面是HttpTransportSE中发送请求数据的方法sendData(void org.ksoap2.transport.HttpTransportSE.sendData(byte[] requestData, ServiceConnection connection, SoapEnvelope envelope) )的代码,很简单可以看出,发送数据并没有gzip压缩:

    protected void sendData(byte[] requestData, ServiceConnection connection, SoapEnvelope envelope)
            throws IOException
    {
        connection.setRequestProperty("Content-Length", "" + requestData.length);
        connection.setFixedLengthStreamingMode(requestData.length);

        OutputStream os = connection.openOutputStream();
        os.write(requestData, 0, requestData.length);
        os.flush();
        os.close();
    }

现在我们可以得出结论,ksoap2的代码并没有支持gzip发送请求,我下载了它的最新版本3.6.1.也依然没有支持。

如何实现gzip压缩发送request data?

ksoap2本身就是个轻量级的soap框架,并没有做到非常完善,但因为它的框架结构比较好,使用者完全可以根据自己的需要在ksoap2的代码基础上进行功能扩展。
所以要实现gzip压缩发送request,需要自己动手实现。其实实现也不复杂:
好在sendData方法是protected,所以在不修改ksoap2代码的基础上我们只要从HttpTransportSE继承新建一个类,然后重写sendData方法,以后就用自己写的这个类来负责数据的发送和接收就可以实现完全的gzip压缩数据传输.
下面是我的实现完整代码:
HttpTransportSEWithGzip.java

package net.gdface.service.client.ksoapstub;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.Proxy;
import java.util.zip.GZIPOutputStream;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.ksoap2.transport.ServiceConnection;

/**
 * 实现Gzip发送请求<br>
 * {@link #compress}为true时发送数据前先压缩数据
 * @author guyadong
 *
 */
public class HttpTransportSEWithGzip extends HttpTransportSE {
	/**
	 * 是否启用GZIP压缩
	 */
	public boolean compress=true;
	public HttpTransportSEWithGzip(String url) {
		super(url);
	}

	public HttpTransportSEWithGzip(Proxy proxy, String url) {
		super(proxy, url);
	}

	public HttpTransportSEWithGzip(String url, int timeout) {
		super(url, timeout);
	}

	public HttpTransportSEWithGzip(Proxy proxy, String url, int timeout) {
		super(proxy, url, timeout);
	}

	public HttpTransportSEWithGzip(String url, int timeout, int contentLength) {
		super(url, timeout, contentLength);
	}

	public HttpTransportSEWithGzip(Proxy proxy, String url, int timeout, int contentLength) {
		super(proxy, url, timeout, contentLength);
	}

	@Override
	protected void sendData(byte[] requestData, ServiceConnection connection, SoapEnvelope envelope) throws IOException {
		if (this.compress) {
			// 先将数据压缩再调用父类的sendData方法完成实际数据发送
			ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(1024);
			GZIPOutputStream os = null;
			try {
				os = new GZIPOutputStream(arrayOutputStream);
				os.write(requestData, 0, requestData.length);
				os.finish();
			} finally {
				if (null != os)
					os.close();
			}
			// 指定数据编码方式为gzip压缩
			connection.setRequestProperty("Content-Encoding", "gzip");
			requestData = arrayOutputStream.toByteArray();
		}
		// 调用父类的方法完成请求数据发送
		super.sendData(requestData, connection, envelope);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值