CXF之二(上传及下载附件)
? ? 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 进行注解,标注这是一个附件类型的数据。
?
? ?这里拿上传及下载用户的图像为例子,大致的说下CXF的MTOM协议对附件的支持
?
? ?1、POJO对象类的处理
?
?
@XmlRootElement(name="User")@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name="User")public class User {@XmlElement(nillable=true)private Long id;@XmlElement(nillable=true)private String name;@XmlElement(nillable=true)private int age;@XmlMimeType("application/octet-stream")private DataHandler imageData;//人员的图像public User() {}public User(Long id, String name, int age) {super();this.id = id;this.name = name;this.age = age;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public DataHandler getImageData() {return imageData;}public void setImageData(DataHandler imageData) {this.imageData = imageData;}}?
? 注意:图像的类型必须为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
? t添加代码如下: ??
?
?
<jaxws:properties><entry key="mtom-enabled" value="true" /> </jaxws:properties>?
?
?
这段内容加到<jaxws:server … 、<jaxws:endpoint … 、<jaxws:client … 之间即可,例如:
?
?
?
<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>?
?
?
?
也可以使用Java Code 实现启用MTOM
?
3、具体实现
? ?(1)HelloWorld.java接口添加如下两个方法
?
?
@WebMethodpublic User getUser();@WebMethodpublic void updateUser(@WebParam(name="user")User user);?
?
?
(2)HellWorld.java实现接口添加的两个方法
?
?
/** * <修改用户信息,包括上传用户的图像 * 创 建 人: XX * 创建时间: 2012-9-26 下午04:50:23 * @param user * @see [类、类#方法、类#成员] */public void updateUser(User user){System.out.println("姓名:"+user.getName()+",年龄:"+user.getAge());DataHandler handler = user.getImageData();try {InputStream is = handler.getInputStream();OutputStream os = new FileOutputStream(new File("c:\\test11.jpg"));byte[] b = new byte[100000];int bytesRead = 0;while ((bytesRead = is.read(b)) != -1) {os.write(b, 0, bytesRead);}os.flush();os.close();is.close();} catch (IOException e) {e.printStackTrace();}}/** * 查询用户信息,包括以附件的形式返回用户的图像 * 创 建 人: XX * 创建时间: 2012-9-26 下午04:49:43 * @return * @see [类、类#方法、类#成员] */public User getUser(){User user =new User(11L,"李四",21);user.setImageData(new DataHandler(new FileDataSource(new File("d:"+File.separator)+"test.jpg")));return user;}?
?
?
4、测试
?
?
User user =client.getUser(); //修改用户信息,包括上传图像user =new User(12L,"王五",23);DataSource source = new FileDataSource(new File("d:"+File.separator+"test.jpg"));user.setImageData(new DataHandler(source));client.updateUser(user);//查询用户信息InputStream is = user.getImageData().getDataSource().getInputStream();OutputStream os = new FileOutputStream(new File("d:"+File.separator+"test11.jpg"));byte[] b = new byte[100000];int bytesRead = 0;while ((bytesRead = is.read(b)) != -1) {os.write(b, 0, bytesRead);}os.close();is.close();?
?
?
?附件中的Demo所需要的jar,请在【CXF之一 (与Spring整合)】中下载
?
?