一个完整的基于JAX-WS SOAP的示例,展示了如何使用消息传输优化机制(MTOM)和XML二进制优化打包(XOP)技术将二进制附件(图像)从服务器发送到客户端,反之亦然。
注意
关于MTOM及其用途的好处有很多文章(请参见下面的参考站点 ),但是在JAX-WS中缺少使用MTOM的完整示例,希望该示例可以填补整个图片中的一些遗漏之处。
在服务器上启用MTOM
使服务器通过MTOM发送附件非常容易,只需使用javax.xml.ws.soap.MTOM
注释Web服务实现类即可。
1. WebService端点
这是一个RPC样式的Web服务,发布了两个方法downloadImage(String name)
和uploadImage(Image data)
,以允许用户上载或下载图像文件。
文件:ImageServer.java
package com.mkyong.ws;
import java.awt.Image;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
//Service Endpoint Interface
@WebService
@SOAPBinding(style = Style.RPC)
public interface ImageServer{
//download a image from server
@WebMethod Image downloadImage(String name);
//update image to server
@WebMethod String uploadImage(Image data);
}
文件:ImageServerImpl.java
package com.mkyong.ws;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.jws.WebService;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.soap.MTOM;
//Service Implementation Bean
@MTOM
@WebService(endpointInterface = "com.mkyong.ws.ImageServer")
public class ImageServerImpl implements ImageServer{
@Override
public Image downloadImage(String name) {
try {
File image = new File("c:\\images\\" + name);
return ImageIO.read(image);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
@Override
public String uploadImage(Image data) {
if(data!=null){
//store somewhere
return "Upload Successful";
}
throw new WebServiceException("Upload Failed!");
}
}
文件:ImagePublisher.java
package com.mkyong.endpoint;
import javax.xml.ws.Endpoint;
import com.mkyong.ws.ImageServerImpl;
//Endpoint publisher
public class ImagePublisher{
public static void main(String[] args) {
Endpoint.publish("http://localhost:9999/ws/image", new ImageServerImpl());
System.out.println("Server is published!");
}
}
2. WebService客户端
这是一个Web服务客户端,用于通过URL“ http:// localhost:9999 / ws / image ”访问已发布的Web服务。
文件:ImageClient.java
package com.mkyong.client;
import java.awt.Image;
import java.io.File;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.soap.MTOMFeature;
import javax.xml.ws.soap.SOAPBinding;
import com.mkyong.ws.ImageServer;
public class ImageClient{
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:9999/ws/image?wsdl");
QName qname = new QName("http://ws.mkyong.com/", "ImageServerImplService");
Service service = Service.create(url, qname);
ImageServer imageServer = service.getPort(ImageServer.class);
/************ test download ***************/
Image image = imageServer.downloadImage("rss.png");
//display it in frame
JFrame frame = new JFrame();
frame.setSize(300, 300);
JLabel label = new JLabel(new ImageIcon(image));
frame.add(label);
frame.setVisible(true);
System.out.println("imageServer.downloadImage() : Download Successful!");
}
}
3. HTTP和SOAP流量
这是客户端生成的HTTP和SOAP流量,由流量监控工具捕获。
PS省略第一个wsdl请求以节省空间。
客户发送请求:
POST /ws/image HTTP/1.1
SOAPAction: ""
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-Type: text/xml; charset=utf-8
User-Agent: Java/1.6.0_13
Host: localhost:9999
Connection: keep-alive
Content-Length: 209
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:downloadImage xmlns:ns2="http://ws.mkyong.com/">
<arg0>rss.png</arg0>
</ns2:downloadImage>
</S:Body>
</S:Envelope>
服务器发送响应:
HTTP/1.1 200 OK
Transfer-encoding: chunked
Content-type: multipart/related;
start="<rootpart*c73c9ce8-6e02-40ce-9f68-064e18843428@example.jaxws.sun.com>";
type="application/xop+xml";
boundary="uuid:c73c9ce8-6e02-40ce-9f68-064e18843428";
start-info="text/xml"
--uuid:c73c9ce8-6e02-40ce-9f68-064e18843428
Content-Id: <rootpart*c73c9ce8-6e02-40ce-9f68-064e18843428@example.jaxws.sun.com>
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"
Content-Transfer-Encoding: binary
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:downloadImageResponse xmlns:ns2="http://ws.mkyong.com/">
<return>
<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
href="cid:012eb00e-9460-407c-b622-1be987fdb2cf@example.jaxws.sun.com">
</xop:Include>
</return>
</ns2:downloadImageResponse>
</S:Body>
</S:Envelope>
--uuid:c73c9ce8-6e02-40ce-9f68-064e18843428
Content-Id: <012eb00e-9460-407c-b622-1be987fdb2cf@example.jaxws.sun.com>
Content-Type: image/png
Content-Transfer-Encoding: binary
Binary data here.............
在客户端上启用MTOM
需要一些额外的努力来使客户端能够通过MTOM将附件发送到服务器,请参见以下示例:
//codes enable MTOM in client
BindingProvider bp = (BindingProvider) imageServer;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
1. WebService客户端
这是一个Web服务客户端,用于通过MTOM将映像文件发送到上面发布的终结点(http:// localhost:8888 / ws / image)。
文件:ImageClient.java
package com.mkyong.client;
import java.awt.Image;
import java.io.File;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.soap.MTOMFeature;
import javax.xml.ws.soap.SOAPBinding;
import com.mkyong.ws.ImageServer;
public class ImageClient{
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:8888/ws/image?wsdl");
QName qname = new QName("http://ws.mkyong.com/", "ImageServerImplService");
Service service = Service.create(url, qname);
ImageServer imageServer = service.getPort(ImageServer.class);
/************ test upload ****************/
Image imgUpload = ImageIO.read(new File("c:\\images\\rss.png"));
//enable MTOM in client
BindingProvider bp = (BindingProvider) imageServer;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
String status = imageServer.uploadImage(imgUpload);
System.out.println("imageServer.uploadImage() : " + status);
}
}
2. HTTP和SOAP流量
这是客户端生成的HTTP和SOAP流量,由流量监控工具捕获。
PS省略第一个wsdl请求以节省空间。
客户发送请求:
POST /ws/image HTTP/1.1
Content-type: multipart/related;
start="<rootpart*751f2e5d-47f8-47d8-baf0-f793c29bd931@example.jaxws.sun.com>";
type="application/xop+xml";
boundary="uuid:751f2e5d-47f8-47d8-baf0-f793c29bd931";
start-info="text/xml"
Soapaction: ""
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
User-Agent: JAX-WS RI 2.1.6 in JDK 6
Host: localhost:9999
Connection: keep-alive
Content-Length: 6016
--uuid:751f2e5d-47f8-47d8-baf0-f793c29bd931
Content-Id: <rootpart*751f2e5d-47f8-47d8-baf0-f793c29bd931@example.jaxws.sun.com>
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"
Content-Transfer-Encoding: binary
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:uploadImage xmlns:ns2="http://ws.mkyong.com/">
<arg0>
<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
href="cid:2806f201-e15e-4ee0-8347-b7b4dffad5cb@example.jaxws.sun.com">
</xop:Include>
</arg0>
</ns2:uploadImage>
</S:Body>
</S:Envelope>
--uuid:751f2e5d-47f8-47d8-baf0-f793c29bd931
Content-Id: <2806f201-e15e-4ee0-8347-b7b4dffad5cb@example.jaxws.sun.com>
Content-Type: image/png
Content-Transfer-Encoding: binary
Binary data here.............
服务器发送响应:
HTTP/1.1 200 OK
Transfer-encoding: chunked
Content-type: multipart/related;
start="<rootpart*188a5835-198b-4c28-9b36-bf030578f2bd@example.jaxws.sun.com>";
type="application/xop+xml";
boundary="uuid:188a5835-198b-4c28-9b36-bf030578f2bd";
start-info="text/xml"
--uuid:188a5835-198b-4c28-9b36-bf030578f2bd
Content-Id: <rootpart*188a5835-198b-4c28-9b36-bf030578f2bd@example.jaxws.sun.com>
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"
Content-Transfer-Encoding: binary
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:uploadImageResponse xmlns:ns2="http://ws.mkyong.com/">
<return>Upload Successful</return>
</ns2:uploadImageResponse>
</S:Body>
</S:Envelope>
--uuid:188a5835-198b-4c28-9b36-bf030578f2bd--
完整的WSDL文档
对于那些有兴趣研究WSDL文件的人,可以通过URL获得wsdl文件: http:// localhost:9999 / ws / image?wsdl
ImageServer WSDL文件的样本
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://ws.mkyong.com/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://ws.mkyong.com/"
name="ImageServerImplService">
<types></types>
<message name="downloadImage">
<part name="arg0" type="xsd:string"></part>
</message>
<message name="downloadImageResponse">
<part name="return" type="xsd:base64Binary"></part>
</message>
<message name="uploadImage">
<part name="arg0" type="xsd:base64Binary"></part>
</message>
<message name="uploadImageResponse">
<part name="return" type="xsd:string"></part>
</message>
<portType name="ImageServer">
<operation name="downloadImage">
<input message="tns:downloadImage"></input>
<output message="tns:downloadImageResponse"></output>
</operation>
<operation name="uploadImage">
<input message="tns:uploadImage"></input>
<output message="tns:uploadImageResponse"></output>
</operation>
</portType>
<binding name="ImageServerImplPortBinding" type="tns:ImageServer">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc">
</soap:binding>
<operation name="downloadImage">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://ws.mkyong.com/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://ws.mkyong.com/"></soap:body>
</output>
</operation>
<operation name="uploadImage">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://ws.mkyong.com/">
</soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://ws.mkyong.com/">
</soap:body>
</output>
</operation>
</binding>
<service name="ImageServerImplService">
<port name="ImageServerImplPort" binding="tns:ImageServerImplPortBinding">
<soap:address location="http://localhost:9999/ws/image"></soap:address>
</port>
</service>
</definitions>
下载源代码
下载它– JAX-WS-Attachment-MTOM-Example.zip (20KB)
参考
- http://www.devx.com/xml/Article/34797/1763/page/1
- http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/2.0/jaxws/mtom-swaref.html
- http://www.crosschecknet.com/intro_to_mtom.php
- http://download.oracle.com/docs/cd/E12840_01/wls/docs103/webserv_adv/mtom.html
- http://www.theserverside.com/news/1363957/Sending-Attachments-with-SOAP
- http://metro.java.net/guide/Binary_Attachments__MTOM_.html
翻译自: https://mkyong.com/webservices/jax-ws/jax-ws-attachment-with-mtom/