`
chenlk823
  • 浏览: 37338 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

my wsdl2

 
阅读更多


使用 WSDL 的原因
网络通讯协议之类的标准,到底是某当权机构强制施行的;或是,人们真的认为,确实遵守的优点远胜于必须付出的代价?历来所提出的标准,许多都无疾而终。有时候,从未被大众所使用的标准,法律或政府规定还是硬要使用:好比说,Ada 程序语言。

我 相信,遵守标准所能获得的优点,才是使标准普及的原因。例如,铁路服务的重点是,即使不同公司所建造的列车轨道,也可以接驳在一起;也就是说,不同公司的 产品必须能整合使用。因此,几家厂商便共同推出了 SOAP 这个标准。WSDL (Web Services Description Language,网络服务描述语言) 可轻易将网络服务提供厂商与服务的使用者结合起来,轻松获取 SOAP 的优点。不同公司所建造的列车轨道比较容易整合;毕竟,必须同意的标准不过是两条铁轨之间的距离而已。但对网络服务而言,情况则复杂得多了。首先必须取得 的共识是,指定接口的标准格式。

有个论点一直认为,SOAP 并不需要接口描述语言。若 SOAP 纯粹是沟通内容的标准,那么它需要的便是描述该内容的语言。SOAP 讯息确实可传递类型信息,也因此 SOAP 允许以动态的方式决定类型。但除非知道函数的名称、参数、与类型,否则根本无法正确呼叫任何函数。若不使用 WSDL,还是可以从所提供的文件或检查线路讯息,来确定呼叫的语法。但这两种方式都需要人力介入,也因此可能在过程中出现错误。若使用 WSDL,即可以真正不受语言与平台限制的方式,自动为网络服务产生 Proxy。类似 CORBA 或 COM 的 IDL 档案,WSDL 档案也是一种客户端与伺服端之间的合约。

请注意,虽然 WSDL 的设计目的是,对 SOAP 以外的通讯协议显示系结;但本文的主旨则是在 HTTP 上与 SOAP 有关连的 WSDL。而且虽然目前 SOAP 的主要用途是远程程序或函数呼叫,但 WSDL 已经可以在 SOAP 下,指定传输的文件。WSDL 1.1 已经以 Note (通知书) 的方式 (请参阅 http://www.w3.org/TR/wsdl.html),提交至 W3C 。

WSDL 文件结构
若欲了解任何 XML 文件,区块图是很有帮助的。下图说明 WSDL 的结构;它是一种 XML 文件,可显示 WSDL 文件五个组成区段之间的关系。

WSDL 文件可分成两个区段群组。上群组是由抽象定义 (Abstract Definitions) 所组成;而下群组则是由具体定义 (Concrete Descriptions) 所组成。抽象区段定义 SOAP 讯息的方式是,排除平台与语言的限制;因此它们不含任何计算机或语言特有的元素。如此一来,不同的网站皆可实作它所定义的服务。诸如序列化等网站特有的资 讯,则交由含具体描述的下区段处理。

抽象定义
Types (类型)
不受计算机与语言限制的类型定义。
Messages (讯息)
内含函数参数 (输入与输出分离) 或文件描述。
PortTypes (埠类型)
根据 Messages 区段中的讯息定义,说明函数签章 (作业名称、输入参数、输出参数)。
具体定义
Bindings (系结)
在 PortTypes 区段中,指定每个作业的系结。
Services (服务)
指定每个系结的传输端口地址。
在 下图中,箭头连接代表,在文件的不同区段之间有关联性存在。点与箭头连接代表「参照」或「使用」关系。双箭头连接代表「修改 (modifier)」关系。3-D 箭头连接代表「包含 (contains)」关系。因此,Messages 区段使用 Types 区段的定义;PortTypes 区段使用 Messages 区段的定义;Bindings 区段参照 PortTypes 区段;Services 区段参照 Bindings 区段。PortTypes 与 Bindings 区段内含作业元素,而 Services 区段则内含端口元素。Bindings 区段中的作业元素,会修改或进一步说明 PortTypes 区段中的作业元素。

以此为基础,本文将使用标准 XML 技术,说明 WSDL 文件。「元素」一词是指 XML 元素,而「属性」一词则是指元素属性。因此:

<element attribute="attribute-value">contents</element>

内容可以递归的方式,由一个以上的元素组成。根元素是最顶端的元素,文件中其它所有元素皆归在其下。子元素永远附属于其它的父元素。

请 注意,只可以有一个 Types 区段,甚或根本没有此区段。其它所有区段可以有零、一、或多个父元素。例如,Messages 区段可以有零、或多个 <message> 元素。WSDL 结构描述规定,所有区段必须依指定顺序排列:汇入、类型、讯息、portType、系结、与服务。每个抽象区段可能各自位于不同的档案,并分别汇入至主文 件中。



[图 1] 抽象与具体定义

WSDL 范例档案
现在请一同深入探讨 WSDL 范例档案,以检视其结构与运作方式。请记得这是一个非常简单的 WSDL 文件范例。其目的仅在解说最明显的功能。下列各区段皆有更详实的讨论。

<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="FooSample"
targetNamespace="http://tempuri.org/wsdl/"
xmlns:wsdlns="http://tempuri.org/wsdl/"
xmlns:typens="http://tempuri.org/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension"
xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>
<schema targetNamespace="http://tempuri.org/xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
elementFormDefault="qualified" >
</schema>
</types>

<message name="Simple.foo">
<part name="arg" type="xsd:int"/>
</message>

<message name="Simple.fooResponse">
<part name="result" type="xsd:int"/>
</message>

<portType name="SimplePortType">
<operation name="foo" parameterOrder="arg" >
<input message="wsdlns:Simple.foo"/>
<output message="wsdlns:Simple.fooResponse"/>
</operation>
</portType>

<binding name="SimpleBinding" type="wsdlns:SimplePortType">
<stk:binding preferredEncoding="UTF-8" />
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="foo">
<soap:operation
soapAction="http://tempuri.org/action/Simple.foo"/>
<input>
<soap:body use="encoded" namespace="http://tempuri.org/message/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded" namespace="http://tempuri.org/message/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>

<service name="FOOSAMPLEService">
<port name="SimplePort" binding="wsdlns:SimpleBinding">
<soap:address location="http://carlos:8080/FooSample/FooSample.asp"/>
</port>
</service>
</definitions>

下列为此范例文件的大略说明。稍后,会就每个区段详细讨论。

第 一行宣告,本文件为 XML。虽然非是必要,但它可协助 XML 剖析器决定,应该剖析此 WSDL 档案,或发出错误讯号。第二行是 WSDL 文件中的根元素:<definitions>。有几个命名空间属性 (命名空间宣告),附属于此根元素以及 <types> 元素的 <schema> 子元素中。

<types> 元素是由 Types 区段组成。若无数据类型须要宣告,则此区段可以省略。在范例 WSDL 中,并无应用程序专属的类型须要宣告,但还是使用 Types 区段,以宣告本文件中结构描述的命名空间。

<message> 元素是由 Messages 区段所组成。若将作业视为函数,则 <message> 元素可将参数定义至该函数。<message> 元素中的每个 <part> 子元素,都对应一个参数。请将参数定义输入至单一的 <message> 元素之中,并与位于自己 <message> 元素中的输出参数分开。同时是输入与输出的参数,在输入与输出 <message> 元素中,各有与自己相对应的 <part> 元素。根据惯例,输出 <message> 元素的名称,如同「fooResponse」,会以「Response」结束。如同函数参数需有名称与类型一样,每个 <part> 元素也都有名称与类型属性。

若用于文件交换,WSDL 可使用 <message> 元素,说明交换的文件。

<part> 元素的类型可以是,XSD 基础类型、SOAP 定义类型 (soapenc)、WSDL 定义类型 (wsdl)、或 Types 区段的定义类型。

在 PortTypes 区段中,可以有零、一、或更多个 <portType> 元素。由于抽象的 PortType 定义,可置于不同的档案中;因此在 WSDL 档案中,可以有零个 <portType> 元素。在上面的范例中,即只有一个 <portType> 元素。诚如所见,<portType> 元素可在 <operation> 元素中,定义一或多个作业。此范例仅显示一个名为「foo」的 <operation> 元素。此名称应与函数名称相同。<operation> 元素可有一、二、或三个子元素:即 <input>、<output> 与 <fault> 元素。每个 <input> 与 <output> 元素中的讯息属性,都会参照 Messages 区段中的相关 <message> 元素。因此,范例中的整个 <portType> 元素,相当于下列的 C 函数宣告:

int foo(int arg);

此范例正足以说明,相较于 C,XML 是多么冗长的语言。 (包括 <message> 元素在内,此范例共使用 12 行的 XML 进行函数宣告;而相同的动作, C 只要一行即可。)

Bindings 区段可有零、一或多个 <binding> 元素。而其目的则是,指定每个 <operation> 呼叫与响应,在在线传送的方式。Services 区段也可有零、一或多个 <service> 元素。它所含的 <port> 元素,每个都参照 Bindings 区段中的一个 <binding> 元素。Bindings 与 Services 区段都是由,WSDL 文件的具体描述所组成。

命名空间
在根元素 <definitions> 与子元素 <schema> 中,都有命名空间属性:

<definitions name="FooSample"
targetNamespace="http://tempuri.org/wsdl/"
xmlns:wsdlns="http://tempuri.org/wsdl/"
xmlns:typens="http://tempuri.org/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension"
xmlns="http:// schemas.xmlsoap.org/wsdl/">

<types>
<schema targetNamespace="http://tempuri.org/xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
elementFormDefault="qualified" >
</schema>
</types>

每 个命名空间属性,都会为命名空间宣告一个速记法,以便在文件中使用。例如,「xmlns:xsd」可定义一个速记法 (xsd),代表命名空间 http://www.w3.org/2001/XMLSchema。如此一来,稍后即可在文件中参照此命名空间;其方式很简单,只要在名称前嵌入前缀 「xsd」,则「xsd:int」即成为合格的类型名称。一般的领域设定规则,皆可套用至此速记前缀。也就是说,在一个元素中所定义的前缀,仅在该元素中 使用。

使用命名空间的原因何在?命名空间的目的在避免命名冲突。若我建立了一个网络服务,其 WSDL 档案中含有一个名为「foo」的元素,而您想要将我的网络服务,与另一个互补性的服务结合起来使用;假若没有使用命名空间,则另一个网络服务,在其 WSDL 档案中,便绝对不能使用「foo」这个名称。除非在两者的执行个体中,都是指完全相同的东西,否则这两个服务不可以使用相同的名称。但若使用两个不同的命 名空间,则我网络服务的「foo」所代表的意义,便与另一个网络服务的「foo」不同。在客户端,您便必须以嵌入前缀 (prefixing 或 qualifying) 的方式,参照我的「foo」。例如,若我宣告 http://www.infotects.com/fooService 的速记法是 carlos,则 http://www.infotects.com/fooService#foo 这个完全合格的名称,可以等于「carlos:foo」。请注意,若使用 URI 作为命名空间,不但可确保其独特性,更可允许在文件中使用寻址器。URI 所指向的地址,不必对应真正的网络地址。也可以使用 GUID 代替或补充 URI。例如,GUID「335DB901-D44A-11D4-A96E-0080AD76435D」即是个有效的命名空间指示项。

元 素中所宣告的所有名称,都附属于 targetNamespace 属性所宣告的命名空间之下。在 WSDL 范例档案中,代表 <definitions> 的 targetNamespace 是 http://tempuri.org/wsdl。它所代表的意义是,在此 WSDL 文件中宣告的所有名称,都附属于此命名空间。由于 <schema> 元素有它自己的 targetNamespace 属性,且其值为 http://tempuri.org/xsd;所以在此 <schema> 元素中定义的所有名称,都是属于此命名空间,而不属于主目标命名空间。

下一行程序代码位于 <schema> 元素中,它所宣告的是预设的命名空间。结构中所有无嵌入前缀 (unqualified ) 的名称,都属于此命名空间。

xmlns="http://www.w3.org/2001/XMLSchema"

SOAP 讯息
对 使用 WSDL 档案的客户端与伺服端而言,它所代表的意义之一是,可决定在线传送的内容。虽然 SOAP 使用的是,诸如 IP 与 HTTP 等低层次的通讯协议,但此应用程序却可决定,特定客户端与特定伺服端之间所使用的高层次通讯协议。换句话说,若以「echoInt」作业为例,使用回波传 回输入整数,则参数总计、每个参数的类型、与参数传过线路的方式 (序列化) 等,便会构成一个应用程序特有的通讯协议。指定这类通讯协议的方式很多,但我认为使用 WSDL 才是最佳的方式。若就此观点而言,WSDL 便不只是一种「接口合约」,它更是一种通讯协议指定语言。若超出了诸如 IP 与 HTTP 等固定通讯协议的范围,进入应用程序专属通讯协议的领域,WSDL 正好符合我们所需。

WSDL 可以指定,SOAP 讯息是否符合 rpc 或文件样式。正如范例中所使用的一样,rpc 样式讯息的外观就像是,一个有零或多个参数的函数呼叫。文件样式讯息则较扁平 (flatter) 且不需要那么多的巢状阶层。下列 XML 讯息的传送与接收,是使用 MS SOAP Toolkit 2.0 (MSTK2) 的 SoapClient 对象,剖析 WSDL 范例档案的结果。

自客户端执行函数呼叫「foo(5131953)」:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<m:foo xmlns:m="http://tempuri.org/message/">
<arg>5131953</arg>
</m:foo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

伺服端所接收到的 (回应):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAPSDK1:fooResponse xmlns:SOAPSDK1="http://tempuri.org/message/">
<result>5131953</result>
</SOAPSDK1:fooResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

此 函数呼叫讯息与其响应,都是正确有效的 XML。SOAP 讯息是由 <Envelope> 元素所组成,其中含有一个选择性的 <Header> 元素,与至少一个的 <body> 元素。传送与接收讯息两者,在主 <Envelope> 元素中,都有只一个 <Body> 元素。rpc 函数呼叫讯息的主体,有一个依作业名称「foo」命名的元素,而响应主体中则有一个名为「fooResponse」元素。这个 foo 元素有个如范例 WSDL 所示的单一自变量,其名称为 <arg>。同样地,fooResponse 也有一个 <result>。在此处重复出现的 WSDL Bindings 区段中,请注意 encodingStyle、信封、与讯息命名空间的指定方式。

<binding name="SimpleBinding" type="wsdlns:SimplePortType">
<stk:binding preferredEncoding="UTF-8" />
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="foo">
<soap:operation
soapAction="http://tempuri.org/action/Simple.foo"/>
<input>
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>WSDL 类型与讯息区段中的 XML 结构描述
WSDL 的数据类型,是根据目前 W3C Recommendation 的「XML Schema: Datatypes」(XSD)。此文件共有三种不同的版本 (1999、2000/10、与 2001),若欲指定特定 WSDL 档案所使用的版本,请在 <definitions> 元素中,将其宣告为命名空间的属性。方法如下:

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

本文仅以 2001 版为考虑。WSDL 标准的拥护者,也大力建议使用 2001 版。

在本节与后续章节中,采用的前缀或命名空间速记法如下:

前缀 对应的命名空间 说明
soapenc http://schemas.xmlsoap.org/soap/encoding SOAP 1.1 编码
wsdl http://schemas.xmlsoap.org/wsdl/soap WSDL 1.1
xsd http://www.w3.org/2001/XMLSchema XML Schema

XSD 基本类型
下表直接取自 MSTK2 文件,列举了 MSTK2 支持的所有 XSD 基本类型。该表说明,位于客户端与伺服端的 WSDL 读者,如何在 VB、C++、与 IDL 中,将 XSD 类型对应至不同与对等的类型。

XSD (Soap) 类型 不同的类型 VB C++ IDL 批注
anyURI VT_BSTR String BSTR BSTR
base64Binary VT_ARRAY | VT_UI1 Byte() SAFEARRAY SAFEARRAY(unsigned char)
boolean VT_BOOL Boolean VARIANT_BOOL VARIANT_BOOL
byte VT_I2 Integer short short 转换时验证范围。
date VT_DATE Date DATE DATE 时间设为 oo:oo:oo
dateTime VT_DATE Date DATE DATE
double VT_R8 Double double double
duration VT_BSTR String BSTR BSTR 不执行验证或转换
ENTITIES VT_BSTR String BSTR BSTR 不执行验证或转换
ENTITY VT_BSTR String BSTR BSTR 不执行验证或转换
float VT_R4 Single float float
gDay VT_BSTR String BSTR BSTR 不执行验证或转换
gMonth VT_BSTR String BSTR BSTR 不执行验证或转换
gMonthDay VT_BSTR String BSTR BSTR 不执行验证或转换
gYear VT_BSTR String BSTR BSTR 不执行验证或转换
gYearMonth VT_BSTR String BSTR BSTR 不执行验证或转换
ID VT_BSTR String BSTR BSTR 不执行验证或转换
IDREF VT_BSTR String BSTR BSTR 不执行验证或转换
IDREFS VT_BSTR String BSTR BSTR 不执行验证或转换
int VT_I4 long long long
integer VT_DECIMAL Variant DECIMAL DECIMAL 转换时验证范围。
language VT_BSTR String BSTR BSTR 不执行验证或转换
long VT_DECIMAL Variant DECIMAL DECIMAL 转换时验证范围。
Name VT_BSTR String BSTR BSTR 不执行验证或转换
NCName VT_BSTR String BSTR BSTR 不执行验证或转换
negativeInteger VT_DECIMAL Variant DECIMAL DECIMAL 转换时验证范围。
NMTOKEN VT_BSTR String BSTR BSTR 不执行验证或转换
NMTOKENS VT_BSTR String BSTR BSTR 不执行验证或转换
nonNegativeInteger VT_DECIMAL Variant DECIMAL DECIMAL 转换时验证范围。
nonPositiveInteger VT_DECIMAL Variant DECIMAL DECIMAL 转换时验证范围。
normalizedString VT_BSTR String BSTR BSTR
NOTATION VT_BSTR String BSTR BSTR 不执行验证或转换
number VT_DECIMAL Variant DECIMAL DECIMAL
positiveInteger VT_DECIMAL Variant DECIMAL DECIMAL 转换时验证范围。
QName VT_BSTR String BSTR BSTR 不执行验证或转换
short VT_I2 Integer short short
string VT_BSTR String BSTR BSTR
time VT_DATE Date DATE DATE Day 设定成 1899 年 12 月 30 日
token VT_BSTR String BSTR BSTR 不执行验证或转换
unsignedByte VT_UI1 Byte unsigned char unsigned char
unsignedInt VT_DECIMAL Variant DECIMAL DECIMAL 转换时验证范围。
unsignedLong VT_DECIMAL Variant DECIMAL DECIMAL 转换时验证范围。
unsignedShort VT_UI4 long long long 转换时验证范围。

XSD 定义两组内建的数据类型:基本类型与衍生类型。若需进一步信息,可前往 http://www.w3.org/TR/2001/PR-xmlschema-2-20010330,检视内建类型的阶层架构。

复杂类型
XML Schema 可定义复杂类型,也就是 C 中的 struct。例如,下列 C struct 的相对定义方式为:

typedef struct {
string firstName;
string lastName;
long ageInYears;
float weightInLbs;
float heightInInches;
} PERSON;

若使用 XML Schema 可以撰写成:

<xsd:complexType name="PERSON">
<xsd:sequence>
<xsd:element name="firstName" type="xsd:string"/>
<xsd:element name="lastName" type="xsd:string"/>
<xsd:element name="ageInYears" type="xsd:int"/>
<xsd:element name="weightInLbs" type="xsd:float"/>
<xsd:element name="heightInInches" type="xsd:float"/>
</xsd:sequence>
</xsd:complexType>

不过,<complexType> 所能表示的,绝不仅止于 struct 的对应而已。除了 <sequence> 之外,它还可以有其它的子元素。若不用 <sequence>,也可以使用 <all>:

<xsd:complexType name="PERSON">
<xsd:all>
<xsd:element name="firstName" type="xsd:string"/>
<xsd:element name="lastName" type="xsd:string"/>
<xsd:element name="ageInYears" type="xsd:int"/>
<xsd:element name="weightInLbs" type="xsd:float"/>
<xsd:element name="heightInInches" type="xsd:float"/>
</xsd:all>
</xsd:complexType>

其意义则是,成员变量 <element> 可以任何顺序输入,且每一项都具有选择性。这点便与 C struct 的使用方式不同了。

请注意范例中,string (字符串)、int (整数)、float (浮点数) 等内建数据类型的使用方式。C 的字符串在 XML 中也是字符串,且浮点数还是浮点数。但 C 的 long (长整数),在 XML 则是 int (请参考上表)。

在 WSDL 档案中,Types 区段是宣告上述复杂类型的位置。例如,PERSON 类型可以下列方式宣告,并将其用于 Messages 区段中:

<?xml version="1.0" encoding="UTF-8" ?>
<definitions ?>
<types>
<schema targetNamespace="someNamespace"
xmlns:typens="someNamespace" >
<xsd:complexType name="PERSON">
<xsd:sequence>
<xsd:element name="firstName" type="xsd:string"/>
<xsd:element name="lastName" type="xsd:string"/>
<xsd:element name="ageInYears" type="xsd:int"/>
<xsd:element name="weightInLbs" type="xsd:float"/>
<xsd:element name="heightInInches" type="xsd:float"/>
</xsd:sequence>
</xsd:complexType>
</schema>
</types>

<message name="addPerson">
<part name="person" type="typens:PERSON"/>
</message>

<message name="addPersonResponse">
<part name="result" type="xsd:int"/>
</message>

</definitions>

在上述的范例中,第一个讯息的名称是「addPerson」,它有个类型为「PERSON」的 <part>。在 Types 区段中,类型 PERSON 会被宣告为复杂类型。

起 始 MSTK2 SoapClient 时,若在上述片段使用完整的 WSDL 档案,它便可成功地剖析该档案。不过,它还是不能将函数呼叫,传送至 <addPerson>。这是因为 SoapClient 本身不知道如何处理复杂类型;它需要自订的类型对应器 (mapper) 才能处理复杂类型。在 MSTK2 文件中有一个范例应用程序,它含有自订的类型对应器。

另外还有一个方法,可将 <part> 元素,关连至类型宣告。这个方法使用的是元素,而非类型属性。下个范例会在 Types 区段中,先宣告两个元素 (「Person」与「Gender」);然后在「addPerson」的 <message> 中,再使用元素属性参照它们。

<?xml version="1.0" encoding="UTF-8" ?>
<definitions ?>
<types>
<schema targetNamespace="someNamespace"
xmlns:typens="someNamespace" >
<element name="Person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="firstName" type="xsd:string"/>
<xsd:element name="lastName" type="xsd:string"/>
<xsd:element name="ageInYears" type="xsd:int"/>
<xsd:element name="weightInLbs" type="xsd:float"/>
<xsd:element name="heightInInches" type="xsd:float"/>
</xsd:sequence>
</xsd:complexType>
</element>
<element name="Gender">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Male" />
<xsd:enumeration value="Female" />
</xsd:restriction>
</xsd:simpleType>
</element>
</schema>
</types>

<message name="addPerson">
<part name="who" element="typens:Person"/>
<part name="sex" element="typens:Gender"/>
</message>

<message name="addPersonResponse">
<part name="result" type="xsd:int"/>
</message>
</definitions>

在 Types 区段的 Gender <element> 中,内嵌着一个匿名的列举类型,其值可以是「Male」或「Female」。然后在「addPerson」的 <message> 中,再使用元素属性 (不用类型属性) 参照该元素。

若欲关连特定类型至 <part>,使用「元素」与「类型」属性有何不同?若使用「类型」属性,part 可描述成能采取数种类型 (就像变量一样);但若使用「元素」属性,便不能这么做。请参考下列范例的说明。

<?xml version="1.0" encoding="UTF-8" ?>
<definitions ?>
<types>
<schema targetNamespace="someNamespace"
xmlns:typens="someNamespace">
<xsd:complexType name="PERSON">
<xsd:sequence>
<xsd:element name="firstName" type="xsd:string"/>
<xsd:element name="lastName" type="xsd:string"/>
<xsd:element name="ageInYears" type="xsd:int"/>
<xsd:element name="weightInLbs" type="xsd:float"/>
<xsd:element name="heightInInches" type="xsd:float"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="femalePerson">
<xsd:complexContent>
<xsd:extension base="typens:PERSON" >
<xsd:element name="favoriteLipstick" type="xsd:string" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="malePerson">
<xsd:complexContent>
<xsd:extension base="typens:PERSON" >
<xsd:element name="favoriteShavingLotion" type="xsd:string" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="maleOrFemalePerson">
<xsd:choice>
<xsd:element name="fArg" type="typens:femalePerson" >
<xsd:element name="mArg" type="typens:malePerson" />
</xsd:choice>
</xsd:complexType>
</schema>
</types>

<message name="addPerson">
<part name="person" type="typens:maleOrFemalePerson"/>
</message>

<message name="addPersonResponse">
<part name="result" type="xsd:int"/>
</message>

</definitions>

此 范例也说明了扩展名的衍生用法。「femalePerson」与「malePerson」两者,都是衍生自「PERSON」。它们都各有一个额外的元素: 「femalePerson」的「favoriteLipstick」以及「malePerson」的「favoriteShavingLotion」。 使用 <choice> 的 construct,这两个衍生类型又可结合成一个复杂类型「maleOrFemalePerson」。最后,在「addPerson」的 <message> 中,此结合类型又可供「person」的 <part> 参照。而此 <part> 或参数,可以是「femalePerson」或「malePerson」。

数组
XSD 可提供 <list> construct,以宣告空白所分隔的项目数组。但是,SOAP 并不使用 XSD 清单为数组编码;而是为数组定义自己的类型,即「SOAP-ENC:Array」。下列范例说明,如何为单一维度的整数数组,依其法则导出此种类型:

<xsd:complexType name="ArrayOfInt">
<xsd:complexContent>
<xsd:restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:int[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>

只要使用导出限制的方式,即可从 soapenc:Array 宣告新的复杂类型。接着便可宣告此复杂类型的属性:arrayType。参照「soapenc:arrayType」实际上即是 arrayType 属性的宣告,其方式如下:

<xsd:attribute name="arrayType" type="xsd:string"/>

然后,wsdl:arrayType 属性值,可决定每个数组成员的类型。数组项目也可以是复杂类型:

<xsd:complexType name="ArrayOfPERSON">
<xsd:complexContent>
<xsd:restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType"
wsdl:arrayType="typens:PERSON[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>

WSDL 的要求是,数组的类型名称必须是,「ArrayOf」与数组项目类型的的串连 (concatenation)。也因此,单从名称即可得知,「ArrayOfPERSON」是 PERSON struct 的数组。在下例中,只要使用 ArrayOfPERSON 宣告一个 <message>,即可新增多个 PERSON:

<?xml version="1.0" encoding="UTF-8" ?>
<definitions ?>
<types>
<schema targetNamespace="someNamespace"
xmlns:typens="someNamespace" >
<xsd:complexType name="PERSON">
<xsd:sequence>
<xsd:element name="firstName" type="xsd:string"/>
<xsd:element name="lastName" type="xsd:string"/>
<xsd:element name="ageInYears" type="xsd:int"/>
<xsd:element name="weightInLbs" type="xsd:float"/>
<xsd:element name="heightInInches" type="xsd:float"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfPERSON">
<xsd:complexContent>
<xsd:restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType"
wsdl:arrayType="typens:PERSON[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</schema>
</types>

<message name="addPersons">
<part name="person" type="typens:ArrayOfPERSON"/>
</message>

<message name="addPersonResponse">
<part name="result" type="xsd:int"/>
</message>

</definitions>

<portType> 与 <operation> 元素
PortType 可在抽象中,定义多种作业。PortType 中的作业元素,可定义呼叫所有 PortType 方法的语法。每个作业元素都会宣告,方法的名称、参数 (使用 <message> 元素)、类型 (每个 <message> 中所宣告的 <part> 元素)。

在 WSDL 文件中,可有多个 <portType> 元素。每个 <portType> 元素,群组化多个相关作业的方式,与 COM 接口群组化方法的方式非常类似。

在一个 <operation> 元素中,最多可有一个 <input> 元素、一个 <output> 元素、与一个 <fault> 元素。这三个元素都各有一个名称与讯息属性。

在 <input>、<output>、与 <fault> 元素中使用名称属性的目的为何?原来是为了,区别具相同名称 (多载) 的两项作业。例如,下列两个 C 函数,即具有相同的名称,但不同的参数。

void foo(int arg);
void foo(string arg);

使用 WSDL 时,这种多载的表达方式如下:

<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="fooDescription"
targetNamespace="http://tempuri.org/wsdl/"
xmlns:wsdlns="http://tempuri.org/wsdl/"
xmlns:typens="http://tempuri.org/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-
extension"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="http://tempuri.org/xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
elementFormDefault="qualified" >
</schema>
</types>

<message name="foo1">
<part name="arg" type="xsd:int"/>
</message>

<message name="foo2">
<part name="arg" type="xsd:string"/>
</message>

<portType name="fooSamplePortType">
<operation name="foo" parameterOrder="arg " >
<input name="foo1" message="wsdlns:foo1"/>
</operation>
<operation name="foo" parameterOrder="arg " >
<input name="foo2" message="wsdlns:foo2"/>
</operation>
</portType>

<binding name="fooSampleBinding" type="wsdlns:fooSamplePortType">
<stk:binding preferredEncoding="UTF-8" />
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="foo">
<soap:operation soapAction="http://tempuri.org/action/foo1"/>
<input name="foo1">
<soap:body use="encoded" namespace="http://tempuri.org/message/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
</operation>
<operation name="foo">
<soap:operation soapAction="http://tempuri.org/action/foo2"/>
<input name="foo2">
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
/>
</input>
</operation>
</binding>

<service name="FOOService">
<port name="fooSamplePort" binding="fooSampleBinding">
<soap:address
location="http://carlos:8080/fooService/foo.asp"/>
</port>
</service>
</definitions>

在本文写作时,并无任何 SOAP 实作,能进行作业名称的多载动作。这对使用 Java 的客户端是很重要的,因为使用 Java 的伺服端所使用的接口,会利用 Java 的多载功能。但这对使用 COM 的客户端倒无所谓,因为 COM 并不支持多载。

<binding> 与 <operation> 元素
Binding 区段是,指定通讯协议、序列化、与编码的地方。若 Types、Messages、与 PortType 等区段负责抽象的数据内容,那么 Binding 区段便负责处理数据传输的具体细节。Binding 区段负责使前三个区段的抽象具体化。

将系结规格从数据与讯息宣告中分离出来的意义是,执行相同业务的服务提供者,可将一组作业 (portType) 标准化。若欲凸显自身的差异,每个提供者可另外提供自订系结。让 WSDL 拥有汇入 construct 是有好处的;因为如此一来,即可远离 Bindings 与 Services 区段,将抽象定义置于自身的档案中;并可将其散布于服务提供者间,让他们把抽象定义设定成标准。例如,银行可标准化,一组抽象 WSDL 文件详尽说明的银行作业。但每家银行还是可以自由地,「自订」基础通讯协议、序列最佳化、与编码。

下列为 Binding 区段的 WSDL 多载范例,于此重复以方便详细讨论:

<binding name="fooSampleBinding" type="wsdlns:fooSamplePortType">
<stk:binding preferredEncoding="UTF-8" />
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="foo">
<soap:operation soapAction="http://tempuri.org/action/foo1"/>
<input name="foo1">
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/" />
</input>
</operation>
<operation name="foo">
<soap:operation soapAction="http://tempuri.org/action/foo2"/>
<input name="foo2">
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/" />
</input>
</operation>
</binding>

<binding> 元素会有个名称 (本例中为「fooSampleBinding」),以方便 Services 区段的 <port> 元素参照。它有个参照 <portType> 的「type」属性,在本例中为「wsdlns:fooSamplePortType」。第二行是 MSTK2 扩充元素 <stk:binding>,它可指定 preferredEncoding,或称「UTF-8」。

<soap:binding> 元素可指定,使用的样式 (rpc) 与传输。传输属性会参照命名空间,以确定所使用的 HTTP SOAP 通讯协议。

有两个 <operation> 元素具有相同的名称「foo」。这两个作业不同之处在于,两个不同的 <input> 名称:「foo1」与「foo2」。在两个 <operation> 元素中,<soap:operation> 元素的「soapAction」属性皆相同,都是一个 URI。soapAction 属性是 SOAP 专属的 URI,并逐字依 SOAP 讯息使用。以此方式取得的 SOAP 讯息,会有个 SOAPAction 标头;而且还会以 <soap:operation> 元素中的 URI 为其值。虽然 HTTP 系结需要 soapAction 属性,但非 HTTP 系结则不用。本文刊出时,其用途仍然不明。就本范例而言,它似乎可用来区别两个不同的「foo」作业。SOAP 1.1 宣称,soapAction 可用来识别讯息的「目的 (intent)」。它更建议伺服端,可用此属性路由讯息,而不用剖析整个讯息。实务上,其用途差异很大。<soap:operation> 元素也可以含另一个名为「style」的属性;若特定作业需要覆写 <soap:binding> 元素中所指定的样式,则可使用此属性。

<operation> 元素所含的 <input>、<output>、与 <fault> 元素,可对应 PortTypes 区段的相同元素。在上例中出现的只有 <input> 元素。在本例中,这三个元素都各有一个选择性的「name」属性,可用以区别名称相同的作业。在范例的 <input> 元素中,有个 <soap:body> 元素,它可指定输入结果 SOAP 讯息之 <body> 的内容。此元素有下列属性:

Use
它是用以指定数据采「编码 (encoded)」或「常值 (literal)」。「常值」的意义是,结果 SOAP 讯息所含数据的格式,完全依照抽象定义 (Types、Messages、与 PortTypes 区段) 的指定规格 。「编码」的意义是,「encodingStyle」属性 (参考下文) 会指定编码方式。
Namespace
每个 SOAP 讯息的主体,都有自己的命名空间,以防止名称冲突。此属性所指定的 URI,会逐字使用于结果 SOAP 讯息之中。
EncodingStyle
以 SOAP 的编码方式而言,URI 的值应该是「http://schemas.xmlsoap.org/soap/encoding」。
文件样式系结
在上一区段中,<soap:binding> 元素有个类型属性被设定成「rpc」。若将此属性设定成「document」,即可改变讯息在在线的排序。此时这些讯息便成了文件传输,而不再是函数签 章。在此系结类型中,<message> 元素是定义文件格式,而非函数签章。请参考下例中的 WSDL 片段:

<definitions
xmlns:stns="(SchemaTNS)"
xmlns:wtns="(WsdlTNS)"
targetNamespace="(WsdlTNS)">

<schema targetNamespace="(SchemaTNS)"
elementFormDefault="qualified">
<element name="SimpleElement" type="xsd:int"/>
<element name="CompositElement" type="stns:CompositeType"/>
<complexType name="CompositeType">
<all>
<element name='a' type="xsd:int"/>
<element name='b' type="xsd:string"/>
</all>
</complexType>
</schema>

<message...>
<part name='p1' type="stns:CompositeType"/>
<part name='p2' type="xsd:int"/>
<part name='p3' element="stns:SimpleElement"/>
<part name='p4' element="stns:CompositeElement"/>
</message>
?</definitions>

此结构描述有 SimpleElement 与 CompositeElement 两个元素,以及一个宣告类型 (CompositeType)。所宣告的唯一 <message> 元素有四个部分 (part):p1 是 CompositeType 类型;p2 是 int 类型;p3 是 SimpleElement;而 p4 是 CompositeElement。下表是四种系结的比较,依照「使用/类型」分别为:rpc/literal、document/literal、 rpc/encoded、与 document/encoded。本表可说明,每种系结方式反映在在线的实际情况。

rpc / literal
<operation name="method1" style="rpc" ...>
<input>
<soap:body parts="p1 p2 p3 p4"
use="literal"
namespace="(MessageNS)"/>
</input>
</operation>

在线情形:
<soapenv:body... xmlns:mns="(MessageNS)"
xmlns:stns="(SchemaTNS)">
<mns:method1>
<mns:p1>
<stns:a>123</stns:a>
<stns:b>hello</stns:b>
</mns:p1>
<mns:p2>123</mns:p2>
<mns:p3>

<stns:SimpleElement>

123

</stns:SimpleElement>
</mns:p3>
<mns:p4>
<stns:CompositeElement>
<stns:a>123</stns:a>
<stns:b>hello</stns:b>
</stns:CompositeElement>
</mns:p4>
</mns:method1>
</soapenv:body>
document / literal / type=
<operation name="method1"
style="document" ...>
<input>
<soap:body parts="p1" use="literal">
</input>
</operation>

在线情形:

<soapenv:body... xmlns:stns="(SchemaTNS)">
<stns:a>123</stns:a>
<stns:b>hello</stns:b>
</soapenv:body>

rpc / encoded
<operation name="method1" style="rpc" ...>
<input>
<soap:body parts="p1 p2" use="encoded"
encoding=
"http://schemas.xmlsoap.org/soap/encoding/"
namespace="(MessageNS)"/>
</input>
</operation>

在线情形:
<soapenv:body... xmlns:mns="(MessageNS)">
<mns:method1>
<p1 TARGET="_self" HREF="#1"/>
<p2>123</p2>
</mns:method1>
<mns:CompositeType id="#1">
<a>123</a>
<b>hello</b>
</mns:CompositeType>
</soapenv:body>
document / literal / element=
<operation name="method1"
style="document" ...>
<input>
<soap:body parts="p3 p4"

use="literal">
</input>
</operation>

在线情形:

<soapenv:body... xmlns:stns="(SchemaTNS)">
<stns:SimpleElement>

123

</stns:SimpleElement>
<stns:CompositeElement>
<stns:a>123</stns:a>
<stns:b>hello</stns:b>
</stns:CompositeElement>
</soapenv:body>

document / encoded
<operation name="method1"
style="document" ...>
<input>
<soap:body parts="p1 p2" use="encoded"
encoding=

"http://schemas.xmlsoap.org/soap/encoding/"
namespace="(MessageNS)"/>
</input>
</operation>

在线情形:
<soapenv:body... xmlns:mns="(MessageNS)">
<mns:CompositeType>
<a>123</a>
<b>hello</b>
</mns:CompositeType>
<soapenc:int>123</soapenc:int>
</soapenv:body>


<service> 与 <port> 元素
服务即是一组 <port> 元素。每个 <port> 元素,都以一对一的方式,关连一个位置与 <binding>。若有一个以上的 <port> 元素,与相同的 <binding> 关连,便可以使用其它 URL 作为替换。

在 WSDL 文件中,可以有一个以上的 <service> 元素。多个 <service> 元素,可以有许多用途。其中之一便是,根据 URL 的目的地,将传输埠群组化。因此,我只要使用另一个 <service>,就可以重新导向所有股票报价要求;而且我的客户端程序依然可以正常咦鳎@是因为在这类的服务群组化中,通讯协议完全不 会更动其它的服务。多个 <service> 服务的另一个用途是为了,根据基础通讯协议,对传输端口进行分类。例如,可将所有的 HTTP 传输埠,置于一个 <service>;所有的 SMTP 传输埠置于另一个 <service>。客户端便可根据它能处理的通讯协议,搜寻相对的 <service>。

<service name="FOOService">
<port name="fooSamplePort" binding="fooSampleBinding">
<soap:address
location="http://carlos:8080/fooService/foo.asp"/>
</port>
</service>

在一份 WSDL 文件中,<service> 的「name」属性,可区分出个别服务的不同。因为一个服务可能会有几个传输埠,所以传输端口也必须有「name」属性。

总结
本文已经说明了 WSDL 文件最显著的 SOAP 特色。但应该声明的是,WSDL 绝不仅只能在 HTTP 上说明 SOAP 而已。在说明 SOAP 上,WSDL 的表达能力绝对足以使用 HTTP-POST、HTTP-GET、SMTP、与其它通讯协议。只要使用 WSDL,不论是程序开发人员或一般使用者,都可轻松处理 SOAP。个人深信,WSDL 与 SOAP 的结合,将可引进全新的应用程序类别,以更彻底地利用各种网络服务。

在 WSDL 的命名空间,有各种 XML 元素。下表整理了这些元素、属性、与内容,以供参考:

元素 属性 内容 (子项)
<definitions> name
targetNamespace
xmlns (其它命名空间) <types>
<message>
<portType>
<binding>
<service>
<types> (无) <xsd:schema>
<message> name <part>
<portType> name <operation>
<binding> name
type <operation>
<service> name <port>
<part> name
type (空值)
<operation> name
parameterOrder <input>
<output>
<fault>
<input> name
message (空值)
<output> name
message (空值)
<fault> name

message (空值)
<port> name
binding <soap:address>

资源:
WSDL 1.1
SOAP 1.1
XML 结构描述入门
MS SOAP Toolkit 下载网站
IDL 至 WSDL 的转译工具
含 WSDL 至 VB 之 Proxy 产生器的免费网络资源
PocketSOAP:SOAP 之相关组件、工具、与原始程序代码





分享到:
评论

相关推荐

    wsdl解析关键包.rar

    InputStream wsdlStream = getClass().getResourceAsStream("/myWsdl.wsdl"); Definition definition = wsdlManager.getDefinition(wsdlStream); // 从定义中获取服务、接口、操作等信息 Service service = ...

    java WSDL接口webService实现方式

    "java WSDL接口webService实现方式" 在本文中,我们将详细介绍java WSDL接口webService实现方式的相关资料,为大家提供了一定的参考价值。 一、使用JDK生成WSDL的对象类 在使用JDK生成WSDL的对象类时,我们可以...

    wsdl2java源码-sbt-cxf:用于通过wsdl2java生成CXFJava类的SBT插件

    wsdl2java源码sbt-cxf SBT 插件,用于使用 . 安装 将插件添加到您的project/plugins.sbt addSbtPlugin( " io.dapas " % " sbt-cxf " % " 0.2.0 " ) 该插件是一个自动插件,会自动添加到所有项目中,并在Compile阶段...

    webservice

    &lt;soap:operation soapAction="http://www.example.org/mywsdl/NewOperation"/&gt; &lt;wsdl:input&gt; &lt;/wsdl:input&gt; &lt;wsdl:output&gt; &lt;/wsdl:output&gt; &lt;/wsdl:operation&gt; &lt;/wsdl:binding&gt; &lt;wsdl:service name=...

    PHP webservice教程,soap wsdl密码验证,webservice高级应用

    WSDL则是用来描述Web服务的接口,它定义了服务的位置、服务提供的操作以及如何调用这些操作。WSDL文件是XML格式的,它为客户端提供了一种方法来了解服务的输入、输出和操作方式。在PHP中,我们可以通过SoapServer类...

    gSoap webservices C++ 客户端

    - 使用gSoap的`wsdl2h`工具将WSDL文件转换为C头文件,这个头文件包含了服务的结构定义和函数原型。 - 接着,使用`soapcpp2`工具处理这个头文件,生成服务客户端和服务器的源代码。 - 编译生成的源代码,并链接到...

    html,js,xml,wsdl,soap基础知识讲解

    ##### 2. HTML标签 HTML标签是一系列由尖括号包围的关键词,例如`&lt;html&gt;`。这些标签通常成对出现,如`&lt;b&gt;`和`&lt;/b&gt;`,其中`&lt;b&gt;`是开始标签,而`&lt;/b&gt;`是结束标签。标签对中的文本将以粗体显示。HTML标签不区分大小写。...

    wsdl-dump:将WSDL及其所有依赖项转储到文件中,保留远程结构

    保留远程结构用法使用Maven生成项目: $ mvn clean install appassembler:assemble这将产生一个可以使用的wsdldump脚本: $ ./wsdldump "http://domain.tld/ws/my/service/api/path?wsdl"创建的文件的结构将是URL的...

    my axis

    2. **WSDL生成**:Axis可以自动生成WSDL文件,这使得服务消费者能够了解服务的输入、输出、操作等信息,从而构建调用服务的客户端。 3. **部署Web服务**:Axis支持多种部署方式,包括直接在Tomcat、Jetty等Servlet...

    my eclipse-8.6

    在压缩包"my eclipse-8.6"中,"MyEclipse-8.6"很可能是安装程序或解压后的文件夹,包含了MyEclipse的所有组件和必要的配置文件。用户通常需要按照指定步骤进行安装,然后就可以开始利用这个强大的开发环境进行工作。...

    my_gsoap.rar_gsoap_gsoap 服务

    1. **代码生成**:使用gSOAP工具(例如wsdl2h和soapcpp2)从WSDL(Web Services Description Language)文件生成C/C++源代码。WSDL文件定义了服务接口、操作、输入和输出消息。 2. **服务实现**:开发人员在生成的...

    Linux环境下通过soap方式获取网页数据

    2. **生成客户端代码**:使用gSOAP的`wsdl2h`和`soapcpp2`工具,根据服务提供的WSDL(Web Services Description Language)文件生成客户端所需的C++代码。 ```bash wsdl2h -o service.h ...

    CXF开发webservice服务端

    值得注意的是,如果使用CXF自带的`wsdl2java.bat`命令自动生成客户端代码时,该方法的返回类型将会被转换为`List&lt;MyObject&gt;`的形式。 #### 四、配置部署 完成接口定义和实现后,还需要进行必要的部署配置才能使Web ...

    my-webservice:my-webservice 是一个项目网络服务。 使用 javax.jws 包。 网址

    my-webservice项目可能有一个对应的WSDL文件,详细定义了服务的输入、输出、操作和绑定,使得客户端能够理解如何与服务进行交互。 6. **URL**: 提到的URL是my-webservice服务的入口点,客户端通过这个URL发起HTTP...

    gsoap编译工具以及说明

    例如,`soapcpp2 -I/usr/local/include -j mywsdl.wsdl`。 3. **编写业务逻辑**:在生成的代码中,实现服务端接口的业务逻辑,以及客户端调用服务的代码。 4. **编译和链接**:将生成的代码与项目源码一起编译,...

    使用Eclipse + MyEclipse开发Web Service的示例

    在IT行业中,Web服务是一种基于开放标准(如XML、SOAP、WSDL和UDDI)的应用程序接口(API),允许不同系统之间的数据交换。Eclipse和MyEclipse是两个广泛使用的Java集成开发环境(IDE),它们提供了强大的工具来支持...

    WebServices创建及使用

    2. 实现接口并发布服务。 3. 访问WSDL文件以获取服务描述。 4. 创建客户端并调用服务。 5. (可选)使用wsimport生成本地客户端类以简化调用。 这个过程演示了一个简单的Web Services工作流程,实际应用中可能涉及...

    WebService整合SpringBoot2.0(csdn)————程序.pdf

    wsdl11Definition.setTargetNamespace("http://myspringboot2.example.com"); wsdl11Definition.setSchema(schema); return wsdl11Definition; } @Bean public XsdSchema schema() { return new ...

    phpStudy实现WebService实例,亲自测试及写了例子

    client.php中,修改代码new SoapClient("http://webservice.my.com/hello.wsdl");中的域名或网址 client.php?fun=fun1 返回1个失败提示 client.php?fun=fun2 返回一个简单数组(json,下同) client....

    ASP.NET Core WebApi使用Swagger生成API说明文档

    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); }); ``` 然后,在Configure方法中,调用UseSwagger和UseSwaggerUI扩展方法,启动Swagger UI: ```csharp app.UseSwagger(); app....

Global site tag (gtag.js) - Google Analytics