示例:使用 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等的数组或向量。 - 使用多个入/出或输出附件。