示例:使用 WSIF 传递带有附件的 SOAP 消息
这里的信息和示例代码说明如何以一种不更改标准 SOAP 消息的 SOAP 处理规则的方式,使用 Web Services Invocation Framework (WSIF) SOAP 提供程序在 MIME 多重部件/相关的消息中传递附件。这包括如何编写 SOAP 附件的 Web 服务描述语言 (WSDL) 扩展以及如何使用类型和类型映射。
带有附件的 W3C SOAP 消息文档描述一个标准方法,通过使用多重部件 MIME 结构进行传输,以它们本来的格式(例如,GIF 或 JPEG)SOAP 消息与一个或多个附件关联。它定义“多重部件/相关”MIME 介质类型的特定使用,以及用于 MIME 软件包内捆绑的对实体 URI 引用的规则。从而,概述了以一种不更改标准 SOAP 消息的 SOAP 处理规则的方式,在 MIME 多重部件/相关的消息中携带 SOAP 1.1 消息的技术。
WSIF 支持使用 SOAP 提供程序将 WSIF 服务链接至 SOAP over HTTP 服务,以在 MIME 消息中传递附件。附件是 javax.activation.DataHandler 对象。mime:multipartRelated、mime:part 和 mime:content 标记用于在 WSDL 中描述附件。
示例:为 SOAP 附件编写 WSDL 扩展
以下示例 WSDL 说明了一个简单操作,该操作具有一个名为 attch 的附件:
<binding name="MyBinding" type="tns:abc" >
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="MyOperation">
<soap:operation soapAction=""/>
<input>
<mime:multipartRelated>
<mime:part>
<soap:body use="encoded" namespace="http://mynamespace"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding"/>
</mime:part>
<mime:part>
<mime:content part="attch" type="text/html"/>
</mime:part>
</mime:multipartRelated>
</input>
</operation>
</binding>
- 操作(在本示例中,操作是 MyOperation)的输入消息必须具有 part 属性(在本示例中,该属性为 attch)。MyOperation 还可以具有其他不是附件的输入部件。
- 在绑定输入中,必须要有 <soap:body> 标记或 <mime:multipartRelated> 标记,但不能同时有这两个标记。
- 对于 MIME 消息,<soap:body> 标记位于 <mime:part> 标记内。在绑定输入中,必须只有一个 <mime:part> 标记包含 <soap:body> 标记,并且该标记一定不能同时包含 <mime:content> 标记,这是因为,对于 <soap:body> 标记,假定内容类型为 text/xml。
- 在 MIME 消息中可以有多个附件,每个附件都由 <mime:part> 标记描述。
- 每个未包含 <soap:body> 标记的 <mime:part> 标记都包含用来描述附件本身的 <mime:content> 标记。<mime:content> 标记中的 type 属性不被 Web Services Invocation Framework (WSIF) 检查或使用。因此,建议应用程序使用附件包含的 WSIF。在一个 <mime:part> 标记中有多个 <mime:content> 标记表示后端服务需要一个附件,该附件的类型由该 <mime:part> 标记中的其中一个 <mime:content> 标记指定。
- <soap:body> 标记中的 parts="..." 属性(可选)假设包含所有 MIME 部件的名称,以及消息中的所有 SOAP 部件的名称。
示例:使用 WSIF 来传递 SOAP 附件
以下代码段可以调用示例:为 SOAP 附件编写 WSDL 扩展中的示例 WSDL 所描述的服务:
import javax.activation.DataHandler;
. . .
DataHandler dh = new DataHandler(new FileDataSource(“myimage.jpg”));
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
WSIFService service = factory.getService(“my.wsdl”,null,null,“http://mynamespace”,“abc”);
WSIFOperation op = service.getPort().createOperation(“MyOperation”);
WSIFMessage in = op.createInputMessage();
in.setObjectPart(“attch”,dh);
op.executeInputOnlyOperation(in);
DeploymentDescriptor.xml 文件中关联的类型映射取决于您的 SOAP 服务器。例如,如果您将 Tomcat 与 SOAP 2.3 协同使用,那么 DeploymentDescriptor.xml 文件包含以下类型映射:
<isd:mappings>
<isd:map encodingStyle=“http://schemas.xmlsoap.org/soap/encoding/”
xmlns:x=“http://mynamespace”
qname=“x:datahandler”
javaType=“javax.activation.DataHandler”
java2XMLClassName=“org.apache.soap.encoding.soapenc.MimePartSerializer”
xml2JavaClassName=“org.apache.soap.encoding.soapenc.MimePartSerializer” />
</isd:mappings>
在这种情况下,使用以下特征符调用后端服务:
public void MyOperation(DataHandler dh);
还可以使用存根将附件传递到 Web Services Invocation Framework (WSIF) 中:
DataHandler dh = new DataHandler(new FileDataSource(“myimage.jpg”));
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
WSIFService service = factory.getService(“my.wsdl”,null,null,“http://mynamespace”,“abc”);
MyInterface stub = (MyInterface)service.getStub(MyInterface.class);
stub.MyOperation(dh);
附件也可以从操作中返回,但只有一个附件可以作为返回参数返回。
SOAP 附件 - 使用类型和类型映射
缺省情况下,附件作为 DataHandler 对象传递到 WSIF。如果作为 DataHandler 对象的消息部分映射到 WSDL 中 <mime:part> 标记,那么 WSIF 自动将 WSDL 类型的标准名称映射到 DataHandler 类并通过 SOAP 提供程序设置该类型映射。
在您的 WSDL中,您可能已定义附件的模式(例如 binary[] 类型)。除非您显式发出 mapType() 方法,否则 WSIF 静默忽略此映射,并将附件看作 DataHandler 对象。WSIF 让 SOAP 提供程序根据 DataHandler 对象的类型,而不是根据为 WSDL 中的 <mime:content> 标记指定的 type 属性设置 MIME 内容类型。
SOAP 附件 - 不支持的方案
- 使用 DIME。
- 在 javax.xml.transform.Source 和 javax.mail.internet.MimeMultipart 中传递。
- 使用 mime:mimeXml WSDL 标记。
- 将 mime:multipartRelated 标记嵌套在 mime:part 标记中。
- 使用扩展 DataHandler、Image 等的类型。
- 使用包含 DataHandler、Image 等的类型。
- 使用 DataHandlers、Images 等的数组或向量。
- 使用多个入/出或输出附件。