WebService CXF --- 傳輸文件MTOM

1、幾個相關的概念html

  一、MTOM基礎概念     java

     官方介紹:http://cxf.apache.org/docs/mtom-attachments-with-jaxb.htmlspring

      MTOM(Message Transmission Optimization Mechanism)消息優化傳輸機制。apache

  它提出的模型適用於大量數據的交互狀況。針對Base64編碼狀況帶來的開銷提出的解決方案。當數據量小的時候,SOAP依然使用XML進行消息的傳遞。網絡

    消息傳輸優化機制 (MTOM) 標準容許將消息中包含的大型數據元素外部化,並將其做爲無任何特殊編碼的二進制數據隨消息一塊兒傳送。MTOM 消息會打包爲多部分/相關 MIME 序列,放在SOAP 消息中一塊兒傳送。app

    可是在大量數據狀況下,若是數據依然進行Base64編碼,會帶來33%的額外開銷,這樣的狀況對於大量數據交換的狀況是沒法容忍的。MTOM 就是針對SOAP 消息傳輸的基礎上提出的改進辦法。對於大量數據的傳遞,不會進行進行Base64編碼,而是直接以附件的二進制原始數據的形式封裝在SOAP消息的 MIME 部分,進行傳輸。SOAP 消息經過指向隨其發送的 MIME 部分來引用二進制內容,另外包括SOAP基本的XML 數據,這些仍是Base64編碼。由於此模型與簡單郵件協議SMTP 模型基本一致。測試

     MTOM經過簡化大量數據的編碼過程,從而提升數據的處理效率。由於SOAP消息等必要的信息,MTOM 也有一些必要的開銷。MTOM僅在二進制數據元素的大小超過大約 1 KB 時,才能體現出其優點。優化

     什麼是BASE64編碼、MTOM消息優化傳輸機制、MIME。這些對於咱們理解MTOM消息優化傳輸機制問題很是的必要。ui

 

  二、BASE64編碼 this

    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編碼的語言。

 

三、MIME

   MIME表示多用途Internet郵件擴允協議。MIME擴允了基本的面向文本的Internet郵件系統,以即可以在消息中包含二進制附件。MIME(Multipurpose Internet Mail Extentions),通常譯做"多用途的網絡郵件擴充協議"。顧名思義,它能夠傳送多媒體文件。 MIME (Multipurpose Internet Mail Extensions,多目的Internet郵件擴展)是建立用於電子郵件交換,網絡文檔,及企業網和Internet上的其餘應用程序中的文件格式的規範。

 

 

2、MTOM之旅

   一、POJO

     

Java代碼 

 收藏代碼

  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 等,但要考慮到客戶端是否支持。

 

 二、接口類

    

Java代碼 

 收藏代碼

  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會有所不一樣,並且生成的客戶端代碼也會有所不一樣。

 

 實現類:

      

Java代碼 

 收藏代碼

  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.         User user = new User();  
  21.         user.setName("wy");  
  22.         user.setDataHandler(new DataHandler(new FileDataSource(new File("D:\\resume\\logo.gif"))));  
  23.         return user;  
  24.     }  
  25. }  

 

三、服務端配置

   applicationContext-cxf.xml

  

Xml代碼 

 收藏代碼

  1. <?xml version="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:schemaLocation="  
  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.     http://cxf.apache.org/schemas/jaxws.xsd">  
  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命令生成客戶端。

 

這時,就能夠調用這個服務了:

   測試類:

  

Java代碼 

 收藏代碼

  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.         UserServiceImplService userService = 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.         System.out.println(name+"\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.         System.out.println(fileName+"\r\n"+fileType+"\r\n"+content.toString());  
  34.         //Streaming Mode   
  35.         InputStream is = dataHandler.getInputStream();  
  36.         FileOutputStream fos = new FileOutputStream("D:\\logo.gif");  
  37.         byte[] bytes = new byte[2048];  
  38.         int len = 0;  
  39.         while((len = is.read(bytes))!=-1){  
  40.             fos.write(bytes, 0, len);  
  41.         }  
  42.         fos.flush();  
  43.         fos.close();  
  44.         is.close();  
  45.     }  
  46.   
  47. }  

  

 

 來看下結果:

 

Java代碼 

 收藏代碼

  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. fileContent= org.apache.cxf.attachment.DelegatingInputStream@11e1bbf
相關文章
相關標籤/搜索