rt

解决方案 »

  1.   

    访问器(accessor)它们是值的容器
    http://www.rainlow.com/forum/viewtopic.php?p=3816SOAP 定义了一个简单的有线协议来传输应用程序级的数据。因为有丰富而又可扩展的类型系统,这个协议可以很容易地将任意 Java 类型作为序列化的 XML 进行传送。在本文,即关于 Apache SOAP 工具箱中的类型系统支持的系列文章的第一部分(共两部分)中,Gavin Bong 将向您介绍 SOAP 的类型系统的理论基础。您还将了解到更多关于 SOAP 对序列化和反序列化的编程支持,最后,深入研究一下工具箱的内部机制。更好地理解这个过程是如何工作的将有助于您构建自己的分布式系统。 
    当以电子方法交换数据时,进行交换的端点需要预先在两方面达成一致:交互模式和类型系统。前者与通信通道的体系结构(例如,点对点和多对一,或分块对异步)有关。而另一方面,后者是要在对消息进行编码和解码的过程中使用的达成一致的数据格式。 在本文中,我将描述 SOAP 中可应用于 Apache SOAP 工具箱的类型系统。虽然 SOAP 工具箱的当前版本同时支持消息传递和 RPC 交互两种模式,但本文只重点讨论后者。除非另有声明,否则本文中讨论的功能一般适用于 2001 年 5 月发行的 Apache SOAP 版本 2.2(请参阅参考资料)。在适当的地方,我将突出显示自该发行版之后发生的错误修正和接口变化。 除术语之外,让我来介绍一下整个系列中使用的用来表示 QName(qualified name,限定名)的名称空间前缀(适用于 SOAP 和 W3C 的 XML Schema)和约定。 2001 年发布了一个 SOAP 1.2 工作草案,但我们将只讨论 SOAP 1.1 的细节问题。这样,前缀 SOAP-ENV 和 SOAP-ENC 将分别引用名称空间 http://schemas.xmlsoap.org/soap/envelope/ 和 http://schemas.xmlsoap.org/soap/encoding/。 
    除非另有明确声明,一般我们假定前缀 xsd 和 xsi 分别引用名称空间 http://www.w3.org/2001/XMLSchema 和 http://www.w3.org/2001/XMLSchema-instance。 
    我们将以下面的格式编写带外部 URI 的 QName: 
    {uri}localpart. 
    一个示例:{http://xml.apache.org/xml-soap}Map 
    SOAP 和 RPC 
    当用 SOAP 执行 RPC 调用时,在 Web 服务请求者和提供者之间交换两种类型的有效负载: 远程方法的参数(RPC 请求) 
    返回值(RPC 响应) 
    从技术上来说,SOAP 附件和 SOAP 报头也可以组成 SOAP RPC 调用中的有效负载,但现在我们可以安全地忽略它们。通常是使用俗称 Section 5 的方法对有效负载编码。虽然 SOAP 规范没把它指定为缺省的编码方法,但目前可用的所有 SOAP 框架都支持这个编码方法。 Section 5 编码描述了将对象图转换为 XML 的方法。如果一直坚持使用这种方法,就可以将 SOAP XML 重新构造回它的原始形态。另一种编码方法通过使用模式语言(如 W3C 的 XML Schema)约束有效负载。在前一个方法学中,事务中感兴趣的各方对序列化规则都持一致意见,而在后一个方法学中,他们是对消息的文字格式意见一致。在这个序列的第 2 部分中,您会看到一个示例,它演示由模式约束的 SOAP。 清单 1 和 2 详细演示并深入研究了 Section 5 编码。清单 1 中的 Foo JavaBean 在清单 2 中被序列化。 清单 1. Foo JavaBean 
    class Foo{ 
    int i; 
    String s; 
    public Foo() {} 
    .... /* property mutators and accessors not shown for brevity */ 

    清单 2. Foo 对象的 SOAP 表示 
    <SOAP-ENV:Body> 
    <ns1:eatFoo 
    xmlns:ns1="urn:ibmdw:myservice" 
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
    <fooParam 
    xmlns:ns2="http://foo/type" 
    xsi:type="ns2:Foo"> 
    <i xsi:type="xsd:int">1000</i> 
    <s xsi:type="xsd:string">Hello World</s> 
    </fooParam> 
    </ns1:eatFoo> 
    </SOAP-ENV:Body> 
    清单 2 中的 SOAP XML 实例表示一个 RPC 调用,该调用将方法调用 eatFoo 调度到由 URI urn:ibmdw:myservice 标出的 Web 服务。元素 fooParam、i 和 s 被称为访问器(accessor);它们是值的容器。多引用(Multireference)访问器不在这个定义的范围内;这些是一些空元素,使用“XML 指针语言”(XML Pointer Language)之类的机制(关于更多信息,请参阅下面的参考资料)来引用其它包含实际值的元素。 清单 2 中遍布的 xsi:type 属性提供访问器的子类型。通常,Web 服务提供者和请求者已经预先就每个 RPC 调用的参数数据类型达成了一致。要对 SOAP XML 实例进行正确的反序列化,有了这个预先达成的一致就够了,即使没有 xsi:type 属性也可以。但请考虑一下这样一个用例,在其中有一个特殊的方法既接受字符串也接受整数(例如可以将参数定型为接受 java.lang.Object 参数)。在这个案例中,为使对象正确进行反序列化,需要一个显式的 xsi:type 声明所包含值的类型。带有显式的 xsi:type 属性的访问器被称为多态访问器(polymorphic accessor)。 Apache SOAP 被设计为把所有的访问器都当作多态访问器看待。版本 2.2 继续使用多态访问器生成 SOAP XML 实例,但编程时它被设计为不用多态访问器就可以进行数据编出。稍后,在本文中我将简要说明如何执行这种操作。 xsi:type 属性将 QName 作为它的值。xsi:type 属性可接受的值有: “XML 模式第 2 部分:数据类型”规范中的内置类型。 
    Apache SOAP 支持大多数内置类型并向后兼容该模式第 2 部分规范的所有版本的类型,这些版本中包括: 推荐版 (2001) 
    候选推荐版 (2000 年 10 月) 
    工作草案 (1999) 准确地说,Apache SOAP 并没有涵盖所有的内置类型,但它的确支持那些最常用的类型。在下一部分,我将看一下 Apache SOAP 支持的 Section 5 编码类型的详细清单。 表示一个用户定义的类型的任意 QName 
    这些用于表示混合类型如清单 2 中的 ns2:Foo。这种类型的序列化格式可以由模式文档来定义,或者,象 Apache SOAP 中那样,由定制的(反)序列化器来定义。 SOAP 1.1 扩展类型。 
    这些包括 SOAP-ENC:Array(表示数组成员的一个有序序列)和 SOAP-ENC:base64(表示一个 base-64 编码的字符串)。 清单 2 中的 encodingStyle 属性被用于指出所用的序列化模式。例如,Section 5 编码由 URI http://schemas.xmlsoap.org/soap/encoding/ 指出。Apache SOAP 有三个 encodingStyle 的内置支持:Section 5、XMI 和文字 XML(literal XML)。同时也支持定制的 encodingStyle。 但是,Apache SOAP 的 Section 5 编码支持并不全面。它仍然缺少一些功能,如稀疏(sparse)支持、部分传输支持和多维数组支持。 直到现在,我一直都在暗示进行数据交换的端点将能够魔术般地(反)序列化以 Section 5 编码的类型;但前提条件实际上依赖于对被来回传送的实体的数据模型要有某些非常规的一致。这基本上意味着,端点需要在一些“众所周知”的类型上达成一致。然而,这里有一个替代方案。不想受 Section 5 限制的软件开发者可以求助于基于模式的序列化(schema-based serialization)。将 SOAP 服务的接口和请求/响应消息的模式(一个或多个)一起发布,这种方法就可以生效。“Web 服务定义语言”(Web Services Definition Language,WSDL)是当前用于这种目的的实际标准。Apache SOAP 是无 WSDL 意识的,但 Apache SOAP 的后继工具箱 Axis(请参阅参考资料)有这种意识。