当前位置: 代码迷 >> Web前端 >> Webservice-三
  详细解决方案

Webservice-三

热度:415   发布时间:2013-11-08 17:52:14.0
Webservice-3

【WSDL的产生】

为了在具体的web服务中使用SOAP,需要事先知道如何构造SOAP消息,要采用哪一种通讯协议(如HTTP或SMTP)以及Web服务的Internet地址。总而言之,需要使用文档。
比如我们在SOAP文档里写到的BookQuote的SOAP消息非常简单,如1-1例:
<?xml version = “1.0” encoding= “UTF-8”>
<sopa:Envelope
Xmlns:soap=Http://schemas.xmlsoap.org/soap/envelope/
Xmlns:mh=”Http://www.Monson-Haefel.com/jwsbook/BookQuote”>

<soap:Body>

<mh:getBookPrice>

<isbn>0930849028</isbn>

</mh:betBookPrice>

</soap:Body>
</soap:Envelope>
虽然这个上个文档介绍的BookQuote Web服务的描述非常易于理解,但它并不是结构良好的文档,如果所有的Web服务都以这种方式描述,那么每当用户希望使用一个新的Web服务时,就需要读一个非正规的文档了。为了避免出现非正规文档的问题,Web服务社团采用了WSDL(Web Services Description Language,Web服务描述语言)。WSDL是一个用于精确描述Web服务的文档格式。
【WSDL的作用】---------------------------------------------------------

Wsdl用来指定客户与具体的Web服务通信时必须使用的确切的消息格式,Internet协议以及地址。换句话说,WSDL文档要告诉用户如何使用Web服务。Wsdl是Web服务的另外一个事实标准,而且像SOAP一样,它得到了广泛的认可,现在基本上所有的厂商都支持WSDL。

WSDL非常合适做代码生成器,它能够读WSDL文档,并可以访问Web服务生成一个程序化的接口。比如,JAX-RPC提供者要用WSDL1.1生成Java RMI 接口和网络占位程序,他们可用于与Web服务交换SOAP消息。

JAX-RPC提供者是JAX-RPC API的一个供应商实现。比如,BEA WebLogic是一个JAX-RPC提供者。所有的J2EE1.4应用程序服务器是JAX-RPC提供者,因为它们均提供他们自己的JAX-RPC API实现。
?????? 虽然WSDL特别适合用作代码生成器,但当使用其他的Web服务工具和API时,WSDL也是非常有用。比如,许多的Web服务客户要使用SOAP API而不是使用生成的调用接口和占位程序。这些API通常要用像Envelope,Header,Body,Fault这样的对象对SOAP消息的结构进行建模。【当用户使用SOAP API时,可以用Web服务的WSDL作为与那个Web服务交换SOAP消息的向导。】
?????? 虽然人们把WSDL看成一个Web服务标准,但它其实并不简单,这可能是它的最大障碍,本人看了很多的内容,到现在还是没有完全理解,自己觉得WSDL的复杂性取决于其设计者的目的,即对没有与任何具体的协议,编程语言或操作系统有联系的Web服务创建一个IDL(interface definition language,接口定义语言)。还有顺便说一下,WSDL1.1并不是专门用于SOAP,可以用它描述没有基于SOAP的Web服务。
?????? 模块化是WSDL的另一个设计目的。由于WSDL非常模块化,因此用户可以重复使用它的功能来描述多个Web服务。非常遗憾的是,我觉得这样使得初学者很难读懂WSDL文档。我希望大家能认真的读懂前面的基本概念,还要去理解前面写的SOAP文档和深入了解一下XML的东西,可是很多情况下,用户从不需要读写自己的WSDL文档,因此自己的J2EE平台通常会自动创建并处理这些文档。我想在这说一下的是,如果你真的想真正的了解J2EE web services 我建议大家别用市面上的那些软件。。毕竟以后你用JAX-RPC的时候你会摸不到头脑,因为你根本不清楚这些WSDL的内部构造是怎么样的。顶多你只能应用而已。
【WSDL的基本结构】------------------------------------

WSDL文档是一个遵循WSDL XML模式的XML文档。作为XML文档实例,如果要使WSDL文档有效且格式良好的话,应必须以正确的方式使用正确的元素(感觉是废话哇,可是你看完下面的介绍你就知道为什么我要强调这些了)。下面的部分将介绍WSDL的结构以及如何构造恰当描述Web服务的WSDL。虽然WSDL能够用于描述任何种类的Web(从理论说),但我会重点介绍基于SOAP且符合WS-I Basic Profile 1.0(对这个陌生的可以去看看我发布的SOAP消息的文档)的Web服务的WSDL文档。
?????? 一个WSDL文档包括了7个重要元素,即 types,import,message,porttype,operation,binding和services。这些元素嵌套于definitions元素中。Definitions元素是WSDL的根元素。来看看下面的表吧:
元素名称

?元素作用

?
Types
?使用了XML模式语言声明在WSDL文档中的其他位置使用的复杂数据类型与元素。
?
Import
?类似于XML模式文档中的import元素,用于其他WSDL文档中导入WSDL定义
?
Message
?使用在WSDL文档的type元素中定义或在import元素引用的外部WSDL文档中定义的XML模式内置类型,复杂类型或元素描述了消息的有效负载。
?
Porttype
?和operation元素描述了web服务的接口并定义了它的方法。Porttype元素及其operation元素类似于java接口和它的方法声明。
?
Operation
?需要定义多个或一个message类型来定义它的输入和输出有效负载。
?
Binding
?此元素将porttype元素及其operation元素赋给一个特殊协议(如SOAP1.1)和编码样式。
?
Services
?此元素负责将一个internet地址赋给一个具体的绑定。
?
Documentation
?此元素向读者说明了WSDL文档方面的一些信息,其他任何WSDL元素均可以包含documentation元素,documentation元素并不重要,我不会继续介绍了。
?

看看下面的1-2例子是一个非常简单的WSDL文档实例,该文档描述了前面SOAP里的BookQuote的Web服务,当大家读到这里时,要记住它要描述一个Web服务以及用于访问该Web服务的SOAP消息类型,协议和Internet地址的类型:
示例1-2:
<?xml version = “1.0” encoding= “UTF-8”>
<definitions name = “BookQuoteWS”
targetNamespace = http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:mh=http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:soapbind=http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=http://www.w3.org/2001/XMLScheam
xmlns=”http://schemas.xmlsopa.org/wsdl”>

<!―消息元素(message)描述了输入和输出的参数-->
<message name = “GetBookPriceRequest”>

<part name = “isnb” type = “xsd:string”>
</messgae>

<message name = “GetBookPriceResponse”>

<part name = “price” type = “xsd:float”>
</messgae>

<!―portType 元素描述了web services 的抽象接口-->
<portType name = “BookQuote”>

<operation name = “getBookPrice”>

<input name = “isbn” message = “mh:GetBookPriceRequest”/>

<output name = “price” message = “mh:GetBookPriceRespsonse”/>

</operation>
</portType>

<!―binding 告诉了我们哪些协议和内码样式被使用-->

<binding name = “BookPrice Binding” type = “mh:BookQuote”>

<soapbind:binding style = “rpc”
Transport = http://schemas.xmlsoap.org/soap/http/>
<operation name = “getBookPrice”>

<soapbind: operation styles = “rpc”
Soap:Action =
http://www.Monson-Haefel.com/jwsbook/BookQuote/GetBookPrice/>
<input>

<soapbind.body use = “literal”
Namespace = http://www.Monson-Haefel.com/jwsbook/BookQuote />

</input>

<output>

<soapbind:body use = “literal”
Namespace = http://www.Monson-Haefel.com/jwsbook/BookQuote />

</output>

</operation>

</binding>

<!―services 告诉我们Web Services的Internet地址-->

<services name = “BookPriceServices”>

<port name = “BookPrice_port” binding = “mh:BookPrice_Binding”>

<soapbind:address location =
http://www.Monson-Haefel.com/jwsbook/BookQuote />

</port>
</services>
</definitions>

也许大家读到这里有点晕了吧。。。正常,不要泄气,这是初学WSDL的正常表现。在后面会对1-2例里出现的元素与属性作用,详细分解。

【WSDL声明:definitions元素,types元素和import元素】
【definitions元素详解】----------------------------------
所有WSDL文档的根元素均是definitions元素。该元素封装了整个文档,同时还通过它的名称提供了一个WSDL文档。
<definitions name = “BookQuoteWS”
targetNamespace = http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:mh=http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:soapbind=http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=http://www.w3.org/2001/XMLScheam
xmlns=”http://schemas.xmlsopa.org/wsdl”>
definitions元素通常包含了若干个XML命名空间声明,这妒意根元素来说是正常的。这些声明中包括一个用于WSDL1.1XML模式的命名空间 http://schemas.xmlsoap.org/wsd/的声明。将WSDL命名空间声明为默认命名空间,就不再需要前缀来显示限定每一个WSDL元素了。

Definitions元素中的第一个属性是name,该属性用来命名整个WSDL文档。其实整个属性不是那么重要,因为根本无任何对象要引用它。

Definitions元素还定义了一个targetNamespace属性,该属性指定了WSDL文档中定义的命名空间,就像XMK模式文档中指定命名空间一样。

Message,portType和binding元素利用他们的name属性指定了标签。这些标签会自动使用由targetNamespace属性指定的命名空间(这些例子还使用了targetnamespace属性赋给了URI的前缀mh)。标签的message,portType,binding元素通常成为定义。这些定义假设了由targetnamespace属性指定的命名空间。
?????? 文档中的其他元素用他们的标签和命名空间前缀引用定义。通常将带有前缀的标签看成是一个定义的完全限定名称。例如,下面的1-3例子中,input和output元素要用它们的限定名称引用消息定义。
<message name = “GetBookPriceRequest”>

<part name = “isnb” type = “xsd:string”>
</messgae>

<message name = “GetBookPriceResponse”>

<part name = “price” type = “xsd:float”>
</messgae>

<!―portType 元素描述了web services 的抽象接口-->
<portType name = “BookQuote”>

<operation name = “getBookPrice”>

<input name = “isbn” message = “mh:GetBookPriceRequest”/>

<output name = “price” message = “mh:GetBookPriceRespsonse”/>

</operation>
</portType>
【types元素详解】-----------------------------------------------------

WSDL采用了W3C XML模式内置类型(我们常理解为基本类型)。Type元素用作一个容器,用于定义XML模式内置类型(即复杂类型和定制的简单类型)中没有描述的各种数据类型。当声明消息部分(即有效负载)时,消息定义使用了在types元素中定义的数据类型与元素。
?????? 下面的1-4例子没有使用types元素,我觉得不需要。直接的消息定义getBookPriceRequest和getBookPriceResponse引用了简单的内置数据类型。
?????? 如果愿意,可以为ISBN号定义定制的简单类型,并在GetBookPriceRequest消息中使用该类型而不是内置String类型,让我们来看看实例1-4吧:

<definitions name = “BookQuoteWS”
targetNamespace = http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:mh=http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:soapbind=http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=http://www.w3.org/2001/XMLScheam
xmlns=”http://schemas.xmlsopa.org/wsdl”>

<types>

<xsd:schema
targetNamespace = “http://www.Monson-Haefel.com/jwsbook/BookQuote”>
<!―这是ISBN的简单类型-->
<xsd:simpleType name = “ISBN”>

<xsd:restriction base = “xsd:string”>

<xsd:pattern value = “[0-9]{9}[0-9Xx]”>

</xsd:restriction>

</xsd:simpleType>

</xsd:schema>

</types>
<message name = “GetBookPriceRequest”>

<part name = “isnb” type = “mh:ISBN”>
</messgae>

<message name = “GetBookPriceResponse”>

<part name = “price” type = “xsd:float”>
</messgae>
……………………………………………..
</definitions>

在这里1-4例子中,types元素中直接嵌套了一个完成的W3C XML模式文档。实例1-4还定义了定制的简单类型(标签ISBN),并通过XML模式targetnamespace属性将其赋给了mh命名空间,然后用mh:ISBN类型定义了GetBookPriceRequest消息定义的isbn部分。

XML模式的targetnamespace属性必须是一个有效的非空值,否则该类型个元素不属于一个有效的命名空间。此外,在types元素中定义的XML模式必须属于一个由WSDL文档(通常位于definitions元素中)指定的命名空间,或属于一个导入的WSDL文档的命名空间。换句话说,WSDL文档必须知道文档使用的各个命名空间。
【特别补充】------------------------------------------------------------

SOAP和WSDL均定义了属性与编码类型,用户可以用它们定义数组数据类型。但是这些数组类型和属性引起了混乱,并引起互操作性方面的问题,所以BP严格禁止使用他们。简单地说,不允许使用为SOAP1.1编码定义的Array类型或arrayType属性,也不允许使用由WSDL定义的WSDL arrayType属性。此外,用户不能将数组类型标记为WSDL1.1注释建议的ArrayOfxxxx形式。这些要求并不是障碍,因为XML模式提供了用于定义数组的更加容易的方式。
?????? 定义数组时用户需要做的工作是用大于0的maxOccurs属性加值(如10,222222或unbounded定义)定义一个复杂类型。而且用户还有其自己的基本数组如下例1-5:

<definitions name = “BookQuoteWS”
targetNamespace = http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:mh=http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:soapbind=http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=http://www.w3.org/2001/XMLScheam
xmlns=”http://schemas.xmlsopa.org/wsdl”>

<types>

<xsd:schema
targetNamespace = “http://www.Monson-Haefel.com/jwsbook/BookQuote”>
<!―这是简单的类似数组的类型-->
<xsd:simpleType name = “ISBN”>


<xsd:element name = “arg” type = “xsd:int” maxOccurs = “unbounded”>

</xsd:simpleType>

</xsd:schema>

</types>

【import元素】----------------------------------------------------------
Import元素使得可以在当前WSDL文档中使用在其他WSDL文档中指定的命名空间中的定义有效。如果用户希望模块化WSDL文档(如为了将抽象定义(types,message,porttype元素)与具体定义(binding,services和port元素)相区分),则此功能非常有用。
?????? 使用import元素的另一个原因是,将若干个想要单独维护的定义放在一个WSDL文档中,但要在可由商业伙伴访问的公共目录中对所有Web服务提供一个完整的定义。让我们看看下面的1-6例子吧:
<definitions name = “AllMhWebServices”
Xmlns=http://schemas.xmlsoap.org/wsdl/ >
<import namespace = http://www.Monson-Haefel.com/jwsbook/BookQutoe
Location = “http://www.Monson-Haefel.com/jwsbook/BookPrice.wsdl”>

<import namespace = http://www.Monson-Haefel.com/jwsbook/Po
Location = “http://www.Monson-Haefel.com/jwsbook/wsdl/PurchaseOrder.wsdl”>

<import namespace = http://www.Monson-Haefel.com/jwsbook/Shipping
Location = “http://www.Monson-Haefel.com/jwsbook/wsdl/Shipping.wsdl”>

</definitions>

WSDL的import元素必须声明2个属性,即namespace属性和location属性。Namespace属性的值必须与正导入的WSDL文档中声明的targetnamespace相匹配,location属性必须指向一个实际的WSDL文档,不能为空。
?????? 有人将location属性看成一条线索。如果读WSDL文档的应用程序在本地缓存或储存了所导入的WSDL文档的复制,那么location属性有可能要使用他们。
【特别注意】-----------------------------------------------------------------

Import元素的使用很容易,但它也会引起版本匹配问题。如果WSDL文档是单独维护的,那么就非常有可能出现导入的文档发生更改(希望这里大家好好想想为什么),但没有考虑导入它的WSDL文档的现象。要保证在更改导入的WSDL文档时考虑版本问题。
----------------------------------------------

?????? 用户可以使用import元素和types元素,但应该在WSDL文档的types元素之前列出import元素。
?????? 就WSDL的import元素的目的而言有许多的混乱。有些人认为应该用该元素导入WSDL文档或导入XML模式文档,而有些人则认为它只适用于导入WSDL文档。不同的解释引起了互操作性问题。因此,BP规定WSDL的import元素能能引用WSDL文档。如果用户用户需要导入一个XML模式元素,则应该在WSDL type元素内包含的模式定义中导入。【需要注意的是 用户不能用XML模式的import语句直接从其他一些WSDL文档的types元素中导入一个XML模式】
【WSDL抽象接口:message元素,portType元素和operation元素】-----------------------------------

Message,portType和operation元素均用于描述Web服务的抽象接口。portType元素将operation定义和message定义组合成一个与java的接口定义类似的抽象接口。portType元素描述了Web服务所支持的操作种类(即消息传递模式和有效负载),但没有指定所用的Internet协议或地址。
【message元素】-------------------------------------------------------------

Message元素描述了Web服务使用的消息的有效负载。Message元素可以描述输出或接收消息的有效负载,即直接发送到Web服务或直接从Web服务接收到的消息。此外,message元素可以描述SOAP文件头和错误detail元素的内容。定义message元素的方式取决于用户使用RPC模式或者是文档样式的消息传递模式。
?
?
?TOP
?
?

xt19833 发短消息
加为好友
xt19833 当前离线

UID394352 帖子24 精华0 金币62? 代金券35? 阅读权限100 在线时间20 小时 注册时间2006-12-18 最后登录2008-4-2?
进士

?

UID394352 帖子24 精华0 金币62? 代金券35? 阅读权限100? 3楼? 发表于 2007-8-29 10:28 | 只看该作者
【用于RPC样式Web服务的message元素】------------------------------------------------------
?????? 当使用RPC样式的消息传递时,message元素描述了SOAP请求和应答消息的有效负载。这些元素可以描述调用参数,调用返回值,文件头以及错误。比如,SOAP文档中的BookQuote Web服务用2个message元素来描述该服务的参数与返回值(以后在介绍如何用消息描述错误和文件头)下面1-7例子:
<message name = “GetBookPriceRequest”>

<part name = “isnb” type = “xsd:string”>
</messgae>

<message name = “GetBookPriceResponse”>

<part name = “price” type = “xsd:float”>
</messgae>


GetBookPriceRequest消息表示参数(即输入),GetBookPriceResponse表示应答(即输出)。换句话说,GetBookPriceRequest消息藐视了从SOAP客户向BookQuote Web服务所传递的消息的有效负载,而GetBookPriceResponse消息描述了由BookQuote Web服务传递回客户的有效负载。
?????? 其实命名消息并没有规定习惯,在我这次写的文档中,从SOAP客户传递给服务器的消息附加有后缀Request,而传递回客户的消息则附加后缀Response。大家可以采用自己的命名习惯,就是说消息名称可以是任何名称,它不过是用来标识消息定义的而已。消息元素不能将其本身声明为输入或输出(我想在operation元素中在具体加以区分吧),因此消息命名成request或response并不能确定如何使用这些消息。
?????? 在RPC样式的消息中,消息通常分为多个部分。比如,可以用多个part元素定义一个名为GetBookPriceRequest的消息,其中每个元素表示不同的参数,如下 1-8例:
<message name = “GetBookPriceRequest”>

<part name = “isnb” type = “xsd:string”>

<part name = “quantity” type = “xsd:int” >
</messgae>

<message name = “GetBookPriceResponse”>

<part name = “price” type = “xsd:float”>
</messgae>
Web服务中的输入和输出均可以有多个部分,这一点与Java方法调用语义不同,后者允许多个参数输入,但只有一个输出(看成返回值)。然而,对于像C++,C#和Perl等这样的编程语言来说,更常见的情况是它们声明的参数即可以是输入参数,也可以是输出参数。

Wsdl是一个中性编程语言,所以它必须有足够的灵活性,从而与所有编程语言相兼容,而不是为了某个语言。SAAJ和JAX-RPC均具有用多个部分支持输出消息的功能。
【文档样式Web服务的message元素】------------------------------
?????? 当用户采用文档样式消息传递模式时,message元素定义要引用types定义中的顶级元素。如下例1-9:描述一个SubmitPurchasePrder Web Services的WSDL文档,PO命名空间是以前SOAP文档中的。此例是单向消息传递模式,所以没有应答,这在文档样式中是最常见的了。

<definitions name = “SubmitPurchasePrder”
targetNamespace = http://www.Monson-Haefel.com/jwsbook/PO
xmlns:mh=http://www.Monson-Haefel.com/jwsbook/PO
xmlns:soapbind=http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=http://www.w3.org/2001/XMLScheam
xmlns=”http://schemas.xmlsopa.org/wsdl”>

<types>


<xsd:schema
targetNamespace = “http://www.Monson-Haefel.com/jwsbook/PO”>
<!―导入这个SubmitPurchasePrder XML 规则文档-->
<xsd:import namespace = http://www.Monson-Haefel.com/jwsbook/PO
schemaLocation = http://www.Monson-Haefel.com/jwsbook/po.xsd />

?

</xsd:schema>


</types>
<message name = “SubmitPurchasePrderMessage”>

<part name = “isnb” element = “mh: purchasePrder”>
</messgae>
……………………………………………..
</definitions>
?????? 消息部分可以声明type属性或者element属性,但不能同时声明两者。具体声明哪一种属性取决于传递消息的种类。如果用户使用的是RPC样式的消息传递,那么part元素必须使用type属性:如果用户使用的是文档样式的消息传递,part元素则必须是element属性。RPC样式的消息传递用类型来定义过程调用,该调用中每个元素表示某一类型的参数。此外,文档样式的消息传递要交换XML文档段,并引用它们的顶级元素(即全局元素)。

【声明错误消息】-----------------------------------------------------------
?????? 用户可以用消息定义声明错误,其声明方式与用消息等译声明输入和输出消息的方式相同。比如下面程序2-1定义了一个错误消息,如果BookQuote请求消息包含了一个无效的ISBN,则会将该错误消息返回。它就包含一个部分,就是错误消息。

<definitions name = “BookQuote”
targetNamespace = http://www.Monson-Haefel.com/jwsbook/PO
xmlns:mh=http://www.Monson-Haefel.com/jwsbook/PO
xmlns:soapbind=http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=http://www.w3.org/2001/XMLScheam
xmlns=”http://schemas.xmlsopa.org/wsdl”>


<types>

<xsd:schema

<xsd:element name = “InvalidIsbnFaultDetail”>

<xsd:complexType>

<xsd:sequence>


<xsd:element name = “offending-value” type = “xsd:string” />


<xsd:element name = “conformance-rules” type = “xsd:string” />

</xsd:sequence>

</xsd:complexType>

<xsd:element>

</xsd:schema>

</types>
<message name = “SubmitPurchasePrderMessage”>

<part name = “isnb” element = “mh: purchasePrder”>
</messgae>

<message name = “InvalidArgumentFault”>

<part name = “error_message” element = “mh: InvalidArgumentFault” />
</messgae>

……………………………………………..
</definitions>

【portType元素】-----------------------------------极为重点-----------------------------------------------

portType元素定义了Web服务的抽象接口。从概念上讲,该接口有点像java接口,因为它定义了一个抽象类型和它的方法,但没有定义实现。在WSDL中,portType元素是由binding元素和services元素实现的,这两个元素用于说明Web服务实现使用的Internet协议,编码方案以及Internet地址。

portType元素的“方法”是它的operation元素。portType元素可以有一个或多个operation,其中每个operation元素定义了一个RPC样式或文档样式Web服务方法。每个operation元素最多是由一个input或output元素以及任意数量的fault元素组成。
?????? 在下面的2-2例子中名为“BookQuote”的portType元素(左列)声明了三个操作,即GetBookPrice,GetBulkBookPrice和GetBookIsbn。右为对应的Java接口。如下例:


WSDL portType定义

?
Java接口

?
<portType name = “BookQuote”>
<operation name = “GetBeokPrice”>

<input name = “isbn”
?Public interface BookQuote{

Public float getBookPrice

(String isbn);

?
Message = “mh:GetBookPriceRequest”/>

<output name = “price”
Message = “mh:GetBookPriceResponse” />
</operation>
<!----------------------------------------------->

<operation name = “GetBulkBoekPrice”>

<input name = “request”
Message = “mh: GetBulkBoekPrice”/>

<output name = “price”
Message = “mh: GetBulkBoekPrice” />
</operation>

<!----------------------------------------------->
<operation name = “GetBookIsbn”>

<input name = “title”
Message = “mh: GetBookIsbn Request”/>

<output name = “price”
Message = “mh: GetBookIsbn Response” />
</operation>
?

?

?

?


Public float getBulkBoekPrice

(String isbn,int quantity);

?

?


Public String getBookIsbn(String bookTitle);
?


WSDL,portType与java接口并不完全相同,但它们非常接近。其实,大多数给予java的Web服务代码生成器均在java接口和WSDL portType元素之间创建了映射。它们其实是根据WSDL的portType元素生成java接口,而且也可以根据简单的Java接口生成portType元素,operation元素和message元素。
WSDL文档可以有一个或多个portType元素,其中每个portType元素描述了不同Web服务的抽象接口,比如:一个WSDL Web服务可以定义一个名为BookQuote的PortType元素和一个名为SubmitpurchaseOrder的portType元素。
?
?
?TOP
?
?

xt19833 发短消息
加为好友
xt19833 当前离线

UID394352 帖子24 精华0 金币62? 代金券35? 阅读权限100 在线时间20 小时 注册时间2006-12-18 最后登录2008-4-2?
进士

?

UID394352 帖子24 精华0 金币62? 代金券35? 阅读权限100? 4楼? 发表于 2007-8-29 10:30 | 只看该作者
【operation元素】------------------------------------------------------------
?????? 由portType元素声明的每一个operation元素要用一个或多个消息定义来定义、它的输入、输出已经错误。在2-3例子中,BookQuote portType元素将GetBookPriceRequest声明为它的input元素、将GetBookPriceRsponse声明为它的output元素、并将InvalidArgumentFault声明为它的fault元素。

<portType name = “BookQuote”>


<operation name = “getBookPrice”>

<input name = “isbn” message = “mh:GetBookPriceRequest”/>

<output name = “price” message = “mh:GetBookPriceRsponse”/>

<fault name =“InvalidArgumentFault” message = “mh: InvalidArgumentFault”>

</operation>

</portType>


Input消息表示传递到Web服务的有效负载,output消息则表示传递到客户的有效负载。在RPC样式的消息传递中,input是请求,output是客户。而在文档样式的消息传递中,input是传递到Web服务的XML文档段,output是传递回客户的XML文档段。除input消息和output消息外,一个错做可以不包含fault错误消息或包含多个fault错误消息,其中每个错误消息用于描述不同类型的错误。
【1.0 操作的参数错误】-------------------------------------------------
?????? 在WSDL中,当使用RPC样式的消息传递时,要假设客户使用的是过程调用语义,比如:JAX-RPC使用带方法调用的Java RMI接口对基于SOAP的RPC样式的Web服务建立模型。很多情况下,必须按制定的顺序传输input和output消息的参数,其顺序与过程调用时所使用的参数顺序要完全相同。为了使input和output消息参数采用正确的顺序,operation元素可以声明一个parameterOrder属性。如2-4例一个名为“GetBulkBookPrice”的操作用parameterOrder属性来指定其输入和输出的参数是顺序。
<message name = “GetBulkBookPriceRequest”>

<part name = “isnb” type = “xsd:string”>

<part name = “quantity” type = “xsd:int” >
</messgae>

<message name = “GetBulkBookPriceResponse”>

<part name = “prices” type = “mh:pricet”>
</messgae>

<portType name = “GetBulkBookPrice”>

<operation name = “GetBulkBookPrice” parameterOrder = “isbn quantity”>

<input name = “isbn” message = “mh: GetBulkBookPriceRequest”/>

<output name = “price” message = “mh: GetBulkBookPriceRsponse”/>

?

</operation>

</portType>
使用ParameterOrder属性时,该属性必须包含所有输入部分,并且只包含不是返回类型的输出部分。因此,如果一个output只有一个部分(不如上面的2-4例子),那么会假设它只有一个返回值,故不应该列在ParameterOrder属性中。
如果ParameterOrder属性列出了output部分,那么会将它按OUT参数对待。当portType元素中的input和output元素用相同的名称声明了一个部分时,该部分是一个INOUT参数。而且在input和output元素中的类型必须相同。
对ParameterOrder属性含义的不同解释会引起一些互操作性问题。Basic Profile通过提供单一的ParameterOrder属性解决了问题。从发送方向接收传递的参数顺序必须符合input消息定义和output消息定义中的part声明的顺序。
ParameterOrder属性的目的是说明哪些部分是返回类型。
由ParameterOrder属性提供的列表中忽略的任何部分均假设为操作的返回类型。过程调用可以只有一个返回类型,因此只能从ParameterOrder属性中忽略一个输出部分。
【2.0操作重载】
?????? 这里我不多说这个问题,因为这个会引起极大的互操作问题。因此BP禁止操作重载。
由portType元素定义的每个操作必须有唯一的名称,但允许2个或多个portType元素用完全相同的名称声明操作元素,因为每个portType被认为是一个单独定义。
【WSDL消息传递交换模式】------------------------------------------

Web服务中使用四种基本的消息交换模式(简称MEP),即请求/响应、单向、通知、以及恳求/响应模式。
?????? 虽然WSDL支持通知和恳求/响应消息传递模式,但BP不支持它们。而且实际上用的很少。目前,大多数基于WSDL的Web服务使用请求/响应消息传递模式或单向消息传递模式,而且它们是能与J2EE Web Services 一起使用的MEP。

WSDL文档可以通过声明它的输入和输出元素来为一个具体的操作确定MEP。看下面的1-1图吧。说明了请求/响应消息传递模式或单向消息传递模式的区别。


【1.0请求/响应消息传递】-------------------------------------------------
?????? 在请求/响应消息传递中,客户通过向Web服务发送请求消息来启动通信,而且Web服务要用响应消息来应答。
?????? 如果用一个input元素和一个output元素(output元素位于input元素之后)声明operation,那么它会定义一个请求/响应操作。通过首先列出input元素,operation表示Web服务接收到最初由客户发送的消息:将output元素列在input元素之后,则表示Web服务对消息给于响应,下面2-5例子,表示一个只使用一个input和一个output元素的经典请求/响应模式。
<portType name = “GetBulkBookPrice”>

<operation name = “GetBulkBookPrice” >

<input name = “isbn” message = “mh: GetBulkBookPriceRequest”/>

<output name = “price” message = “mh: GetBulkBookPriceRsponse”/>

?

</operation>
</portType>
?????? 请求/响应操作除了使用一个input元素和一个output元素外,还可以包含多个fault元素。Fault元素要在错误事件中返回给客户。(个人建议弄清客户的含义)请求/响应操作可以没有错误或有多个错误,如下2-6例:
<portType name = “GetBulkBookPrice”>

<operation name = “GetBulkBookPrice” >

<input name = “isbn” message = “mh: GetBulkBookPriceRequest”/>

<output name = “price” message = “mh: GetBulkBookPriceRsponse”/>

<fault name =“InvalidArgumentFault” message = “mh: InvalidArgumentFault”>

<fault name =“SecurityFault” message = “mh: SecurityFault”>

?

</operation>
</portType>
【2.0单向消息传递】--------------------------------------------------------
?????? 在单向消息传递中,客户将消息传递给Web服务,但不期待应答。此MEP通常被认为是异步消息传递。
?????? 单项消息传递是当今仅次于请求/响应消息传递的流行MEP。
?????? 如果用一个input但没有使用output声明了一个操作,那么就定义了一个单向操作。如果只列出了input消息,那么operation表示客户要把消息发送到Web服务,但不期待应答。下面2-7例子说明了一个简单的单向操作SubmitPuraseOrder PortType。
<portType name = “SubmitPuraseOrder PortType”>

<operation name = “SubmitPuraseOrder” >

<input name = “isbn” message = “mh: SubmitPuraseOrderMessage”/>

</operation>
</portType>
?????? 单向操作与请求/响应操作不同。单向操作不可以指定错误,也不需要生成错误消息。单向消息传递模式是严格但方向的,不能把错误传递回客户。
【通知和恳求/响应消息传递】----------------------------------------

J2EE Web Services中不能使用通知和恳求/响应MEP。J2EE Web Services 之所以不支持他们,其原因是因为WSDL1.1规范不能很好的标识他们。而且它们带来的问题比它们所解决的问题还要多,但我们可以理解~~呵呵。
?????? 在通知消息传递中,Web服务将消息发送给客户,但并不期望应答消息。使用通知MEP的Web服务符合分布计算的推模式(Push model 不能理解的可以去百度里搜),假设客户向Web服务进行了注册,以便接收有关一个事件的消息(看成通知)。通过注册来接收通知的客户称为订阅者(Subscriber)。在通知消息传递中,portType包含一个output元素,但不包含input消息定义。
?????? 恳求/响应类似于通知,但客户要期待对Web服务的响应。与通知消息传递一样,恳求/响应Web服务的客户必须订阅服务以便接收消息。在该MEP里,portType元素首先要声明output消息,然后才是input消息。顺序相反。
?
?
?TOP
?
?

xt19833 发短消息
加为好友
xt19833 当前离线

UID394352 帖子24 精华0 金币62? 代金券35? 阅读权限100 在线时间20 小时 注册时间2006-12-18 最后登录2008-4-2?
进士

?

UID394352 帖子24 精华0 金币62? 代金券35? 阅读权限100? 5楼? 发表于 2007-8-29 10:32 | 只看该作者
----------------------------------------------

这里是WSDL文档的一个段落


----------------------------------------------
【WSDL实现:binding元素】

Binding元素将一个抽象portType映射到一组具体协议(如SOAP和HTTP)、消息传递模式(RPC或文档)以及编码样式(字面或SOAP编码)。

Binding元素及其子元素与协议专用的元素组合在一起使用。Binding元素确定出正在绑定的portType元素和operation元素、而协议专用的元素声明与portType关联的协议与编码样式。
?????? 每种类型的协议(如果SOAP、HTTP和MIME)有其自己的一组协议专用元素和其自己的命名空间。如下3-1例声明了将BookQuote portType绑定到使用SOAP专用协议元素的SOAP1.1协议。。。

<?xml version = “1.0” encoding= “UTF-8”>
<definitions name = “BookQuoteWS”
targetNamespace = http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:mh=http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:soapbind=http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=http://www.w3.org/2001/XMLScheam
xmlns=”http://schemas.xmlsopa.org/wsdl”>

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

<!―binding 告诉了我们哪些协议和内码样式被使用-->

<binding name = “BookPrice Binding” type = “mh:BookQuote”>

<soapbind:binding style = “rpc”
Transport = http://schemas.xmlsoap.org/soap/http/>
<operation name = “getBookPrice”>

<soapbind: operation styles = “rpc”
Soap:Action =
http://www.Monson-Haefel.com/jwsbook/BookQuote/GetBookPrice/>
<input>

<soapbind.body use = “literal”
Namespace = http://www.Monson-Haefel.com/jwsbook/BookQuote />

</input>

<output>

<soapbind:body use = “literal”
Namespace = http://www.Monson-Haefel.com/jwsbook/BookQuote />

</output>

</operation>

</binding>
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
</definitions>
?????? 我向大家要注意的第一个问题是此例中声明的binding元素实际上是由2个不同的命名空间组成的,没有命名空间前缀的元素是WSDL1.1命名空间http://schemas.xmlsoap.org/wsdl啊成员。此命名空间是WSDL文档的默认命名空间。WSDL1.1通用的绑定元素是binding、operation、input和output。另外,soapbind:binding,soapbind:operation和soapbind:body元素是协议专用的元素,它们是SOAP-WSDL绑定的命名空间http://schemas.xmlsoap.org/wsdl/soap的成员。在来看看3-2的实例:

<?xml version = “1.0” encoding= “UTF-8”>
<definitions name = “BookQuoteWS”
targetNamespace = http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:mh=http://www.Monson-Haefel.com/jwsbook/BookQuote
xmlns:soapbind=http://schemas.xmlsoap.org/wsdl/soap/
xmlns:xsd=http://www.w3.org/2001/XMLScheam
xmlns=”http://schemas.xmlsopa.org/wsdl”>

<!―binding 告诉了我们哪些协议和内码样式被使用-->

<binding name = “BookPrice Binding” type = “mh:BookQuote”>

<soapbind:binding style = “rpc”
Transport = http://schemas.xmlsoap.org/soap/http/>
<operation name = “getBookPrice”>

<soapbind: operation styles = “rpc”
Soap:Action =
http://www.Monson-Haefel.com/jwsbook/BookQuote/GetBookPrice/>
<input>

<soapbind.body use = “literal”
Namespace = http://www.Monson-Haefel.com/jwsbook/BookQuote />

</input>

<output>

<soapbind:body use = “literal”
Namespace = http://www.Monson-Haefel.com/jwsbook/BookQuote />

</output>

</operation>

</binding>
</definitions>

Soapbind:binding元素和soapbind:body元素用于表示Web服务的SOAP专用细节,比如:soapbind:binding说明了消息样式是RPC,并且网络应用协议是HTTP。Soapbind:body元素说明了输入和输出均使用了字面编码。后面会详细接触到SOAP绑定元素。

Binding元素的子元素(operation、input、output元素)可以直接映射到portType元素的子元素。如下3-3:
<portType name = “BookQuote”>

<operation name = “getBookPrice”>

<input name = “isbn” message = “mh:GetBookPriceRequest” />

<output name = “price” message = “mh:GetBookPriceRsponse” />

</operation>
</portType>

<binding name = “BookPrice Binding” type = “mh:BookQuote”>
<soapbind:binding style = “rpc”
Transport = http://schemas.xmlsoap.org/soap/http
/>
<operation name = “getBookPrice”>

<soapbind: operation styles = “rpc”
Soap:Action =
http://www.Monson-Haefel.com/jwsbook/BookQuote/GetBookPrice/>
<input>

<soapbind.body use = “literal”
Namespace = http://www.Monson-Haefel.com/jwsbook/BookQuote />

</input>

<output>

<soapbind:body use = “literal”
Namespace = http://www.Monson-Haefel.com/jwsbook/BookQuote />

</output>

</operation>
</binding>
====================================================================
portType元素的name属性对应着binding元素的 type属性。
portType元素中的operation元素的 name属性对应着binding元素中的operation元素中的name属性
portType元素中的operation元素的input和output元素分别与binding元素中的operation元素中的input和output属性对应。
====================================================================
?????? 虽然到目前为止给出的绑定示例均使用SOAP绑定元素,但WSDL规范上实际还是为HTTP和MIME定义了其他两个协议专用绑定。如下3-4:
<!―HTTP/MIME-binding of BookQuote-->
<binding name = “BookPrice_HttpMimeBinding” type = “mh:BookQuote”>

<Http:binding verb = “GET”>

<operation name = “getBookPrice”>

<http:operation location = “alt.http.service” />

<input>

<http:urlEncoded/>

</input>

<output>

<mime:content type = “text/html”>

</output>

</operation>
</binding>
?????? 虽然WSDL1.1允许使用MIME绑定和HTTP绑定(如上例),但Basic Profile不允许使用这两种绑定,因为他们的文档结构很差。
?????? 此限制只适合BP1.0 WS-I已声明它将下一个版本的Basic Profile中扩展对SwA的支持。其中包括WSDL MIME绑定。?

  相关解决方案