重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
今天就跟大家聊聊有关怎么理解WebService CXF中传输文件MTOM,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
成都创新互联公司作为成都网站建设公司,专注网站建设、网站设计,有关企业网站设计方案、改版、费用等问题,行业涉及报废汽车回收等多个领域,已为上千家企业服务,得到了客户的尊重与认可。
一、几个相关的概念
1、MTOM基础概念
官方介绍:http://cxf.apache.org/docs/mtom-attachments-with-jaxb.html
MTOM(Message Transmission Optimization Mechanism)消息优化传输机制。
它提出的模型适用于大量数据的交互情况。针对Base64编码情况带来的开销提出的解决方案。当数据量小的时候,SOAP依然使用XML进行消息的传递。
消息传输优化机制 (MTOM) 标准允许将消息中包含的大型数据元素外部化,并将其作为无任何特殊编码的二进制数据随消息一起传送。MTOM 消息会打包为多部分/相关 MIME 序列,放在SOAP 消息中一起传送。
但是在大量数据情况下,如果数据依然进行Base64编码,会带来33%的额外开销,这样的情况对于大量数据交换的情况是无法容忍的。MTOM 就是针对SOAP 消息传输的基础上提出的改进办法。对于大量数据的传递,不会进行进行Base64编码,而是直接以附件的二进制原始数据的形式封装在SOAP消息的 MIME 部分,进行传输。SOAP 消息通过指向随其发送的 MIME 部分来引用二进制内容,另外包括SOAP基本的XML 数据,这些还是Base64编码。因为此模型与简单邮件协议SMTP 模型基本一致。
MTOM通过简化大量数据的编码过程,从而提高数据的处理效率。因为SOAP消息等必要的信息,MTOM 也有一些必要的开销。MTOM仅在二进制数据元素的大小超过大约 1 KB 时,才能体现出其优势。
什么是BASE64编码、MTOM消息优化传输机制、MIME。这些对于我们理解MTOM消息优化传输机制问题非常的必要。
2、BASE64编码
BASE64编码 的原理很简单,其方法是,将输入数据流每次取6 bit(每bit代表1位二进制),不足6bit的补0,这样,每3个8位字节将编码为4个6位字节(3×8 → 4×6);不满4个字节的以“=”填充。其实这4个六位字节 仍然是8位,只不过高两位被设置为0。当一个字节只有6位有效时,它的取值空间为0 到 2的6次方减1 即63,也就是说被转换的Base64编码的每一个编码的取值空间为(0~63)。
这样就可以将3个8位字节,转换为4个字节,这4个转换的字节都可以映射到字符中。也即数据都可以使用字符编码代替。 因为转换后的字符串要比原来的多一个字节,长1/3。因此编码后的数据长度增加到4/3倍。这里也是为什么使用SOAP消息效率比MTOM低的原因。因为 SOAP使用XML语言进行消息传递,XML是基于BASE64编码的语言。
3、MIME
MIME表示多用途Internet邮件扩允协议。MIME扩允了基本的面向文本的Internet邮件系统,以便可以在消息中包含二进制附件。MIME(Multipurpose Internet Mail Extentions),一般译作"多用途的网络邮件扩充协议"。顾名思义,它可以传送多媒体文件。 MIME (Multipurpose Internet Mail Extensions,多目的Internet邮件扩展)是创建用于电子邮件交换,网络文档,及企业网和Internet上的其他应用程序中的文件格式的规范。
二、MTOM之旅
1、POJO
Java代码
package org.wy.pojo;
import javax.activation.DataHandler;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlMimeType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class User {
private String name = "wy";
private String sex = "man";
public int age = 20;
//private Address address;
//注这是一个附件类型的数据
@XmlMimeType("application/octet-stream")
private DataHandler dataHandler;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//处理复杂的对象
/*@XmlJavaTypeAdapter(AddressAdapter.class)
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}*/
public DataHandler getDataHandler() {
return dataHandler;
}
public void setDataHandler(DataHandler dataHandler) {
this.dataHandler = dataHandler;
}
}
MTOM 方式中要传输的附件必须使用javax.activation.DataHandler 类,还要注意必须在类上使用@XmlAccessorType(XmlAccessType.FIELD)注解,标注JAXB 在进行JAVA 对象与XML 之间进行转换时只关注字段,而不关注属性(getXXX()方法)。
然后使用@XmlMimeType 注解标注这是一个附件类型的数据,这里我们标注imageData 是一个二进制文件,当然你也可以使用具体的MIME类型,譬如:image/jpg、image/gif 等,但要考虑到客户端是否支持。
2、接口类
Java代码
package org.wy.service;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.soap.MTOM;
import org.wy.pojo.User;
@WebService(name="userService") //name属性标注在接口类上,可以指定wsdl中接口名称,也就是生成的客户端代码中接口类的名字。
@SOAPBinding(style = SOAPBinding.Style.RPC) //指定SOAP消息样式
@MTOM //开启MTOM功能
public interface IUserService {
public User getUser();
}
@MTOM注解用于开启MTOM功能。
@WebService注解中的name属性标注在接口类上,可以指定wsdl中接口名称,也就是生成的客户端代码中接口类的名字。
@SOAPBinding(style = SOAPBinding.Style.RPC)指定SOAP消息样式,有两个枚举值:SOAPBinding.Style.DOCUMENT(默认)和 SOAPBinding.Style.RPC,可以对比这两种方式生成的wsdl会有所不同,而且生成的客户端代码也会有所不同。
实现类:
Java代码
package org.wy.service.impl;
import java.io.File;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.jws.WebService;
import org.wy.pojo.User;
import org.wy.service.IUserService;
/**
*
* @author wy
*
*/
@WebService
public class UserServiceImpl implements IUserService{
public User getUser()
{
User user = new User();
user.setName("wy");
user.setDataHandler(new DataHandler(new FileDataSource(new File("D:\\resume\\logo.gif"))));
return user;
}
}
3、服务端配置
applicationContext-cxf.xml
Xml代码
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
在命令行键入“wsimport -p org.wy.client -keep http://localhost:8080/WebServiceCXF/services/UserService?wsdl”生成客户端代码,拷贝到工程相应文件夹
当然也可以使用CXF中的wsdl2java命令生成客户端。
这时,就可以调用这个服务了:
测试类:
Java代码
package org.wy.jdkclienttest;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.activation.DataHandler;
import org.wy.jdkclient.User;
import org.wy.jdkclient.UserServiceImplService;
/**
*
* @author wy
*
*/
public class Test {
public static void main(String[] args) throws IOException {
UserServiceImplService userService = new UserServiceImplService();
User user = userService.getUserServiceImplPort().getUser();
String name = user.getName();
int age = user.getAge();
String sex = user.getSex();
System.out.println(name+"\r\n"+age+"\r\n"+sex);
//输出传递过来的文件
DataHandler dataHandler = user.getDataHandler();
String fileName = dataHandler.getName();
String fileType = dataHandler.getContentType();
Object content = dataHandler.getContent();
System.out.println(fileName+"\r\n"+fileType+"\r\n"+content.toString());
//Streaming Mode
InputStream is = dataHandler.getInputStream();
FileOutputStream fos = new FileOutputStream("D:\\logo.gif");
byte[] bytes = new byte[2048];
int len = 0;
while((len = is.read(bytes))!=-1){
fos.write(bytes, 0, len);
}
fos.flush();
fos.close();
is.close();
}
}
来看下结果:
Java代码
2011-12-25 14:03:49 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
信息: Creating Service {http://impl.service.wy.org/}UserServiceImplService from WSDL: http://localhost:8080/WebServiceCXF/services/UserService?wsdl
name= wy
age= 20
sex= man
fileName= null
fileType= image/gif
fileContent= org.apache.cxf.attachment.DelegatingInputStream@11e1bbf
看完上述内容,你们对怎么理解WebService CXF中传输文件MTOM有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。