cxf使用MTOM实现下载文件

背景

早已经发布的项目,但是一直在下载ftp文件是有点问题,原来的项目只能下载小文件,应该介于20-100左右的文件,虽然你能应对基本的需求,但是总有一天会发现这是逃避问题,于是现在发现了,自己留的坑自己填吧!
项目是基于cxf webservice的,其中需要实现一些基本的查询以及下载功能。

相关知识点介绍(暂时假装能看得懂吧)

cxf

	Apache CXF 是一个开源的 Services 框架。
	CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services ,像 JAX-WS 。
	这些 Services 可以支持多种协议,
	比如:SOAP、XML/HTTP、RESTful HTTP 或者 CORBA ,并且可以在多种
	传输协议上运行,比如:HTTP、JMS 或者 JBI,CXF 大大简化了 Services 的创建,
	同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。

MOTM

	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 时,才能体现出其优势。

MIME

	表示多用途Internet邮件扩允协议。
	MIME扩允了基本的面向文本的Internet邮件系统,以便可以在消息中包含二进制附件。MIME(Multipurpose Internet Mail Extentions),一般译作"多用途的网络邮件扩充协议"。
	顾名思义,它可以传送多媒体文件。
	 MIME (Multipurpose Internet Mail Extensions,多目的Internet邮件扩展)是
	 创建用于电子邮件交换,网络文档,
	 及企业网和Internet上的其他应用程序中的文件格式的规范。
原理

MTOM需要XOP(XML-binary Optimized Packing)来传输二进制数据。MTOM 允许将消息中包含的大型数据元素外部化,并将其作为无任何特殊编码的二进制数据随消息一起传送。MTOM 消息会打包为多部分相关 MIME序列,放在SOAP 消息中一起传送。因此你可以看出MTOM 并不是将附件转为Base64 编码,这样可以大大的提高性能,因为二进制文件转Base64 编码会非常庞大。

所以在cxf中如何实现呢?

cxf实现MTOM

在我的项目里,我需要实现从ftp中下载文件,文件最终以byte[]形式返回。客户端调用时,将数组转换成自己需要的文件类型。

服务端

为了实现将消息中包含的大型数据元素外部话,并将其作为无任何特殊编码的二进制随消息一起传送。首先需要实现一个类,作为消息的携带者,其实就是对要上传或者下载的文件进行一个定义,具体如下:

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;  

//标注JAXB 在进行JAVA 对象与XML 之间进行转换时只关注字段,而不关注属性(getXXX()方法)
@XmlRootElement(name="resume")  
@XmlAccessorType(XmlAccessType.FIELD)  
public class Resume {  
    //需要上传下载的文件的其他属性
    private String fileName;  
    private String fileType;
	//这是一个二进制文件(application/octet-stream),
	//也可以使用具体的MIME类型,譬如:image/jpg、image/gif 等,
	//要考虑客户端是否有对应的类型,javax.activation.*中的MIME 的相关API 可以完成MIME 类型的自动识别。
    @XmlMimeType("application/octet-stream")
	//这里有人说必须是DataHandler类型,但是我这边测试用byte[]也是可以的
    private byte[] fileData;

    public byte[] getFileData() {
        return fileData;
    }

    public void setFileData(byte[] fileData) {
        this.fileData = fileData;
    }

    public String getFileName() {  
        return fileName;  
    }  
    public void setFileName(String fileName) {  
        this.fileName = fileName;  
    }  
    public String getFileType() {  
        return fileType;  
    }  
    public void setFileType(String fileType) {  
        this.fileType = fileType;  
    }  


}  

然后就是对这个类的操作,无非就是对其进行赋值,打个样:

   //对resume进行赋值
  byte[] fileData= (byte[]) downloadFtp(serviceID,url);
        String fName = url.trim();
        String temp[] = fName.split("/");
        String fileName = temp[temp.length-1];
        String file[]=fileName.split("\\.");
        Resume resume=new Resume();
         resume.setFileName(file[0]);
         resume.setFileType(file[1]);
         resume.setFileData(fileData);
         return  resume;

最后,最终要的一步:配置MTOM协议

<jaxws:properties>  
      <entry key="mtom_enabled" value="true"></entry>  
   </jaxws:properties>  

打个样:

<jaxws:endpoint id="helloWorld" implementor="#HelloWorldImpl" address="/HelloWorld" >  
    <!-- 输入日志拦截器 -->  
   <jaxws:inInterceptors>  
        <ref bean="inMessageInterceptor"/>  
   </jaxws:inInterceptors>  
   <!-- 输出日志拦截器 -->  
   <jaxws:outInterceptors>  
      <ref bean="outMessageInterceptor"/>  
   </jaxws:outInterceptors>  
   <jaxws:properties>  
      <entry key="mtom_enabled" value="true"></entry>  
   </jaxws:properties>  
</jaxws:endpoint>  

这样服务端就配置完成了。

客户端

客户端也很简单,也还是服务端那三步:

  1. 添加信息携带者,和服务端的一样
  2. 对类进行操作,取值
  3. 配置MOTM,配置方法跟实现的客户端的写法有关系,这里就不写了
总结

总的来说,这个方法在项目里使用能够满足下载大文件的需求,至少1G以内不成问题。
但是在使用中也发现部分问题:

  1. 加上了MTOM,在客户端和服务端通信方面都要有所改动,负责会造成无法通信的问题.
  2. 配置了MTOM之后,貌似会影响速度,反正在我这里至少影响2-3秒,貌似是这个协议的问题,但是具体的还没有深究
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值