溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解WebService CXF中傳輸文件MTOM

發(fā)布時間:2021-10-20 16:46:29 來源:億速云 閱讀:163 作者:柒染 欄目:大數(shù)據(jù)

今天就跟大家聊聊有關怎么理解WebService CXF中傳輸文件MTOM,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

一、幾個相關的概念

  1、MTOM基礎概念     

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

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

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

    消息傳輸優(yōu)化機制 (MTOM) 標準允許將消息中包含的大型數(shù)據(jù)元素外部化,并將其作為無任何特殊編碼的二進制數(shù)據(jù)隨消息一起傳送。MTOM 消息會打包為多部分/相關 MIME 序列,放在SOAP 消息中一起傳送。

    但是在大量數(shù)據(jù)情況下,如果數(shù)據(jù)依然進行Base64編碼,會帶來33%的額外開銷,這樣的情況對于大量數(shù)據(jù)交換的情況是無法容忍的。MTOM 就是針對SOAP 消息傳輸?shù)幕A上提出的改進辦法。對于大量數(shù)據(jù)的傳遞,不會進行進行Base64編碼,而是直接以附件的二進制原始數(shù)據(jù)的形式封裝在SOAP消息的 MIME 部分,進行傳輸。SOAP 消息通過指向隨其發(fā)送的 MIME 部分來引用二進制內(nèi)容,另外包括SOAP基本的XML 數(shù)據(jù),這些還是Base64編碼。因為此模型與簡單郵件協(xié)議SMTP 模型基本一致。

     MTOM通過簡化大量數(shù)據(jù)的編碼過程,從而提高數(shù)據(jù)的處理效率。因為SOAP消息等必要的信息,MTOM 也有一些必要的開銷。MTOM僅在二進制數(shù)據(jù)元素的大小超過大約 1 KB 時,才能體現(xiàn)出其優(yōu)勢。

     什么是BASE64編碼、MTOM消息優(yōu)化傳輸機制、MIME。這些對于我們理解MTOM消息優(yōu)化傳輸機制問題非常的必要。

  2、BASE64編碼 

    BASE64編碼 的原理很簡單,其方法是,將輸入數(shù)據(jù)流每次取6 bit(每bit代表1位二進制),不足6bit的補0,這樣,每3個8位字節(jié)將編碼為4個6位字節(jié)(3×8 → 4×6);不滿4個字節(jié)的以“=”填充。其實這4個六位字節(jié) 仍然是8位,只不過高兩位被設置為0。當一個字節(jié)只有6位有效時,它的取值空間為0 到 2的6次方減1 即63,也就是說被轉換的Base64編碼的每一個編碼的取值空間為(0~63)。

  這樣就可以將3個8位字節(jié),轉換為4個字節(jié),這4個轉換的字節(jié)都可以映射到字符中。也即數(shù)據(jù)都可以使用字符編碼代替。 因為轉換后的字符串要比原來的多一個字節(jié),長1/3。因此編碼后的數(shù)據(jù)長度增加到4/3倍。這里也是為什么使用SOAP消息效率比MTOM低的原因。因為 SOAP使用XML語言進行消息傳遞,XML是基于BASE64編碼的語言。

3、MIME

   MIME表示多用途Internet郵件擴允協(xié)議。MIME擴允了基本的面向文本的Internet郵件系統(tǒng),以便可以在消息中包含二進制附件。MIME(Multipurpose Internet Mail Extentions),一般譯作"多用途的網(wǎng)絡郵件擴充協(xié)議"。顧名思義,它可以傳送多媒體文件。 MIME (Multipurpose Internet Mail Extensions,多目的Internet郵件擴展)是創(chuàng)建用于電子郵件交換,網(wǎng)絡文檔,及企業(yè)網(wǎng)和Internet上的其他應用程序中的文件格式的規(guī)范。

二、MTOM之旅

   1、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.     //注這是一個附件類型的數(shù)據(jù)  

  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 方式中要傳輸?shù)母郊仨毷褂胘avax.activation.DataHandler 類,還要注意必須在類上使用@XmlAccessorType(XmlAccessType.FIELD)注解,標注JAXB 在進行JAVA 對象與XML 之間進行轉換時只關注字段,而不關注屬性(getXXX()方法)。

    然后使用@XmlMimeType 注解標注這是一個附件類型的數(shù)據(jù),這里我們標注imageData 是一個二進制文件,當然你也可以使用具體的MIME類型,譬如:image/jpg、image/gif 等,但要考慮到客戶端是否支持。

 2、接口類

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

 實現(xiàn)類:

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. }  

3、服務端配置

   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命令生成客戶端。

這時,就可以調(diào)用這個服務了:

   測試類:

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

看完上述內(nèi)容,你們對怎么理解WebService CXF中傳輸文件MTOM有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI