理解 WSRF第1部分-使用 WS-ResourceProperties
本 教程是一个由 4 部分组成的系列文章中的第 1 部分,该系列介绍 WSRF(Web Services Resource Framework)背后的概念。WSRF 是一组规范,提供一种标准方式,在 Web 服务应用程序的本质上“无状态的”环境中与“有状态”资源交互。这种有状态资源实际上可以是任何东西,从数据库到电子鼠标都是有状态资源。实际上,可以使 用 WSRF 来处理任何可以通过改变其属性来操纵的东西。
WS-Resource 是一个有状态资源(比如数据库或硬盘)和它与之交互的 Web 服务的组合。本教程解释了创建 WS-Resources、请求和更新用于定义 WS-Resource 状态的属性。我们将介绍以下内容:
1. WSRF 规范的概述。
2. 本系列教程中使用的系统的概述。
3. 关于 WSDL 的基本信息。
4. 关于的 WS-Addressing 的基本信息,WS-Addressing 用于定位 WS-Resource。
5. 创建 WS-Resource。
6. 获得和设置 WS-Resource 属性。
注意,WSRF 作为一种规范,定义了描述这些操作的 WSDL 文件的结构。该 WSDL 文件然后可以被任何语言的实现所使用。本教程描述 WSDL 文件的创建并展示产生的 SOAP 消息。
一定要明白,WSRF 规范只定义应该做什么,而不定义应该如何做。这里描述的概念的实际实现留给了应用程序去完成。在本系列的第 4 部分中,我们将使用 Globus Alliance 提供的 Core Java WSRF 类来讨论该实现。
在本系列中,我们将使用一系列围绕地球的人造卫星作为例子。我们将创建一个 WS-Resource,它就代表这样一个人造卫星。然后我们将请求它的属性以检索它的数据,更改它的属性以将它发射到天空中,并更改它观测的对象。
l 网格计算简介
首先,我们指出 WSRF 的应用远远超出了网格,但是 WSRF 是在网格中开发的,所以网格是 WSRF 可以做什么的一个很好的例子。之后,将花点时间为那些不熟悉网格的人解释一下网格是什么。
数 百万的 Web 用户已经体验了网格计算,只是大多数人都没有感觉到而已。1998 年,由于 NASA 发起了一个新计划,使得 Search for Extraterrestrial Intelligence (SETI) 项目差点夭折,此时就创建了也许是最著名的网格计算项目。他们的 Aricebo 无线电望远镜得到非常大量的数据,但是没有足够的处理能力可以处理这些数据。为了解决这个问题,他们创建了一个 screensaver,当计算机不忙时,它会从*服务器请求一包数据并进行分析,然后把结果发送回去。然后又请求一包新的数据,并重复刚才的步骤。数 百万用户下载了 screensaver 并参与该项目。
大型网格应用程序更加复杂,要处理的问题也更多,这些问题与身份验证、跨组织边界的进程间通信和高性能数据传输等方面有关。尽管网格*者可能不愿意听到 SETI@Home 的情况,但是它确实提供了网格工作原理的一个很好的例子。它涉及以下步骤:
工作被分成适合于在多个系统上处理的“单元”。该“工作”可以是计算、存储或其他类型的处理。
单元被分布到多个客户机。这个步骤通过让客户机请求或“pull”工作,或者让*服务器将工作“push”给可用的客户机来完成。
总体进展、需求和状态由*系统或系统组维护。
当前的网格应用程序一般遵循这种模式,有一个*系统与客户机交互,这些客户机位于那些一般在地理位置上与*服务器分离的系统上。
l 使用 Web 服务:承诺和问题
既然多个客户机在不同的地方,那么 Web 服务应该是网格计算顺理成章的选择。毕竟,它提供一种标准而容易的方法,以从一个系统到另一个系统获得信息,而不用求助于特定于平台或语言的方法,比如 CORBA、DCOM 或 Java-RMI。
但是,原来并不是这样的。早期的网格应用程序使用其他更加不可移植的方法。但是为什么呢?
也 许最贴切的是体系结构方面的原因。尽管网格应用程序可以在很多机器上实现,但它仍然是一个应用程序,因此很难与本质上是无状态的体系结构相协调。当使用数 据库客户机连接到一个数据库时,您就保持了连接,并且可以插入记录,然后再查看插入的结果。另一个客户查看表时不会看到该记录,除非您提交了事务,但是数 据库认识您的会话,并知道是您。
Web 服 务的工作方式不是这样的。利用 Web 服务,您发出请求(比如插入一条记录)并得到响应(比如插入成功),然后断开连接。没有正在进行的会话需要管理。例如 HTTP —— 在大多数情况下,Web 服务通过 HTTP 传输 —— 每个请求独立于前一个请求,Web 服务没有访问或使用任何不是当前输入消息一部分的信息。
WSRF 的目标是通过创建“状态”概念以及处理状态的方法来解决该问题。
l 有状态资源
那么到底什么是“状态”,什么又是“有状态”资源呢?
有状态资源是一些即使您不与之交互也存在的东西。例如数据库,即使在您不查询它的时候,它也存在。围绕行星的人造卫星即使在您不与之对话时也存在。甚至简单的计数器,在调用之间,或者每次调用它返回一个 1 时,都必须存在。
此 外,一定要明白,状态概念也包含属性的思想。当要求您把所借的东西以原状态返还时,涉及某些属性的值,比如清洁度、修理要求、油罐中的汽油量,等等。有状 态资源与此类似,具有定义其状态的属性,并且这些属性就是我们将与资源交互的方式,如 WS-Resource 的属性 中所示。
l Web 服务 + 有状态资源 = WS-Resource
根据规范可知,WS-Resource 是 Web 服务与它在其上起作用的有状态资源的组合。但是这真正的含义是什么呢?
让我们从实际的角度来看这个问题。假设我们有一个系统,涉及到管理一组人造卫星。每个人造卫星是一个有状态资源,因为即使在我们不与之对话时它也存在。我们还有一个 Web 服务,它提供人造卫星功能,比如更改反向、检索信息,或者甚至调整姿势。
通 过将者二者组合起来,我们创建了一个 WS-Resource。注意,并不需要一对一的对应关系。例如,这个 Web 服务可以与几个不同的人造卫星交互,从而创建几个引用相同服务的不同 WS-Resources。另一方面,一个人造卫星可以与几个不同的服务(比如控制宇宙实验的服务和发射激光束的服务)交互,从而创建几个引用相同有状态 资源的不同 WS-Resources。
为了使用 WS-Resource,必须了解它的属性。
l WS-Resource 的属性
正如 有状态资源 中所提到的,有状态资源(以及 WS-Resource)具有各种与之相关的属性。例如,人造卫星可能具有以下属性:
latitude
longitude
altitude
pitch
yaw
roll
focalLength
currentView
在 本例中,latitude、longitude 和 altitude 这前三个属性指定人造卫星的位置。其次,pitch、 yaw 和 roll 指定它的方位,或者说它看起来的方向。最后两个属性,focalLength 和 currentView,指定它离观测点的距离以及它在这一点所看到的东西。
这 些属性的值定义资源的状态。更改属性值,就更改了状态。事实上,我们就是这样来控制人造卫星的。要更改它的位置,我们就改变它的一个位置属性。要更改它的 方位,我们就改变它的一个方位属性。实际上,我们想要对该人造卫星做任何事情(在这个非常有限的实现中),我们都只要改变这些属性就可以了。
但是如何来做到 这一点?
l 进入 WSRF
好了,既然 WS-Resource 是有状态资源和 Web 服务的组合,并且我们通过请求和设置它的属性来操纵它,那么如何来做到这一点呢?
有很多方法来做到这一点,但是问题也正在于此。需要的是一种做出请求的标准方式,以获取和设置各个属性。
进 入 WSRF。WSRF 实际上是一系列规范,用于定义标准的“消息模式”或方法,以请求属性的值或者指定这些属性应该变更。实际上,WSRF 定义一些标准方法,以处理关于处理 WS-Resources 的各个方面,比如处理它们的属性,从而将它们成组在一起,以达到诸如这样的目的 —— 进行身份验证,确保它们被及时地销毁。
WSRF 定 义这些操作的方法是,指定它们应该如何出现在 Web 服务描述语言(Web Services Description Language,WSDL)文件中。WSDL 文件定义 Web 服务会话两端之间传输的消息,所以通过定义 WSDL 文件,WSRF 定义了发生的任何交互的形式。
当我们说到“WSRF”时,实际上是指几个不同的规范:
1. WS-ResourceProperties (WSRF-RP)指定 ResourceProperties 在 WSDL 文件中被定义的形式。它还指定消息的形式,这些消息用于请求和接收属性的值,还解释了如何更改、添加和删除 WS-Resource 的属性。
2. WS-ResourceLifetime (WSRF-RL)谈论这样一些状态,即 WS-Resource 需要过期了,或者在它不再需要了时应该被显式地销毁。
3. WS-ServiceGroup (WSRF-SG)定义创建一组 Web 服务(比如可用服务的注册表)的方法。
4. WS-Base Faults (WSRF-BF)定义一种标准的方法,用于指出基于 WSRF 的应用程序中的错误。
您将注意到,没有哪一个规范简单地描述了所有这一切应该如何一起工作。这项工作(几乎)是由 Modeling Stateful Resources with Web Services 白皮书完成的,该书解释了一般的概念,并将它们联系在一起。
本 教程除了介绍白皮书中的一些概念之外,还将讨论 WS-ResourceProperties 规范。本系列的以后各期将讨论其他的 WSRF 规范,以及 Web Services Notifications (WSN) 规范(整个 WSRF 中都引用了这些规范)。
l 什么是 WSDL,为什么我要关注它?
在正式开始在 WSDL 文件中创建 WS-Resources 之前,我们首先花点时间来看一下 WSDL 文件的目的和结构。这些描述就是在 WSDL 文件中。
Web 服 务 —— 或者至少是与 WS-Resources 相关的 Web 服务 —— 由 SOAP 消息组成。SOAP 消息具有一个标准的“信封”,其中包含一个“有效负载”。该有效负载是由服务器(在请求时)和客户机(在响应时)分析的数据。考虑下面这个 SOAP 消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<SetAltitudeRequest xmlns="http://example.com/satellite.xsd">
<altitude>47700</altitude>
</SetAltitudeRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
它包含标准信封和有效负载,前者在 http://schemas.xmlsoap.org/soap/envelope/ 名称空间(SOAP-ENV)中,后者在 http://example.com/satellite.xsd 名称空间中。
有 效负载可以是任何东西,因此存在这样一个问题:如何定义应用程序期望看到什么,以及返回什么?因而有了 WSDL 文件的用武之地。最终,我们将使用一个 WSDL 文件来定义 WS-Resource 所使用的“消息模式”,但是在本节,我们只来看 WSDL 文件的各部分是如何组合在一起的。
l 消息和类型
我们首先定义一条我们将会发送的实际消息:
<?xml version="1.0"?>
<definitions name="Satellite"
targetNamespace="http://example.com/satellite.wsdl"
xmlns:tns="http://example.com/satellite.wsdl"
xmlns:satTypes="http://example.com/satellite.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="http://example.com/satellite.xsd"
xmlns="http://www.w3.org/2000/10/XMLSchema">
<element name="SetAltitudeRequest">
<complexType>
<all>
<element name="altitude" type="float"/>
</all>
</complexType>
</element>
<element name="SetAltitudeResponse">
<complexType>
<all>
<element name="result" type="string"/>
</all>
</complexType>
</element>
</schema>
</types>
<message name="SetAltitudeInput">
<part name="body" element="satTypes:SetAltitudeRequest"/>
</message>
<message name="SetAltitudeOutput">
<part name="body" element="satTypes:SetAltitudeResponse"/>
</message>
</definitions>
从 底部开始,我们定义了两种类型的消息。第一种是 SetAltitudeInput,这是我们将发送给服务器作为输入的消息。它是您在什么是 WSDL,为什么我要关注它? 中看到的 SOAP 消息中的消息。第二种消息是 SetAltitudeOutput,这是服务器发送给客户机的响应。两种消息都指定一个元素,消息体将放在该元素中。
这些元素的实际定义位于文件顶部的模式(schema)中。例如,SetAltitudeInput 消息包含一个 SetAltitudeRequest 元素,该元素自己又包含一个 altitude 元素,后面这个元素的内容必须是一个 float。
接下来,我们将组合这些消息,以创建服务器执行的一个操作。
l 端口类型和操作
既然知道了我们将要发送的消息是什么,现在就需要指定它们将要完成的角色。要做到这一点,我们将创建一个 portType 及其相关的 operation:
...
<message name="SetAltitudeInput">
<part name="body" element="satTypes:SetAltitudeRequest"/>
</message>
<message name="SetAltitudeOutput">
<part name="body" element="satTypes:SetAltitudeResponse"/>
</message>
<portType name="AltitudePortType">
<operation name="SetAltitude">
<input message="tns:SetAltitudeInput"
wsa:Action="http://example.com/SetAltitude" />
<output message="tns:SetAltitudeOutput"
wsa:Action="http://example.com/SetAltitudeResponse" />
</operation>
</portType>
</definitions>
这 里,我们定义了一个 portType 叫做 AltitudePortType,以及它的一个 operation 叫做 SetAltitude。我们实际上可以在该 portType 中定义任意数量的操作,但是现在我们是为了保持简单。SetAltitude 操作指定一个 input 消息 SetAltitudeInput 和一个 output 消息 SetAltitudeOutput。(下一节我们将处理 wsa:Action 属性。此外,请注意名称空间信息。)
您也可以指定一个 fault 消息在有问题时发送,在本教程系列的后面将会介绍这一点,但是现在还是保持简单。
l 服务和绑定
至此,我们已经使用 portType 定义了可以做什么 事情,但是没有定义如何 做。要完成这个过程,我们需要创建一个描述如何做的 binding,并将它附加到实际的 service:
...
<portType name="AltitudePortType">
<operation name="SetAltitude">
<input message="tns:SetAltitudeInput"
wsa:Action="http://example.com/SetAltitude" />
<output message="tns:SetAltitudeOutput"
wsa:Action="http://example.com/SetAltitudeResponse" />
</operation>
</portType>
<binding name="AltitudeSoapBinding" type="tns:AltitudePortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="SetAltitude">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SatelliteService">
<port name="AltitudePort" binding="tns:AltitudeSoapBinding">
<soap:address location="http://example.com/satellite"/>
</port>
</service>
</definitions>
我们还是从底部开始,先看 service 元素。一个 WSDL 文件可以定义多个服务。例如,您可能有用于不同目的的不同服务,或者在不同位置有具有相同目的的不同服务,或者具有不同绑定的不同服务,比如一个用于 SOAP 的服务和一个用于 SMTP 的服务。
在 本例中,我们将利用一个端口 AltitudePort 来定义一个服务 SatelliteService。但是我们知道关于该端口的哪些情况呢?哦,我们知道 SOAP 请求应该发送到 http://example.com/satellite。我们还知道,为了获得关于如何发送消息的更多信息,应该检查 AltitudeSoapBinding。
AltitudeSoapBinding 指定它是 AltitudePortType 的一个实现,所以我们知道发送什么消息。binding 本身指定每个操作中的消息是如何格式化的。在本例中,我们使用“document/literal”样式,这意味着我们只是将定义好的元素拖放到 Body 中。
我们知道了消息将发送到哪里,如何格式化这些消息,以及这些消息应该是什么。到 创建 WS-Resource 一节,我们将介绍如何创建 WSRF 定义的特定消息,但是首先我们需要了解一下 WS-Addressing。
l 什么是 WS-Addressing,为什么我要关注它?
以 前,很容易指定 Web 服务的地址。所有您真正需要的就是 URL,所有其他信息都包含在 SoapAction 头部或消息本身中。现在,Web 服务应用程序变得越来越复杂,并不总是那么简单。您若想要让应答发送到除最初的请求者之外的其他地方,或者需要其他信息(比如会话标识符)来定义实际的 “位置”,那该怎么办?
或者您只是需要附加到 Web 服务的一个特定实例,那该怎么办?我们在 WS-Resources 的情况中将会遇到这个问题,所以我们需要一种处理它的方式。
WS-Addressing 提 供一种方式来指定关于位置的信息,而不只是一个统一资源标识符(Universal Resource Identifier,URI)或 URL。实际上,在我们的例子中,它提供一种标准的方式,将大量的信息添加到 SOAP 消息。我们来构造一个 SOAP 消息,比如:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<SOAP-ENV:Header>
<wsa:To SOAP-ENV:mustUnderstand="1">http://example.com/satellite</wsa:To>
<wsa:Action>http://example.com/SetAltitude</wsa:Action>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<SetAltitudeRequest xmlns="http://example.com/satellite.xsd">
<altitude>47700</altitude>
</SetAltitudeRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在实际的 SOAP 消息中具有该信息似乎并不重要,但是请记住,消息可能会传输通过多个系统,甚至需要多次传输才能到达最终目的地。
要指定该信息,我们需要创建一个 EndpointReference。
WS-Addressing 引入了 EndpointReference 概念。EndpointReference 是一种方式,用于指定让消息到达适当的位置并带有适当的相关信息所需的信息。例如,我们在前一屏中指定的消息的 EndpointReference 应该是:
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
理 解 EndpointReference 和 SOAP 消息之间的关系很重要,因为 EndpointReference 就是我们指定特定 WS-Resource 的位置的方式。例如,当我们请求创建新的 WS-Resource 时,响应将包含一个指向它的 EndpointReference。
l 什么是 WS-Resource?
至此,您应该在概念上对什么是 WS-Resource 有了很好的理解,并且应该对 WSDL 和 WS-Addressing 有了很好的基本了解。现在开始实际地创建和使用 WS-Resources。
我们首先来定义 WS-Resource 到底真正是什么。在我们的人造卫星例子中,我们可以具有几种类型的 WS-Resources,比如:
一个服务,用于设置或检索特定人造卫星的高度。
一个服务,用于设置或检索特定人造卫星的位置或方位。
一个服务,用于提供对一个进程的访问,该进程计数特定人造卫星观测到的恒星。
关于该列表有两件事情一定要注意:即所有三个 WS-Resources 都可以引用相同的人造卫星,还有,WS-Resource 是由服务和有状态资源(在本例中是人造卫星)的组合定义的,而不是由它可以执行的操作数量定义的。
现 在,我们可以说 WS-Resource 是 Web 服务和有状态资源的组合,但是我们如何在应用程序中表示这个有状态资源呢?答案就在它的 ResouceProperties 中。正如 有状态资源 中提到的,对象的状态可以由它的各种属性的值来决定。因为我们真正感兴趣的就是对象的状态,所以我们可以把有状态资源表示为一个展示其属性的 XML 文档。该文档叫做资源属性文档。在我们的人造卫星例子中,它可能是具有以下代码行的文档:
<satProp:GenericSatelliteProperties xmlns:satProp="http://example.com/satellite">
<satProp:latitude>30.3</satProp:latitude>
<satProp:longitude>223.2</satProp:latitude>
<satProp:altitude>47700</satProp:altitude>
<satProp:pitch>49</satProp:pitch>
<satProp:yaw>0</satProp:yaw>
<satProp:roll>32</satProp:roll>
<satProp:focalLength>21999992</satProp:focalLength>
<satProp:currentView>
http://example.com/satellite/2239992333.zip
</satProp:currentView>
</satProp:GenericSatelliteProperties>
状态的更改需要一个或多个这些属性的更改,反之亦然。
就像可以通过添加成员或方法来扩展类一样,我么可以通过添加属性来扩展 WS-Resource。例如,考虑这样一种情形,我们具有一个人造卫星,它也充当恒星计数器。除了有状态资源的一般属性之外,我们可能还有一个 currentCount 属性:
<satProp:GenericSatelliteProperties
xmlns:satProp="http://example.com/satellite"
xmlns:counterProp="http://example.com/satellite/CounterSatelliteProperties">
<satProp:latitude>30.3</satProp:latitude>
<satProp:longitude>223.2</satProp:latitude>
<satProp:altitude>47700</satProp:altitude>
<satProp:pitch>49</satProp:pitch>
<satProp:yaw>0</satProp:yaw>
<satProp:roll>32</satProp:roll>
<satProp:focalLength>21999992</satProp:focalLength>
<satProp:currentView>
http://example.com/satellite/2239992333.zip
</satProp:currentView>
<counterProp:currentCount>92828</counterProp:currentCount>
</satProp:GenericSatelliteProperties>
注意新信息是在一个独立的名称空间中。
l 合并 WS- 和 Resource:WSDL 文件
至此,我们已经创建了有状态资源(人造卫星)的表示,但是要真正地创建 WS-Resource,我们还必须使用 WSDL 文件将它绑定到服务。
我们首先来看一个基本的 WSDL 文件:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Satellite"
targetNamespace="http://example.com/satellite"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://example.com/satellite"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
location="WS-ResourceProperties.wsdl" />
<types>
<xsd:schema targetNamespace="http://example.com/satellite"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace=
"http://schemas.xmlsoap.org/ws/2004/03/addressing"
schemaLocation="WS-Addressing.xsd" />
</xsd:schema>
</types>
</definitions>
该 文件现在还很空,但是请注意,为了能够工作,还需要导入两个文件。WS-ResourceProperties.wsdl 和 WS-Addressing.xsd 文件的典型版本可能会引用您还没创建在机器上的目录,所以为了简单起见,您可以从教程参考资料 下载简化的版本。
既然有了框架,现在我们就来填充它吧。
首先,我们将实际的有状态资源添加到文件,并将之与 Web 服务关联:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Satellite"
targetNamespace="http://example.com/satellite"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://example.com/satellite"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-
WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-
WS-ResourceProperties-1.2-draft-01.wsdl"
location="WS-ResourceProperties.wsdl" />
<types>
<xsd:schema targetNamespace="http://example.com/satellite"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace=
"http://schemas.xmlsoap.org/ws/2004/03/addressing"
schemaLocation="WS-Addressing.xsd" />
<xsd:element name="latitude" type="xsd:float" />
<xsd:element name="longitude" type="xsd:float" />
<xsd:element name="altitude" type="xsd:float" />
<xsd:element name="pitch" type="xsd:float" />
<xsd:element name="yaw" type="xsd:float" />
<xsd:element name="roll" type="xsd:float" />
<xsd:element name="focalLength" type="xsd:float" />
<xsd:element name="currentView" type="xsd:string" />
<xsd:element name="GenericSatelliteProperties">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="latitude" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="longitude" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="altitude" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="pitch" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="yaw" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="roll" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="focalLength" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="currentView" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<portType name="SatellitePortType"
wsrp:ResourceProperties=
"tns:GenericSatelliteProperties">
</portType>
<binding name="SatelliteSoapBinding"
type="tns:SatellitePortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
</binding>
<service name="SatelliteService">
<port name="SatellitePort"
binding="tns:SatelliteSoapBinding">
<soap:address location=
"http://example.com/satellite"/>
</port>
</service>
</definitions>
我 们首先是添加 Web 服务的基础、实际的 service 元素和将之与 portType 关联的 binding。portType 本身还没有任何操作,但是重要的部分是 wsrp:ResourceProperties 属性。该属性指定,Web 服务执行的任何操作都是在一个特定类型的有状态资源上执行的,如 GenericSatelliteProperties 元素所定义的。GenericSatelliteProperties 元素定义在 schema 中。该有状态资源和该 Web 服务的组合就是 WS-Resource。
注意,规范中指出,在创建资源属性文档(比如本例中的 GenericSatelliteProperties)时,必须 使用这里展示的样式,即初始元素是定义和引用的,而不是内联地定义的。
现在我们向 WSDL 文件添加一些实际的操作,看它是如何工作的。
l 请求新的人造卫星
当然,该练习的整个目的是真正对 WS-Resource 做一些事情,所以我们要做的第一件事情是,创建对实际 WS-Resource 实例的一个引用:
...
<types>
<xsd:schema targetNamespace="http://example.com/satellite"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace=
"http://schemas.xmlsoap.org/ws/2004/03/addressing"
schemaLocation="WS-Addressing.xsd" />
<xsd:element name="createSatellite">
<xsd:complexType/>
</xsd:element>
<xsd:element name="createSatelliteResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="wsa:EndpointReference"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GenericSatelliteProperties">
...
</xsd:element>
</xsd:schema>
</types>
<message name="CreateSatelliteRequest">
<part name="request" element="tns:createSatellite"/>
</message>
<message name="CreateSatelliteResponse">
<part name="response" element=
"tns:createSatelliteResponse"/>
</message>
<portType name="SatellitePortType"
wsrp:ResourceProperties=
"tns:GenericSatelliteProperties">
<operation name="createSatellite">
<input message="tns:CreateSatelliteRequest"
wsa:Action=
"http://example.com/CreateSatellite" />
<output message="tns:CreateSatelliteResponse"
wsa:Action=
"http://example.com/CreateSatelliteResponse" />
</operation>
</portType>
<binding name="SatelliteSoapBinding" type=
"tns:SatellitePortType">
<soap:binding style="document" transport=
"http://schemas.xmlsoap.org/soap/http"/>
<operation name="createSatellite">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort" binding=
"tns:SatelliteSoapBinding">
<soap:address location=
"http://example.com/satellite"/>
</port>
</service>
</definitions>
乍 一看,这与我们在 需要了解的 WSDL 知识 中创建的 WSDL 文件没有太大的区别。我们具有一个指向 binding 的 service,binding 解释如何实现 portType。portType 定义一个操作,即 createSatellite,该操作使用一个 input 和一个 output 消息。这两个消息定义在 schema 中。
这个文件有一点稍微与最初的文件不同:不是返回一个简单的值,服务是返回一个指向新创建的 WS-Resource 的 EndpointReference。我们来看这在 SOAP 消息中是如何实现的。
l SOAP 请求
关于创建 WS-Resource 的实际 SOAP 请求是非常简单的:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<createSatellite xmlns="http://example.com/satellite"/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
我们还没有实际的对象,所以该请求到达 WSDL 文件中列出的 URI,并且我们将该请求定义为一个简单的 createSatellite 元素。
响应要稍微有意思一些。
l SOAP 响应
一旦您发送针对新人造卫星的请求,服务器就创建一个对新 WS-Resource 的引用,并以 EndpointReference 形式将它返回:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<wsa:EndpointReference
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:sat="http://example.org/satelliteSystem">
<wsa:Address>http://example.com/satellite</wsa:Address>
<wsa:ReferenceProperties>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</wsa:ReferenceProperties>
</wsa:EndpointReference>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
注意,EndpointReference 的 Address 元素指向我们在 WSDL 文件中列出的同一 URI,所以信息仍然到达相同的地方,只是量的增多。
现 在我们应该注意,这不是一个普通的端点引用。 ReferenceProperties 元素展示一个标识符,该标识符最终将用于识别 WS-Resource,所以这实际上是一个 WS-Resource 限定的端点引用。正如您马上就会看到的,我们可以使用该信息来对 WS-Resource 做出后续调用。
l 我们想要完成什么?
好的,已经创建了 WS-Resource,那么我们可以对它做什么呢?
实 际上,可以通过调整它的属性来做任何事情。例如,可以通过更改 altitude 属性来改变人造卫星轨道的大小。不,只是更改值并不能移动人造卫星;人造卫星的实际移动是由 Web 服务背后的应用程序决定的。但是这是 WS-Resources 所真正关心的:创建一种方式,以便通过更改属性来操纵对象。规范只是指出了如何将这些更改告诉 Web 服务。它不关心应用程序是如何真正操纵对象的,我们也不关心。
但 是在真正开始更改属性之前,我们先来看看属性。在本节中,首先来看我们在 创建 WS-Resource 中创建的人造卫星 WS-Resource 的 altitude 属性。然后将讲述一次性请求所有的 orientation 值。然后再介绍使用 XPath 来查询多个值。
l 请求属性
请求属性的值是构造适当 SOAP 消息过程中的一个简单过程。例如,假设我们想要请求 altitude 属性的值。基本的 SOAP 消息可能看起来像下面这样:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsrp=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-
ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>...</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetResourceProperty xmlns:satProp=
"http://example.com/satellite">
satProp:altitude
</wsrp:GetResourceProperty>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
wsrp:GetResourceProperty 元素是 WS-ResourceProperties 规范的一部分。我们甚至不必在 WSDL 文件中定义它。它给我们这样一个地方,可以指定我们想要获得值的属性。
但是,SOAP 消息还没有真正完成。是的,它是一个 SOAP 消息,但是如果我们像这样把它发送给 Web 服务,服务将不知道我们引用的是哪个 WS-Resource。接下来我们将关心这个问题。
l 完全的 SOAP 请求
在前一屏,即 请求属性 中,我们创建了一个 SOAP 消息,它指定了我们想要检索的属性,但是为哪个 WS-Resource 创建的呢?
当创建人造卫星时,Web 服务返回一个指向新创建的 WS-Resource 的端点引用。我们可以将该信息添加到 SOAP 消息的 Header,像下面这样:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-
WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProperties/GetResourceProperty
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetResourceProperty
xmlns:satProp="http://example.com/satellite">
satProp:altitude
</wsrp:GetResourceProperty>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
wsa:Action 元 素不是初始端点引用的一部分;它随我们想要做的事情而变化。在本例中,我们使用 GetResourceProperty 操作。wsa:To 元素从端点引用中的 wsa:Address 获得值,而任何 wsa:ReferenceProperty 值都直接包含在 Header 中。
您 会注意到,我们没有讨论 SatelliteId 值。这是故意的。包含在端点引用中的任何用于识别特定 WS-Resource 的信息都必须被应用程序忽略,只是在发送消息时要传送它。根据规范,即使尝试去解释值也认为是不适当的。这意味着被传输为一个“黑盒”,导致一种未经检查 的生活。
l 接收 ResourceProperty
一旦请求属性,就需要获得返回值,并且 WS-ResourceProperties 规范也定义了这种消息的形式。在我们的例子中,我们将接收这样一个消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENV=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-
ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-
ResourceProperties/GetResourcePropertyResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/myClient
</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetResourcePropertyResponse
xmlns:satProp=
"http://example.com/satellite">
<satProp:altitude>
47700
</satProp:altitude>
</wsrp:GetResourcePropertyResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在 本例中,Header 信息并不引用服务,而是引用客户机; http://example.com/myClient 是应该接收响应的客户机的 URI。在大多数情况下,这与发出请求的客户机是相同的,但是您也可以使用 wsa:Reply-To 元素将响应发送到别的地方。
在实际的消息体中还有一个标准元素 wsrp:GetResourcePropertyResponse,但是在本例中,它包含请求的实际属性,以及它的当前值。
现在来看这在 WSDL 文件中是什么样的。
l WSDL 文件
为了将这些功能添加到应用程序,我们需要将它们添加到 WSDL 文件,但是因为我们使用已经定义好的标准消息交换模式,所以我们只需要添加一个新操作,像下面这样:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Satellite"
targetNamespace="http://example.com/satellite"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://example.com/satellite"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/
wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrpwsdl=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-
ResourceProperties-1.2-draft-01.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:import namespace=
"http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
location="WS-ResourceProperties.wsdl" />
<types>
<xsd:schema targetNamespace="http://example.com/satellite"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
...
</xsd:schema>
</types>
<message name="CreateSatelliteRequest">
<part name="request" element="tns:createSatellite"/>
</message>
<message name="CreateSatelliteResponse">
<part name="response" element="tns:createSatelliteResponse"/>
</message>
<portType name="SatellitePortType"
wsrp:ResourceProperties="tns:GenericSatelliteProperties">
<operation name="createSatellite">
<input message="tns:CreateSatelliteRequest"
wsa:Action="http://example.com/CreateSatellite" />
<output message="tns:CreateSatelliteResponse"
wsa:Action="http://example.com/CreateSatelliteResponse" />
</operation>
<operation name="getAltitude">
<input message="wsrpwsdl:GetResourcePropertyRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/
06/WS-ResourceProperties/GetResourceProperty/>
<output message="wsrpwsdl:GetResourcePropertyResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/
06/WS-ResourceProperties/GetResourcePropertyResponse/>
</operation>
</portType>
<binding name="SatelliteSoapBinding" type="tns:SatellitePortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="createSatellite">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="getAltitude">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort" binding=
"tns:SatelliteSoapBinding">
<soap:address location=
"http://example.com/satellite"/>
</port>
</service>
</definitions>
一 开始是 portType,我们创建一个叫做 getAltitude 的新操作。该操作具有一个 input 和一个 output 消息,但是两个消息都已经定义在我们以前导入的 WS-ReferenceProperties.wsdl 文件中,所以我们需要做的就是使用适当的名称空间别名来引用它们。
一旦创建了 operation,我们只要将它添加到 binding 就行了,而这一点我们已经很内行了。
l 请求多个属性
幸运的是,我们并不局限于检索单个属性值。我们也可以检索多个属性:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-Resour
ceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/
WS-ResourceProperties/GetMultipleResourceProperties
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetMultipleResourceProperties
xmlns:satProp="http://example.com/satellite">
<wsrp:ResourceProperty>
satProp:roll
</wsrp:ResourceProperty>
<wsrp:ResourceProperty>
satProp:pitch
</wsrp:ResourceProperty>
<wsrp:ResourceProperty>
satProp:yaw
</wsrp:ResourceProperty>
</wsrp:GetMultipleResourceProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
同前面一样,Header 中的信息来自端点引用。
l 接收多个属性
响应消息类似于它的单个属性对应物:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/200
4/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-Res
ourceProperties/GetMultipleResourcePropertiesResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/myClient
</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:GetMultipleResourcePropertiesResponse
xmlns:satProp="http://example.com/satellite">
<satProp:roll>32</satProp:roll>
<satProp:pitch>49</satProp:pitch>
<satProp:yaw>0</satProp:yaw>
</wsrp:GetMultipleResourcePropertiesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
同样,我们要将它添加到 WSDL 文件。
l WSDL 文件
同样,因为我们传递的实际消息已经定义在 WS-ResourceProperties.wsdl 文件中,把该功能添加到应用程序所要做的就是创建一个新 operation:
...
<message name="CreateSatelliteRequest">
<part name="request" element=
"tns:createSatellite"/>
</message>
<message name="CreateSatelliteResponse">
<part name="response" element=
"tns:createSatelliteResponse"/>
</message>
<portType name="SatellitePortType"
wsrp:ResourceProperties =
"tns:GenericSatelliteProperties">
<operation name="createSatellite">
<input message="tns:CreateSatelliteRequest"
wsa:Action=
"http://example.com/CreateSatellite" />
<output message="tns:CreateSatelliteResponse"
wsa:Action=
"http://example.com/CreateSatelliteResponse" />
</operation>
<operation name="getAltitude">
<input message=
"wsrpwsdl:GetResourcePropertyRequest"
wsa:Action="http://docs.oasis-open.org/ws
rf/2004/06/WS-ResourceProperties/GetResourceProperty"/>
<output message=
"wsrpwsdl:GetResourcePropertyResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/GetResourcePropertyResponse"/>
</operation>
<operation name="getOrientation">
<input message="wsrpwsdl:
GetMultipleResourcePropertiesRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/GetMultipleResourceProperties"/>
<output message=
"wsrpwsdl:GetMultipleResourcePropertiesResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourcePro
perties/GetMultipleResourcePropertiesResponse"/>
</operation>
</portType>
<binding name="SatelliteSoapBinding" type=
"tns:SatellitePortType">
<soap:binding style="document"
transport=
"http://schemas.xmlsoap.org/soap/http"/>
<operation name="createSatellite">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="getAltitude">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="getOrientation">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort" binding="tns:SatelliteSoapBinding">
<soap:address location="http://example.com/satellite"/>
</port>
</service>
</definitions>
一旦我们将 getOrientation operation 添加到了 binding,它就可以由应用程序使用了。
我们也可以查询属性,正如您马上就会看到的。
l 使用 XPath 查询
尽 管请求所需的属性相当直观,但是也有需要使用其他方法的情景。不是简单地按名称请求资源属性,我们可以使用 XPath 中可用的查询。(有关 XPath 的更多信息,请参阅 参考资料。)例如,如果不能确定某个特定的属性是否存在,您可能想要在属性上使用 XPath 函数。
XPath 的 另一个有用功能是,能够请求多个相同命名的属性,或者甚至能够查询参数。我们将在“理解 WSRF(第 2 部分)”中做前一件事,而马上就会做后一件事。例如,我们可以与 boolean() 函数一起使用一个 XPath 表达式,来确定人造卫星是否指向正确的方向,而不用显式地分析数据:
<SOAP-ENV:Envelope xmlns:SOAP-ENV=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/20
04/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-ResourcePro
perties/QueryResourceProperties
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:QueryResourceProperties>
<wsrp:QueryExpression Dialect=
"http://www.w3.org/TR/1999/REC-xpath-19991116">
boolean(/*/pitch=25 and /*/roll=0 and /*/yaw=10)
</wsrp:QueryExpression>
</wsrp:QueryResourceProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
注 意 Dialect 属性的使用,以区分 XPath V1.0 (这里展示的)和 XPath V2.0(http://www.w3.org/TR/2003/WD-xpath20-20031112)。规范没有限制您可以支持的方言 (dialect),但是如果实现不认识 Dialect,它就会返回一个 fault 和错误。
l 查询结果
结果看起来非常像前面的两个响应:
<SOAP-ENV:Envelope xmlns:SOAP-ENV=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/20
04/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/
WS-ResourceProperties/Quer
yResourcePropertiesResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/myClient
</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:QueryResourcePropertiesResponse>
false
</wsrp:QueryResourcePropertiesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在本例中,我们只是返回一个布尔值,但是您可以返回 XPath 可以返回的任何类型的值。
l WSDL 文件
同样,我们向 WSDL 文件添加一个新 operation:
...
<portType name="SatellitePortType"
wsrp:ResourceProperties=
"tns:GenericSatelliteProperties">
...
<operation name="getOrientation">
<input message=
"wsrpwsdl:GetMultipleResourcePropertiesRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/20
04/06/WS-ResourceProperties/GetMultipleResourceProperties"/>
<output message=
"wsrpwsdl:GetMultipleResourcePropertiesResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/W
S-ResourceProperties/GetMultipleResourcePropertiesResponse"/>
</operation>
<operation name="checkOrientation">
<input message=
"wsrpwsdl:QueryResourcePropertiesRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/20
04/06/WS-ResourceProperties/QueryResourceProperties"/>
<output message=
"wsrpwsdl:QueryResourcePropertiesResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/W
S-ResourceProperties/QueryResourcePropertiesResponse"/>
</operation>
</portType>
<binding name="SatelliteSoapBinding" type=
"tns:SatellitePortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
...
<operation name="getOrientation">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="checkOrientation">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort" binding=
"tns:SatelliteSoapBinding">
<soap:address location=
"http://example.com/satellite"/>
</port>
</service>
</definitions>
这关注检索属性。现在来看设置属性的值。
l 我们想要完成什么
至此,我们创建了一个 WS-Resource,并且了解了一个或多个用于表示它的状态的属性。但是这与真正地操纵 WS-Resource 没有太大的关系。在本节中,我们来看添加、悬挂和删除 WS-Resource 的属性。
至 此,我们的人造卫星已经在天空中相对于地球的轨道中稳定了,而不是观测到某些特定的东西了。在本节中,我们要添加一个 ResourceProperty,它表示一个特定的目标。然后我们通过更新位置属性将人造卫星移向该目标,然后再删除所创建的目标属性。最后,通过将适 当的操作添加到 WSDL 文件,我们将把所有事情综合在一起。
l 添加属性
向 WS-Resource 添加属性涉及到使用 Insert 元素:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/
2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/W
S-ResourceProperties/SetResourceProperties
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:SetResourceProperties
xmlns:satProp="http://example.com/satellite">
<wsrp:Insert>
<satProp:targetCoords>
36n11, 115w08
</satProp:targetCoords>
</wsrp:Insert>
</wsrp:SetResourceProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
我们可以给这个新属性取任何好听的名字,但是我们必须允许该新元素在 Resource Properties 文档中。(当我们在 WSDL 文件 中调整 WSDL 文件时将来做这一件事。)
l 添加属性的结果
当成功添加、删除或更改属性之后,我们将会得到一个只是确认操作的响应消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENV=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/
2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/W
S-ResourceProperties/SetResourcePropertiesResponse
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/myClient
</wsa:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:SetResourcePropertiesResponse>
</wsrp:SetResourcePropertiesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
该响应与 Update 和 Delete 操作产生的响应是相同的。
l 更改属性值
在 添加属性 中,我们添加了一个新属性,但是我们也能更改现有属性的值。例如,我们可以告诉系统,通过使用 Update 元素更改人造卫星的位置属性来移动人造卫星:
<SOAP-ENV:Envelope xmlns:SOAP-ENV=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/0
6/wsrf-WS-ResourceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-Re
sourceProperties/SetResourceProperties
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:SetResourceProperties
xmlns:satProp="http://example.com/satellite">
<wsrp:Update>
<satProp:latitude>36.11</satProp:latitude>
</wsrp:Update>
<wsrp:Update>
<satProp:longitude>158.08</satProp:latitude>
</wsrp:Update>
</wsrp:SetResourceProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在本例中,我们使用了两个 Update 组件,但是我们实际上可以使用 Insert、Update 和 Delete 组件的任意组合。
l 删除属性
属性可以被完全删除。例如,如果我们决定不再观测某个特定的目标,就可以删除该属性:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sat="http://example.org/satelliteSystem"
xmlns:wsa="http://www.w3.org/2005/02/addressing"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-Resour
ceProperties-1.2-draft-01.xsd">
<SOAP-ENV:Header>
<wsa:Action>
http://docs.oasis-open.org/wsrf/2004/06/WS-Resou
rceProperties/SetResourceProperties
</wsa:Action>
<wsa:To SOAP-ENV:mustUnderstand="1">
http://example.com/satellite
</wsa:To>
<sat:SatelliteId>SAT9928</sat:SatelliteId>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<wsrp:SetResourceProperties
xmlns:satProp="http://example.com/satellite">
<wsrp:Delete resourceProperty="targetCoords"/>
</wsrp:SetResourceProperties>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
同样,我们的资源属性文档的模式定义必须允许我们做这一更改。
l WSDL 文件
同样,因为标准元素已经定义在 WS-ResourceProperties.wsdl 中,所以我们可以简单地添加新操作:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Satellite"
targetNamespace="http://example.com/satellite"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://example.com/satellite"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/
wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
xmlns:wsrpwsdl="http://docs.oasis-open.org/wsrf/200
4/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:import namespace="http://docs.oasis-open.org/
wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
location="WS-ResourceProperties.wsdl" />
<types>
<xsd:schema
targetNamespace="http://example.com/satellite"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace=
"http://schemas.xmlsoap.org/ws/2004/03/addressing"
schemaLocation="WS-Addressing.xsd" />
<xsd:element name="createSatellite">
<xsd:complexType/>
</xsd:element>
<xsd:element name="createSatelliteResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref=
"wsa:EndpointReference"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="latitude" type="xsd:float" />
<xsd:element name="longitude" type="xsd:float" />
<xsd:element name="altitude" type="xsd:float" />
<xsd:element name="pitch" type="xsd:float" />
<xsd:element name="yaw" type="xsd:float" />
<xsd:element name="roll" type="xsd:float" />
<xsd:element name="focalLength" type="xsd:float" />
<xsd:element name="currentView" type="xsd:string" />
<xsd:element name="GenericSatelliteProperties">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="latitude" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="longitude" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="altitude" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="pitch" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="yaw" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="roll" minOccurs="1"
maxOccurs="1"/>
<xsd:element ref="focalLength"
minOccurs="1" maxOccurs="1"/>
<xsd:element ref="currentView"
minOccurs="1" maxOccurs="1"/>
<xsd:any/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<message name="CreateSatelliteRequest">
<part name="request" element="tns:createSatellite"/>
</message>
<message name="CreateSatelliteResponse">
<part name="response" element=
"tns:createSatelliteResponse"/>
</message>
<portType name="SatellitePortType"
wsrp:ResourceProperties=
"tns:GenericSatelliteProperties">
<operation name="createSatellite">
<input message="tns:CreateSatelliteRequest"
wsa:Action="http://example.com/CreateSatellite" />
<output message="tns:CreateSatelliteResponse"
wsa:Action=
"http://example.com/CreateSatelliteResponse" />
</operation>
<operation name="getAltitude">
<input message=
"wsrpwsdl:GetResourcePropertyRequest"
wsa:Action="http://docs.oasis-open.org/wsr
f/2004/06/WS-ResourceProperties/GetResourceProperty"/>
<output message=
"wsrpwsdl:GetResourcePropertyResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/GetResourcePropertyResponse"/>
</operation>
<operation name="getOrientation">
<input message=
"wsrpwsdl:GetMultipleResourcePropertiesRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/GetMultipleResourceProperties"/>
<output message=
"wsrpwsdl:GetMultipleResourcePropertiesResponse"
wsa:Action=
"http://docs.oasis-open.org/wsrf/2004/06/WS-ResourceProp
erties/GetMultipleResourcePropertiesResponse"/>
</operation>
<operation name="checkOrientation">
<input message=
"wsrpwsdl:QueryResourcePropertiesRequest"
wsa:Action="http://docs.oasis-open.org/wsr
f/2004/06/WS-ResourceProperties/QueryResourceProperties"/>
<output message=
"wsrpwsdl:QueryResourcePropertiesResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/QueryResourcePropertiesResponse"/>
</operation>
<operation name="addTarget">
<input message=
"wsrpwsdl:SetResourcePropertiesRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/SetResourceProperty"/>
<output message=
"wsrpwsdl:SetResourcePropertiesResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/SetResourcePropertyResponse"/>
</operation>
<operation name="moveToTarget">
<input message=
"wsrpwsdl:SetResourcePropertiesRequest"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/SetResourceProperty"/>
<output message=
"wsrpwsdl:SetResourcePropertiesResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/SetResourcePropertyResponse"/>
</operation>
<operation name="removeTarget">
<input message=
"wsrpwsdl:SetResourcePropertiesRequest"
wsa:Action="http://docs.oasis-open.org/ws
rf/2004/06/WS-ResourceProperties/SetResourceProperty"/>
<output message=
"wsrpwsdl:SetResourcePropertiesResponse"
wsa:Action="http://docs.oasis-open.org/wsrf/2004/0
6/WS-ResourceProperties/SetResourcePropertyResponse"/>
</operation>
</portType>
<binding name="SatelliteSoapBinding"
type="tns:SatellitePortType">
<soap:binding style="document" transport=
"http://schemas.xmlsoap.org/soap/http"/>
<operation name="createSatellite">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="getAltitude">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="getOrientation">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="checkOrientation">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="addTarget">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="moveToTarget">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="removeTarget">
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SatelliteService">
<port name="SatellitePort"
binding="tns:SatelliteSoapBinding">
<soap:address location=
"http://example.com/satellite"/>
</port>
</service>
</definitions>
还请注意,我们可以添加任意元素到 GenericSatelliteProperties,所以我们可以容易地添加新属性,比如 targetCoords。
l 结束语
在本教程,也即 4 篇关于 WSRF 的系列文章中的第一篇文章中,我们一开始解释了 WSRF 背后的目的,以及为什么单有 Web 服务还不够。然后解释了 WS-Resource 是有状态资源(比如数据库或卫星)与 Web 服务的组合。
资源本身是由一系列属性来描述的,这些属性是与 WSDL 文件中的 Web 服务相关联的。我们还介绍了 WSDL 和 WS-Addressing 的基础,WSRF 使用 WS-Addressing 来指向一个特定的 WS-Resource 实例。
我们介绍了创建 WS-Resources,了解了它们的属性,以及调整这些属性,以便操纵资源。
在 本系列的以后部分中,我们将会介绍 WSRF 的一些更高级的用途,比如 ServiceGroups 和错误处理,以及 WS-Notifications。在本系列的最后一部分中,我们将把所有内容综合在一起,并编写一个应用程序,它使用类来实现本系列前两部分中讨论的每 个概念。
l 参考资料
Web 服务资源框架(Web Services Resource Framework,WSRF)涉及大量不同领域。下面是起步所需的一些参考资料:
单击 下载本教程中介绍的完整 WSDL 文件。
WSRF 和相关规范
WSRF 文档 的主要位置在 Globus Alliance Web 站点上,但是最新的规范可以在 Oasis 处找到。文档包括:
Web 服务资源框架(白皮书)
The WS-Resource Framework
WS-ResourceProperties (WSRF-RP)
WS-ResourceLifetime (WSRF-RL)
WS-ServiceGroup (WSRF-SG)
WS-Base Faults (WSRF-BF)
Web 服务和相关的规范
Author: orangelizq
email: orangelizq@163.com