用MTOM在WCF和CXF之间传数据

用MTOM在WCF和CXF之间传数据

MTOM是一种机制,用来以原始字节形式传输包含SOAP消息的较大二进制附件,从而使所传输的消息较小。

如果不用MTOM我们也可以通过WebService传递二进制的文件, 我们先来看看不用MTOM的时候是什么样子的。

服务端是一个简单的WebService方法, 接受一个byte数组,计算其中的字符数并返回。

@WebService
public interface CounterService {
    int count(byte[] data);
}


@Service
@WebService(endpointInterface = "com.cccis.ws.CounterService")
public class CounterServiceImpl implements CounterService {

    @Override
    public int count(byte[] data) {
        try {
            String text = GZipUtils.decompressText(data, "utf-8");
            return text.length();
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
    }
}


<bean id="countServiceImpl" class="com.cccis.ws.CounterServiceImpl" />

<jaxws:endpoint 
      id="countService" 
      implementor="#countServiceImpl" 
      serviceName="countService"
      address="/countService" />


客户端是一个简单的WCF的客户端,读取一个文件把字节传递给count方法

try
{
    var service = new ServiceReference1.CounterServiceClient();
    var text = File.ReadAllText("c:\\words");

    var memoryStream = new MemoryStream();
    var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress);
    var rawData = Encoding.UTF8.GetBytes(text);
    gzipStream.Write(rawData, 0 , rawData.Length);
    gzipStream.Close();
    var len = service.count(memoryStream.ToArray());
    Console.WriteLine("lenght = {0}", len);

}
catch (Exception e)
{
    Console.WriteLine(e.Message);
    Console.WriteLine(e.StackTrace);
}
Console.Read();
}


app.config配置如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="countServiceSoapBinding" />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://192.168.2.3:8080/binder/services/countService"
                binding="basicHttpBinding" bindingConfiguration="countServiceSoapBinding"
                contract="ServiceReference1.CounterService" name="CounterServiceImplPort" />
        </client>
    </system.serviceModel>
</configuration>


运行一些客户端,就可以让服务器计算字符数了, 我们来看看HTTP请求是什么样子的。



Content-Length: 1140036, 传输的内容都是base64编码的。也就是说传给count参数的byte数组被编码成Base64传输的。所以比实际的byte数组要大很多,我们的数组实际是854866, 大了近30%。

HTTP请求的内容



使用MTOM的情况

服务端

@WebService
public interface CounterService {
    int count(@XmlMimeType("application/octet-stream") DataHandler value);
}


@Service
@WebService(endpointInterface = "com.cccis.ws.CounterService")
public class CounterServiceImpl implements CounterService {

    @Override
    public int count(DataHandler data) {
        try {
            String text = GZipUtils.decompressText(data.getInputStream(), "utf-8");
            return text.length();
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
    }
}


Java接口的参数类型由原来的b yte[]变成 DataHanlder, 最重要的是要在前面加一个 @XmlMimeType("application/octet-stream")

配置文件:
    <jaxws:endpoint id="countService" implementor="#countServiceImpl"
        serviceName="countService" address="/countService">
        <jaxws:properties>
            <entry key="mtom-enabled" value="true" />
        </jaxws:properties>
    </jaxws:endpoint>


添加了一个属性 mtom-enabled=true

加了上面的变化就OK了。

再来看看WCF 客户端的变化

只需要配置文件app.config发生变化就行了

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="countServiceSoapBinding">
          <mtomMessageEncoding messageVersion="Soap11"></mtomMessageEncoding>
          <httpTransport/>
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://192.168.2.3:8080/binder/services/countService"
          binding="customBinding" bindingConfiguration="countServiceSoapBinding"
          contract="ServiceReference1.CounterService" name="CounterServiceImplPort" />
    </client>
  </system.serviceModel>
</configuration>


由原来的basicHttpBinding变成customBinding,然后使用 mtomMessageEncoding即可。 这里需要注意一点的是如果不设置messageVersion="Soap11" 默认使用的是Soap1.2 但是在我的环境里CXF对Soap1.2+MTOM的方式支持的好像不是很好。 所有退而求其次用Soap1.1。

最后我们看一下MTOM的方式的HTTP请求到底是什么样子的



我们可以看到Content-Length: 855855 比原来不用MTOM的1140036小了不少。 SOAP消息的样子也和原来的有很大的不同。



本文的源代码在附件中

猜你喜欢

转载自zjumty.iteye.com/blog/1892397