WEB开发网
开发学院软件开发Java JAX-RPC 与 JAX-WS 的比较,第 5 部分:附件文件比... 阅读

JAX-RPC 与 JAX-WS 的比较,第 5 部分:附件文件比较:Sw/A 与 MTOM

 2009-11-03 00:00:00 来源:WEB开发网   
核心提示:引言JAX-RPC 的附件模型为 Sw/A,自从编写 JAX-RPC 后,JAX-RPC 与 JAX-WS 的比较,第 5 部分:附件文件比较:Sw/A 与 MTOM,就推出了一个新的附件模型:MTOM,JAX-WS 和 JAX-RPC 一样提供了 Sw/A 支持,MTOM 可以在 Document/literal W

引言

JAX-RPC 的附件模型为 Sw/A,自从编写 JAX-RPC 后,就推出了一个新的附件模型:MTOM。JAX-WS 和 JAX-RPC 一样提供了 Sw/A 支持,但还增加了对 MTOM 的支持。JAX-WS 通过 Java Architecture for XML Binding (JAXB) 规范支持 MTOM,此规范包括用于对 Sw/A 和 MTOM 附件进行封送和取消封送。在本文中,我们将通过示例对这两个模型进行分析。请注意:本文仅对 WSDL 和 Java 编程模型进行比较,连接级别的消息比较需由读者自行完成。

JAX-RPC 和 Sw/A 示例

清单 1 给出了摘自多年前所撰写的关于附件提示的 WSDL。清单 2 显示了对应的 Java 接口(即从此 WSDL 生成的 JAX-RPC 映射)。


清单 1. JAX-RPC Sw/A WSDL
<definitions 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="http://attachment.tip/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" 
    targetNamespace="http://attachment.tip/"> 
 <types/> 
 <message name="sendImage"> 
  <part name="image" type="xsd:base64Binary"/> 
 </message> 
 <message name="sendImageResponse"/> 
 <message name="sendOctet"> 
  <part name="octet" type="xsd:base64Binary"/> 
 </message> 
 <message name="sendOctetResponse"/> 
 <portType name="AttachmentTip"> 
  <operation name="sendImage"> 
   <input message="tns:sendImage"/> 
   <output message="tns:sendImageResponse"/> 
  </operation> 
  <operation name="sendOctet"> 
   <input message="tns:sendOctet"/> 
   <output message="tns:sendOctetResponse"/> 
  </operation> 
 </portType> 
 <binding name="AttachmentBinding" type="tns:AttachmentTip"> 
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> 
  <operation name="sendImage"> 
   <soap:operation soapAction=""/> 
   <input> 
    <mime:multipartRelated> 
     <mime:part> 
      <soap:body parts="" namespace="http://attachment.tip/" use="literal"/> 
     </mime:part> 
     <mime:part> 
      <mime:content part="image" type="image/jpeg"/> 
     </mime:part> 
    </mime:multipartRelated> 
   </input> 
   <output> 
    <soap:body namespace="http://attachment.tip/" use="literal"/> 
   </output> 
  </operation> 
  <operation name="sendOctet"> 
   <soap:operation soapAction=""/> 
   <input> 
    <mime:multipartRelated> 
     <mime:part> 
      <soap:body parts="" namespace="http://attachment.tip/" use="literal"/> 
     </mime:part> 
     <mime:part> 
      <mime:content part="octet" type="application/octet-stream"/> 
     </mime:part> 
    </mime:multipartRelated> 
   </input> 
   <output> 
    <soap:body namespace="http://attachment.tip/" use="literal"/> 
   </output> 
  </operation> 
 </binding> 
 <service name="AttachmentService"> 
  <port binding="tns:AttachmentBinding" name="AttachmentTip"> 
   <soap:address location="http://localhost:9080/SwAService/services/AttachmentTip"/> 
  </port> 
 </service> 
 </definitions>


清单 2. JAX-RPC Sw/A Java 接口
package tip.attachment; 
 
import java.awt.Image; 
import java.rmi.Remote; 
import java.rmi.RemoteException; 
 
import javax.activation.DataHandler; 
 
public interface AttachmentTip extends Remote { 
  public void sendImage(Image image) throws RemoteException; 
  public void sendOctet(DataHandler octet) throws RemoteException; 
} 

从 WSDL 生成的 Java 接口映射相当简单:sendImage 操作的 image/jpeg 部分映射为 java.awt.Image 参数;sendOctet 操作的 application/octet-stream 映射为 javax.activation.DataHandler 参数。不过此映射有一定的代价:多用途 Internet 邮件扩展(Multipurpose Internet Mail Extensions,MIME)类型信息不在 WSDL 接口部分中(portType、message 和 types 部分)。您必须自己对绑定进行分析,以找到 MIME 信息。这很不方便,因为相同 WSDL 接口的不同绑定可能会采用不同的类型,从而映射到不同的 Java 接口。如果从 WSDL 接口到 Java 接口之间存在一对一映射关系,这就要好得多。如果有多个绑定,每个都映射到一个实现,则所有绑定都实现相同的 Java 接口。使用 Sw/A 时不能做到这一点;从 WSDL 到 Java 的映射不是一对一的。

Sw/A 的第二个问题是,它本身对 Document/literal Wrapped WSDL 行业惯例遵循性并不好(您会注意到清单 1 中的 WSDL 是 rpc/literal WSDL)。要将 Sw/A 内容添加到 Document/literal Wrapped 消息,除了单个操作包装外,还需要指定其他消息部分。

MTOM 是否解决了这些问题?接下来我们就要对此进行讨论。

JAX-WS 和 MTOM 示例

在清单 3 中,我们将清单 1 的 Sw/A WSDL 修改为了等效的 MTOM WSDL。


清单 3. JAX-WS MTOM WSDL
<definitions 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="http://attachment.tip/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://attachment.tip/"> 
 <types/> 
 <message name="sendImage"> 
  <part name="image" type="xsd:base64Binary"/> 
 </message> 
 <message name="sendImageResponse"/> 
 <message name="sendOctet"> 
  <part name="octet" type="xsd:base64Binary"/> 
 </message> 
 <message name="sendOctetResponse"/> 
 <portType name="AttachmentTip"> 
  <operation name="sendImage"> 
   <input message="tns:sendImage"/> 
   <output message="tns:sendImageResponse"/> 
  </operation> 
  <operation name="sendOctet"> 
   <input message="tns:sendOctet"/> 
   <output message="tns:sendOctetResponse"/> 
  </operation> 
 </portType> 
 <binding name="AttachmentBinding" type="tns:AttachmentTip"> 
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> 
  <operation name="sendImage"> 
   <soap:operation soapAction=""/> 
   <input> 
    <soap:body namespace="http://attachment.tip/" use="literal"/> 
   </input> 
   <output> 
    <soap:body namespace="http://attachment.tip/" use="literal"/> 
   </output> 
  </operation> 
  <operation name="sendOctet"> 
   <soap:operation soapAction=""/> 
   <input> 
    <soap:body namespace="http://attachment.tip/" use="literal"/> 
   </input> 
   <output> 
    <soap:body namespace="http://attachment.tip/" use="literal"/> 
   </output> 
  </operation> 
 </binding> 
 <service name="AttachmentService"> 
  <port binding="tns:AttachmentBinding" name="AttachmentTip"> 
   <soap:address location="http://localhost:9080/MTOMService/services/AttachmentTip"/> 
  </port> 
 </service> 
</definitions> 

清单 3 中的 MTOM WSDL 和清单 1 中的 Sw/A WSDL 的唯一区别在于绑定。MTOM 绑定不包含 MIME 信息。事实上,通过 WSDL 并不能说明您所处理的是附件,WSDL 的绑定看起来就像一个普通绑定。

清单 4 显示了对应的 Java 接口,即从此 WSDL 生成的 JAX-RPC 映射。


清单 4. JAX-WS MTOM Java 接口
package tip.attachment; 
 
import javax.jws.WebMethod; 
import javax.jws.WebParam; 
import javax.jws.WebService; 
import javax.jws.soap.SOAPBinding; 
 
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/") 
@SOAPBinding(style = SOAPBinding.Style.RPC) 
public interface AttachmentTip { 
 
 
  @WebMethod 
  public void sendImage( 
    @WebParam(name = "image", partName = "image") 
    byte[] image); 
 
  @WebMethod 
  public void sendOctet( 
    @WebParam(name = "octet", partName = "octet") 
    byte[] octet); 
 
} 

因为此 WSDL 是普通 WSDL,没有关于附件的信息,因此最终得到的 Java 接口也会反映出这一点。对于类型为 base64Binary(或 hexBinary)的部分,JAX-WS 将其映射为 byte[] 类型的参数。对于 MTOM,会从 WSLD 提取类型的全部 MIME 信息,并需要由客户机或服务器运行时对内容进行恰当的格式化。

Sw/A 和 MTOM 的比较

JAX-RPC Sw/A 部分指出了 Sw/A 的两个缺点:

MIME 类型信息在 WSDL 绑定中,而不是 WSDL 接口中。

很难创建 Document/literal Wrapped 附件 WSDL。

让我们首先讨论一下 Document/literal Wrapped 样式。

Document/literal Wrapped 样式与附件

出于比较目的,我们将清单 3 中的 MTOM WSDL 保留为 rpc/literal WSDL;但要将此 WSDL 转换为 Document/literal Wrapped WSDL 很容易。下一部分的清单 5 显示了清单 3 中的 WSDL 的 Document/literal Wrapped 等效 WSDL。

绑定中的 MIME 类型信息

因为 MTOM WSDL 的绑定没有任何 MIME 信息,因此不用分析绑定来确定部分类型。在 WSDL 中有生成 Java 接口所需要的全部信息。不过,正如您通过比较清单 2 和清单 4 可以看到的,我们丢失了一些信息。

这两个 WSDL 的接口部分都显示操作中的数据类型为 base64Binary,而 base64Binary 又映射到 byte[]。不过,在 JAX-RPC Sw/A WSDL 中,我们通过绑定了解到部分类型为 MIME 映像和 MIME 八进制流。在 JAX-WS MTOM WSDL 中,此信息丢失了。这可能让人感觉是件坏事,但有一个好处,即接口得到了完全的清理。无论绑定的是什么,接口始终都是一样的。事实上,客户机和服务器代码库的实现者不应考虑参数是否是附件的问题。这仅是 SOAP 消息的一个细节,WSDL 到 Java 映射的编写者已经尽量让程序员不考虑 SOAP 消息的细节。

不过,如果您真的希望知道 MIME 类型(即希望找回所丢失的信息),JAX-WS 提供了一个属性,您可将其注入 XML 元素:expectedContentTypes 中。清单 5 中突出显示的部分就是这个特殊的属性。清单 6 显示了对应的 Java 接口。如果忽略注释,此 Java 接口就完全与清单 2 中的接口相同。


清单 5. JAX-WS MIME 属性
<definitions 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="http://attachment.tip/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://attachment.tip/"> 
 <types> 
  <xsd:schema 
      xmlns:tns="http://attachment.tip/" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      targetNamespace="http://attachment.tip/"> 
   <xsd:element name="sendImage" type="tns:sendImage"/> 
   <xsd:complexType name="sendImage"> 
    <xsd:sequence> 
     <xsd:element 
         xmlns:ns1="http://www.w3.org/2005/05/xmlmime" 
        ns1:expectedContentTypes="image/*" 
         name="image" 
         type="xsd:base64Binary"/> 
    </xsd:sequence> 
   </xsd:complexType> 
   <xsd:element name="sendImageResponse" type="tns:sendImageResponse"/> 
   <xsd:complexType name="sendImageResponse"> 
    <xsd:sequence/> 
   </xsd:complexType> 
   <xsd:element name="sendOctet" type="tns:sendOctet"/> 
   <xsd:complexType name="sendOctet"> 
    <xsd:sequence> 
     <xsd:element 
         xmlns:ns1="http://www.w3.org/2005/05/xmlmime" 
        ns1:expectedContentTypes="application/octet-stream" 
         name="octet" 
         type="xsd:base64Binary"/> 
    </xsd:sequence> 
   </xsd:complexType> 
   <xsd:element name="sendOctetResponse" type="tns:sendOctetResponse"/> 
   <xsd:complexType name="sendOctetResponse"> 
    <xsd:sequence/> 
   </xsd:complexType> 
  </xsd:schema> 
 </types> 
 <message name="sendImage"> 
  <part name="parameters" element="tns:sendImage"/> 
 </message> 
 <message name="sendImageResponse"> 
  <part name="parameters" element="tns:sendImageResponse"/> 
 </message> 
 <message name="sendOctet"> 
  <part name="parameters" element="tns:sendOctet"/> 
 </message> 
 <message name="sendOctetResponse"> 
  <part name="parameters" element="tns:sendOctetResponse"/> 
 </message> 
 <portType name="AttachmentTip"> 
  <operation name="sendImage"> 
   <input message="tns:sendImage"/> 
   <output message="tns:sendImageResponse"/> 
  </operation> 
  <operation name="sendOctet"> 
   <input message="tns:sendOctet"/> 
   <output message="tns:sendOctetResponse"/> 
  </operation> 
 </portType> 
 <binding name="AttachmentBinding" type="tns:AttachmentTip"> 
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 
  <operation name="sendImage"> 
   <soap:operation soapAction=""/> 
   <input> 
    <soap:body use="literal"/> 
   </input> 
   <output> 
    <soap:body use="literal"/> 
   </output> 
  </operation> 
  <operation name="sendOctet"> 
   <soap:operation soapAction=""/> 
   <input> 
    <soap:body use="literal"/> 
   </input> 
   <output> 
    <soap:body use="literal"/> 
   </output> 
  </operation> 
 </binding> 
 <service name="AttachmentService"> 
  <port binding="tns:AttachmentBinding" name="AttachmentTip"> 
   <soap:address location="http://localhost:9080/MTOMService/services/AttachmentTip"/> 
  </port> 
 </service> 
</definitions>

请注意,这个新属性完全包含在 WSDL 接口中。该属性不在绑定中,因此所有类型信息都在您所期望的位置。


清单 6. 从 MIME 属性映射得到的 JAX-WS Java 接口
package tip.attachment; 
 
import java.awt.Image; 
import javax.activation.DataHandler; 
import javax.jws.WebMethod; 
import javax.jws.WebParam; 
import javax.jws.WebService; 
import javax.xml.ws.RequestWrapper; 
import javax.xml.ws.ResponseWrapper; 
 
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/") 
public interface AttachmentTip { 
 
  @WebMethod 
  @RequestWrapper(localName = "sendImage", 
      targetNamespace = "http://attachment.tip/", 
      className = "tip.attachment.SendImage") 
  @ResponseWrapper(localName = "sendImageResponse", 
      targetNamespace = "http://attachment.tip/", 
      className = "tip.attachment.SendImageResponse") 
  public void sendImage( 
    @WebParam(name = "image", targetNamespace = "") 
    Image image); 
 
  @WebMethod 
  @RequestWrapper(localName = "sendOctet", 
      targetNamespace = "http://attachment.tip/", 
      className = "tip.attachment.SendOctet") 
  @ResponseWrapper(localName = "sendOctetResponse", 
      targetNamespace = "http://attachment.tip/", 
      className = "tip.attachment.SendOctetResponse") 
  public void sendOctet( 
    @WebParam(name = "octet", targetNamespace = "") 
    DataHandler octet); 
} 

正如前面所提到的,JAX-WS 依赖于 JAXB 处理其大部分 Web 服务内容的数据绑定。expectedContentTypes 元素的映射在 JAXB 2.0 规范的附录 H 中定义。JAXB 2.0 映射与 JAX-RPC 映射类似。表 1 对这些映射进行了比较。


表 1. MIME 类型到 Java 类型的映射

MIME 类型JAX-RPC 映射JAX-WS/JAXB 映射
image/gifjava.awt.Imagejava.awt.Image
image/jpgjava.awt.Imagejava.awt.Image
text/plainjava.lang.Stringjavax.xml.transform.Source
text/xmljavax.xml.transform.Sourcejavax.xml.transform.Source
application/xmljavax.xml.transform.Sourcejavax.xml.transform.Source
multipart/*javax.mail.internet.MimeMultipartjavax.activation.DataHandler
所有其他类型javax.activation.DataHandlerjavax.activation.DataHandler

启用/禁用附件支持

MTOM 的另外一个好处是,您能够启用或禁用它。对于 Sw/A,如果某一方不支持发送 Sw/A 附件,就不能遵守 WSDL 定义的契约。另一方面,如果使用清单 3 或清单 5 中给出的类似的 MTOM WSDL,客户机就可以选择将数据作为 MTOM 附件发送或在 SOAP 消息中以内联方式发送。无论客户机选择哪个选项,都仍然可以与 Web 服务交互。MTOM 只是发送内容的一个优化选项,而不是像 Sw/A 一样强制要求使用。

Sw/A 和 JAX-WS

JAX-WS 仍然支持 Sw/A 模型。缺省情况下,JAX-WS 将 Sw/A 附件映射到 Java 接口上的 byte[],就像清单 4 中的示例一样。要获得在 JAX-RPC 中使用的映射,可以使用 enableMIMEContent WSDL 绑定定义(有关更多信息,请参见 JAX-WS 规范的 8.7.5 节)。清单 7 显示了与清单 2 中的接口的 JAX-RPC 版本等效的 JAX-WS 版本。


清单 7. JAX-WS Java 接口,Sw/A 附件从 mime:content 映射
package tip.attachment; 
 
import java.awt.Image; 
import javax.activation.DataHandler; 
import javax.jws.WebMethod; 
import javax.jws.WebParam; 
import javax.jws.WebService; 
import javax.jws.soap.SOAPBinding; 
 
@WebService(name = "AttachmentTip", targetNamespace = "http://attachment.tip/") 
@SOAPBinding(style = SOAPBinding.Style.RPC) 
public interface AttachmentTip { 
 
 
  @WebMethod 
  public void sendImage( 
    @WebParam(name = "image", partName = "image") 
    Image image); 
 
  @WebMethod 
  public void sendOctet( 
    @WebParam(name = "octet", partName = "octet") 
    DataHandler octet); 
 
}

总结

JAX-RPC 支持 Sw/A 模型。JAX-WS 也支持 Sw/A,但另外还支持新的 MTOM 模型。从多方面而言,MTOM 都比 Sw/A 提高了不少:

创建 Java 接口所必需的全部信息现在都在 WSDL 接口中。

MTOM 可以在 Document/literal Wrapped WSDL 中使用。

MTOM 允许对附件进行优化,但并不像 Sw/A 一样对附件有强制要求。

Tags:JAX RPC JAX

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接