`

使用MTOM传输附件

 
阅读更多

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

 

package com.nantian.service;

import java.util.Date;

import javax.activation.DataHandler;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlMimeType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
	private long id;
	private String name;
	private Date birthday;
	@XmlMimeType("application/octet-stream")
	private DataHandler imageData;

	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 Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public DataHandler getImageData() {
		return imageData;
	}

	public void setImageData(DataHandler imageData) {
		this.imageData = imageData;
	}
	
}

 这里我们看到MTOM方式中要传输的附件必须使用javax.xml.bind.annotation.XmlMimeType进行注解,标注这是一个附件类型的数据,这里我们标注imageData是一个二进制数据,当然你也可以使用具体的MIME类型,譬如:image/jpgimage/gif等,但你要考虑客户端是否有相对应的类型。

这里你要注意的是必须在类上使用javax.xml.bind.annotation.XmlAccessorType(javax.xml.bind.annotation.XmlMimeType.FIELD)注解,标注JAXB在进行java对象与XML之间进行转换时只关注字段,而不关注属性。

接下来你要分别在服务端和客户端分别启用MTOM支持,Spring的配置文件如下所示:

 

<jaxws:properties>
      <entry key="mtom-enabled" value="true">
</jaxws:properties>

 这段内容加到<jaxws:server...<jaxws:endpoint...<jaxws:client...之间即可,也就是作为他们的子元素存在。如果你想使用java code实现,你可以在服务端、客户端获取javax.xml.ws.soap.SoapBinding实例,然后调用它的setMTOMEnabled(true)方法。其实从这里你可以看出JAX-WS是天然支持MTOM的,只不过默认禁用了这一功能,因为在没有附件这种大量数据要传输,MTOM的优点并不会体现出来。

我们假设服务端SEI的实现的一个方法如下所示:

public Customer selectMaxLongNameStudent(Customer c1, Customer c2) {
		Customer rs=null;
		if(c1.getName().length()>c2.getName().length())
			rs=c1;
		else
			rs=c2;
		rs.setImageData(new DataHandler(new FileDataSource(new File("d:"+File.separator+"18.jpg"))));
		return rs;
	}

 我们看到DataHandler需要DataSource进行构造,这里我们用到了javax.activation.DataSource的一个文件实现类来实现。

客户端调用代码如下所示:

 

......
String attachmentMimeType = helloServiceImpl.selectMaxLongNameStudent(c1, c2).getImageData().getDataSource().getContentType();
		System.out.println(attachmentMimeType);

 你可以看到控制台输出image/jpeg,MTOM传输附件成功。如果你使用了日志拦截器,你会看到服务端的控制台打印出了很多乱码,这些乱码就是传输附件。

如果我们禁用MTOM,还要传递附件,此时,附件会被编为BASE64码进行传递,这种方式传递附件的缺点很明显,一个10KB的图片的BASE64码在WORD里都可以用4篇来显示,那么大一些的附件将会使得XML的体积迅速膨胀,这与MTOM的原样传输二进制数据是没有可比性的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics