CXF实现文件下载
  YX6XGF1y07ua 2023年11月02日 73 0


一、几个相关的概念

  1、MTOM基础概念     

      MTOM(Message Transmission Optimization Mechanism)消息优化传输机制。

  它提出的模型适用于大量数据的交互情况。针对Base64编码情况带来的开销提出的解决方案。当数据量小的时候,SOAP依然使用XML进行消息的传递。

    消息传输优化机制 (MTOM) 标准允许将消息中包含的大型数据元素外部化,并将其作为无任何特殊编码的二进制数据随消息一起传送。MTOM 消息会打包为多部分/相关 MIME 序列,放在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

     

1. package org.wy.pojo;  
2.   
3. import javax.activation.DataHandler;  
4. import javax.xml.bind.annotation.XmlAccessType;  
5. import javax.xml.bind.annotation.XmlAccessorType;  
6. import javax.xml.bind.annotation.XmlMimeType;  
7. import javax.xml.bind.annotation.XmlRootElement;  
8. import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;  
9.   
10. @XmlRootElement  
11. @XmlAccessorType(XmlAccessType.FIELD)  
12. public class User {  
13. private String name = "wy";  
14. private String sex = "man";  
15. public int age = 20;  
16.       
17. //private Address address;  
18.       
19. //注这是一个附件类型的数据  
20. @XmlMimeType("application/octet-stream")  
21. private DataHandler dataHandler;  
22.       
23. public String getName() {  
24. return name;  
25.     }  
26.   
27. public void setName(String name) {  
28. this.name = name;  
29.     }  
30.   
31. //处理复杂的对象  
32. /*@XmlJavaTypeAdapter(AddressAdapter.class)
33.     public Address getAddress() {
34.         return address;
35.     }
36.  
37.     public void setAddress(Address address) {
38.         this.address = address;
39.     }*/  
40.   
41. public DataHandler getDataHandler() {  
42. return dataHandler;  
43.     }  
44.   
45. public void setDataHandler(DataHandler dataHandler) {  
46. this.dataHandler = dataHandler;  
47.     }  
48.       
49. }


 

    MTOM 方式中要传输的附件必须使用javax.activation.DataHandler 类,还要注意必须在类上使用@XmlAccessorType(XmlAccessType.FIELD)注解,标注JAXB 在进行JAVA 对象与XML 之间进行转换时只关注字段,而不关注属性(getXXX()方法)。

    然后使用@XmlMimeType 注解标注这是一个附件类型的数据,这里我们标注imageData 是一个二进制文件,当然你也可以使用具体的MIME类型,譬如:image/jpg、image/gif 等,但要考虑到客户端是否支持。

 

 2、接口类

1. package org.wy.service;  
2.   
3. import javax.jws.WebService;  
4. import javax.jws.soap.SOAPBinding;  
5. import javax.xml.ws.soap.MTOM;  
6.   
7. import org.wy.pojo.User;  
8. @WebService(name="userService") //name属性标注在接口类上,可以指定wsdl中接口名称,也就是生成的客户端代码中接口类的名字。  
9. @SOAPBinding(style = SOAPBinding.Style.RPC) //指定SOAP消息样式  
10. @MTOM  //开启MTOM功能  
11. public interface IUserService {  
12. public User getUser();  
13. }

    @MTOM注解用于开启MTOM功能。

    @WebService注解中的name属性标注在接口类上,可以指定wsdl中接口名称,也就是生成的客户端代码中接口类的名字。

    @SOAPBinding(style = SOAPBinding.Style.RPC)指定SOAP消息样式,有两个枚举值:SOAPBinding.Style.DOCUMENT(默认)和 SOAPBinding.Style.RPC,可以对比这两种方式生成的wsdl会有所不同,而且生成的客户端代码也会有所不同。

 

 实现类:

      

1. package org.wy.service.impl;  
2.   
3. import java.io.File;  
4.   
5. import javax.activation.DataHandler;  
6. import javax.activation.FileDataSource;  
7. import javax.jws.WebService;  
8.   
9. import org.wy.pojo.User;  
10. import org.wy.service.IUserService;  
11. /**
12.  * 
13.  * @author wy
14.  *
15.  */  
16. @WebService  
17. public class UserServiceImpl implements IUserService{  
18. public User getUser()  
19.     {  
20. new User();  
21. "wy");  
22. new DataHandler(new FileDataSource(new File("D:\\resume\\logo.gif"))));  
23. return user;  
24.     }  
25. }


 

3、服务端配置

   applicationContext-cxf.xml

1. <?xml versinotallow="1.0" encoding="UTF-8" ?>  
2. <beans xmlns="http://www.springframework.org/schema/beans"  
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4. xmlns:jaxws="http://cxf.apache.org/jaxws"  
5. xsi:schemaLocatinotallow="  
6.     http://www.springframework.org/schema/beans   
7.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
8.     http://cxf.apache.org/jaxws   
9. >  
10.   
11. <!-- 导入资源 -->  
12. <import resource="classpath:META-INF/cxf/cxf.xml" />  
13. <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />  
14. <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
15.   
16. <!-- <jaxws:endpoint implementor="org.wy.service.impl.UserServiceImpl" address="/UserService"/> -->  
17.   
18. <!-- 使用bean -->  
19.       
20. <jaxws:endpoint implementor="#userService" address="/UserService" />  
21.   
22. </beans>


  

在命令行键入“wsimport -p org.wy.client -keep  http://localhost:8080/WebServiceCXF/services/UserService?wsdl”生成客户端代码,拷贝到工程相应文件夹

当然也可以使用CXF中的wsdl2java命令生成客户端。

 

这时,就可以调用这个服务了:

   测试类:

1. package org.wy.jdkclienttest;  
2.   
3. import java.io.FileOutputStream;  
4. import java.io.IOException;  
5. import java.io.InputStream;  
6.   
7. import javax.activation.DataHandler;  
8.   
9. import org.wy.jdkclient.User;  
10. import org.wy.jdkclient.UserServiceImplService;  
11.   
12. /**
13.  * 
14.  * @author wy
15.  *
16.  */  
17. public class Test {  
18.   
19. public static void main(String[] args) throws IOException {  
20. new UserServiceImplService();  
21.         User user = userService.getUserServiceImplPort().getUser();  
22.           
23.         String name = user.getName();  
24. int age = user.getAge();  
25.         String sex = user.getSex();  
26. "\r\n"+age+"\r\n"+sex);  
27.           
28. //输出传递过来的文件  
29.         DataHandler dataHandler = user.getDataHandler();  
30.         String fileName = dataHandler.getName();  
31.         String fileType = dataHandler.getContentType();  
32.         Object content = dataHandler.getContent();  
33. "\r\n"+fileType+"\r\n"+content.toString());  
34. //Streaming Mode   
35.         InputStream is = dataHandler.getInputStream();  
36. new FileOutputStream("D:\\logo.gif");  
37. byte[] bytes = new byte[2048];  
38. int len = 0;  
39. while((len = is.read(bytes))!=-1){  
40. 0, len);  
41.         }  
42.         fos.flush();  
43.         fos.close();  
44.         is.close();  
45.     }  
46.   
47. }

 

 来看下结果:

1. 2011-12-25 14:03:49 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL  
2. 信息: Creating Service {http://impl.service.wy.org/}UserServiceImplService from WSDL: http://localhost:8080/WebServiceCXF/services/UserService?wsdl  
3. name= wy  
4. age= 20  
5. sex= man  
6. fileName= null  
7. fileType= image/gif  
8. fileCnotallow= org.apache.cxf.attachment.DelegatingInputStream@11e1bbf
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  xaeiTka4h8LY   2024年05月17日   56   0   0 数据库JavaSQL
YX6XGF1y07ua