CXF实现MTOM协议

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

 MTOM 方式中要传输的附件必须使用javax.activation.DataHandler 类,然后对象类型还要使用@javax.xml.binding.annotation.XmlMimeType 进行注解,标注这是一个附件类型的数据。

 

1、POJO对象类的处理

  1. @XmlRootElement(name="User")  
  2. @XmlAccessorType(XmlAccessType.FIELD)  
  3. @XmlType(name="User")  
  4. public class User {  
  5.       
  6.     @XmlElement(nillable=true)  
  7.     private Long id;  
  8.       
  9.     @XmlElement(nillable=true)  
  10.     private String name;  
  11.       
  12.     @XmlElement(nillable=true)  
  13.     private int age;  
  14.   
  15.     @XmlMimeType("application/octet-stream")  
  16.     private DataHandler imageData;  //人员的图像  
  17.       
  18.     public User() {}  
  19.       
  20.     public User(Long id, String name, int age) {  
  21.         super();  
  22.         this.id = id;  
  23.         this.name = name;  
  24.         this.age = age;  
  25.     }  

 注意:图像的类型必须为DataHandle类型。这里标注imageData 是一个二进制文件(application/octet-stream),当然你也可以使用具体的MIME类型,譬如:image/jpg、image/gif 等,但你要考虑客户端是否有对应的类型(因为JAVA语言之外的客户端的特性未必是你完全了解的),而且javax.activation.*中的MIME 的相关API 可以完成MIME 类型的自动识别。这里你要注意的是必须在类上使用@XmlAccessorType(FIELD)注解,标注JAXB 在进行JAVA 对象与XML 之间进行转换时只关注字段,而不关注属性(getXXX()方法),否则发布Web 服务时会报出现了两个imageData 属性的错误

 

2、让你要在服务端和客户端分别启用MTOM 支持。可以与spring整合后,可以修改CXF的spring配置文件,来启用MTOM

  1. <jaxws:properties>  
  2.     <entry key="mtom-enabled" value="true" />  
  3.   </jaxws:properties>

这段内容加到<jaxws:server … 、<jaxws:endpoint … 、<jaxws:client … 之间即可

 

3、具体实现

   (1)HelloWorld.java接口添加如下两个方法

 

 

Java代码  收藏代码
  1. @WebMethod  
  2.     public User getUser();  
  3.       
  4.     @WebMethod  
  5.     public void updateUser(@WebParam(name="user")User user);  

 

2)HellWorld.java实现接口添加的两个方法

 

 

Java代码  收藏代码
  1. /** 
  2.  * <修改用户信息,包括上传用户的图像 
  3.  * 创 建 人:  XX 
  4.  * 创建时间:  2012-9-26 下午04:50:23   
  5.  * @param user 
  6.  * @see [类、类#方法、类#成员] 
  7.  */  
  8. public void updateUser(User user){  
  9.     System.out.println("姓名:"+user.getName()+",年龄:"+user.getAge());  
  10.     DataHandler handler = user.getImageData();  
  11.     try {  
  12.         InputStream is = handler.getInputStream();  
  13.         OutputStream os = new FileOutputStream(new File("c:\\test11.jpg"));  
  14.         byte[] b = new byte[100000];  
  15.         int bytesRead = 0;  
  16.         while ((bytesRead = is.read(b)) != -1) {  
  17.             os.write(b, 0, bytesRead);  
  18.         }  
  19.         os.flush();  
  20.         os.close();  
  21.         is.close();  
  22.     } catch (IOException e) {  
  23.         e.printStackTrace();  
  24.     }  
  25. }  
  26.   
  27. /** 
  28.  * 查询用户信息,包括以附件的形式返回用户的图像 
  29.  * 创 建 人:  XX 
  30.  * 创建时间:  2012-9-26 下午04:49:43   
  31.  * @return 
  32.  * @see [类、类#方法、类#成员] 
  33.  */  
  34. public User getUser(){  
  35.     User user =new User(11L,"李四",21);  
  36.     user.setImageData(new DataHandler(new FileDataSource(new File("d:"+File.separator)+"test.jpg")));  
  37.     return user;  
  38. }  

 

4、测试

 

 

Java代码  收藏代码
  1.     User user =client.getUser();  
  2.   
  3.    //修改用户信息,包括上传图像  
  4. user =new User(12L,"王五",23);  
  5. DataSource source = new FileDataSource(new File("d:"+File.separator+"test.jpg"));  
  6. user.setImageData(new DataHandler(source));  
  7. client.updateUser(user);  
  8.   
  9. //查询用户信息  
  10. InputStream is = user.getImageData().getDataSource().getInputStream();  
  11. OutputStream os = new FileOutputStream(new File("d:"+File.separator+"test11.jpg"));  
  12. byte[] b = new byte[100000];  
  13. int bytesRead = 0;  
  14. while ((bytesRead = is.read(b)) != -1) {  
  15.     os.write(b, 0, bytesRead);  
  16. }  
  17. os.close();  
  18. is.close();  

 

posted @ 2016-10-09 11:09  malcome  阅读(717)  评论(0)    收藏  举报