使用WSDL发布WebService(第二部分)简单对象访问协议——学习SO
作者:Bilal Siddiqui?(wap_monster@yahoo.com) 译者:梅青松 注:由于时间和本人水平问题差错在所难免,还往各位海涵。 ?????简单对象访问协议(SOAP)提供了访问远程对象的方法。这样的对象有JavaBean,EJB组件,COM和COM+对象等等。这些对象使用不同的公司,可能在互联网上随处可见。因此SOAP是一种在互联网上交换企业信息的机制。在本文中,笔者将讨论SOAP通信的细节,对象如何使用SOAP显示其功能,如何调用SOAP对象以及如何在SOAP感知软件中交换信息。他将演示如何将第一部分中的WSDL程序发布为SOAP服务,及其远程调用。 一.SOAP 和 WSDL ????我在这个系列的第一部分介绍了WSDL。WSDL描述Web Service的接口。Web Service的拥有者将使用SOAP实现这些的接口。因此WSDL服务就以SOAP服务的形式存在。一旦Web Service的用户拥有了WSDL文件,他就知道了接口的详细资料,就可以使用SOAP同Web Service通信。 ????可以将你通过WSDL接口发布的Web Service看作对象,它可以通过SOAP从互联网上远程访问。既然服务都是对象,必然就会有一些属性跟每个服务及其行为相关。SOAP消息是可能工作在HTTP上的XML文件。 二.使用SOAP的原因 ????B2B(business-to-business)和A2A(application-to-application)需要通信的企业双方的指示以交换其信息。工作流的概念用于B2B,并贯穿于企业集成。例如,某个企业调用供应商的服务以满足客户的需求,这就形成了一条垂直的供应链。有的供应商也会拓展供应联调用其他企业的服务。 ????显然这类应用软件的交互性极其重要。任一企业都只是实现SOAP通信的一端,而另一端由互联网上的其他人实现。 ????在未来的几年里,企业集成和交互能力将成为软件工程师和企业极具挑战性的任务。平台依赖性也将是集成和交互能力达成的一大难题。SOAP是至今为止最简单的实现企业集成和交互能力的机制。 三.SOAP架构 ????在初步了解了SOAP及其作用后,下面我将讨论它的架构以了解其内部的情况。在图Figure 1中,你可以看见下面的组件运用于典型的SOAP通信机制中: 1.??SOAP Client 2.??SOAP Service 3.??Actual Service ? ? Figure 1. Components of a typical SOAP communication architecture
下面讨论上面提及的各个实体在架构中的角色。 SOAP ClientSOAP Client是一个SOAP感知机器,它可以产生SOAP请求并通过HTTP将SOAP请求发送给SOAP Server。SOAP Client是一种SOAP消息。一般来说有两种SOAP消息:SOAP Client发送给SOAP Service的SOAP请求消息和SOAP Service发送给SOAP Client的SOAP响应消息。Listing 1是一个典型SOAP请求消息,而Listing 2则是一个典型SOAP响应消息。 <SOAP-ENV:Envelope??xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
???<SOAP-ENV:Body>
?????????<m:getListOfModels xmlns:m = "uri reference" >
?????????</m:getListOfModels>
????</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SOAP Server
????SOAP Server也是一个SOAP感知机器,它可以接受SOAP Client发来的请求并创建合适的响应。加密的响应会发给发出请求的SOAP Client。在SOAP Server内部有三个实体: 1.??Service manager 2.??Deployed service list 3.??XML translator Service manager管理响应请求的服务。在Listing 1中的SOAP请求中,节点<m:getListOfModels xmlns:m=”urn:MobilePhoneService”>包含了服务的名称。Service manager会读出Service Client向要调用的服务的名称并向包含SOAP Service中所有服务列表的Deployed service list查询是否有该项服务。如果有Service manager就将SOAP请求发给XML translator。XML translator将SOAP请求的XML结构转换成程序员用来实现Actual Service的程序语言。XML translator还将Actual Service返回的响应转回XML结构的SOAP响应。Listing 2就是一个SOAP响应的例子。 <SOAP-ENV:Envelope??xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
???<SOAP-ENV:Body>
??<m:getListOfModelsResponse xmlns:m="urn:MobilePhoneservice">
????<Model>M1</Model>
????<Model>M2</Model>
????<Model>M3</Model>
??</m:getListOfModelsResponse>
????</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Actual Service 在Figure 1中标为Actual Service的方框显示了Actual Srrvice的位置。服务的实现可能是一个COM组件或是一个JavaBean组件。XML translator会把XML结构转换成合适的方法调用。当XML translator调用Actual Srrvice的方法时,这些方法会执行其功能并返回结果给XML translator。 Figure 1中连接XML translator和Actual Service的箭头的两端都在一个企业里,这意味着同一个组织控制着通信两端的接口。与此相反的是SOAP Client和SOAP Service穿越了企业的边界。这就是SOAP的用途。 SOAP请求响应机制 ????SOAP Client传输SOAP消息给SOAP Service时使用HTTP协议传输。这称为SOAP绑定HTTP.当SOAP Service收到消息时,他将消息传给Service Maneger. SOAP Service检查Deployed service list中是否有SOAP消息请求的服务。如果没有该项服务,他将请求失败的响应发回给SOAP Client。但如果有该项服务,就由XML translator进行适合的语言转换,访问actual service的实现。服务的实现会处理请求并返回结果给XML translator. XML translator再将结果转换为SOAP Client理解的SOAP响应。同样,HTTP绑定也用在SOAP响应的传输上。 SOAP绑定HTTP ????当你将HTTP同SOAP帮定绑定或是在HTTP上操作SOAP时,你实际上在SOAP请求和响应上添加了HTTP头。Listing 1是典型的SOAP请求,而Listing 3,4,5,6演示了在Listing 1上添加了HTTP头的SOAP请求。与此类似的是Listing 7演示了在Listing 2上添加了HTTP头的SOAP响应。 ????当你在HTTP上使用SOAP时,Content-Type字段必须为text/html.在Listing 7中可以看到Listing 3的细节。 一个使用HTTP的SOAP请求 ??你可以将SOAP联合在HTTP的请求方法POST上。要发送一个SOAP HTTP请求,你必须在HTTP头上提供一个SOAPAction字段。 SOAPAction定义了SOAP请求的目的。服务器(例如过滤HTTP上SOAP请求消息的防火墙)可以使用SOAPAction的值做决定。 HTTP客户端在发出SOAP请求时必须使用HTTP头的这个字段。SOAPAction可以取的值如下所示: SOAPAction:”URI-Reference” SOAPAction:”filename” SOAPAction:”” SOAPAction POST /Vendors HTTP/1.1
Host: www.mobilephoneservice.com
Content-Type:"text/xml";Charset="utf-8"
Content-Length: nnnn
SOAPACtion:"www.mobilephoneservice.com/Vendors/MobilePhoneservice#getListOfModels"
?
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"??>
??<SOAP-ENV:Body>
????<m:getListOfModels xmlns:m="urn:MobilePhoneservice" >
????</m:getListOfModels>
??</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
图Listing 3在SOAPAction中包含了下面的URI引用
这个SOAPAction说明了两件事:一是SOAP发布的详细地址 ? POST /Vendors HTTP/1.1
Host: www.mobilephoneservice.com
Content-Type:"text/xml";Charset="utf-8"
Content-Length: nnnn
SOAPAction:"MobilePhoneservice#getListOfModels"
?
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"??>
??<SOAP-ENV:Body>
????<m:getListOfModels xmlns:m="urn:MobilePhoneservice" >
????</m:getListOfModels>
??</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
图Listing 4在SOAPAction中包含了一个文件名( POST /Vendors HTTP/1.1
Host: www.mobilephoneservice.com
Content-Type:"text/xml";Charset="utf-8"
Content-Length: nnnn
SOAPAction:""
?
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"??>
??<SOAP-ENV:Body>
????<m:getListOfModels xmlns:m="urn:MobilePhoneservice" >
????</m:getListOfModels>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
图Listing 5的SOAPAction中包含了一个控字符串(””)。空字符串说明SOAP的目标跟主机URI相同 POST /Vendors HTTP/1.1
Host: www.mobilephoneservice.com
Content-Type:"text/xml";Charset="utf-8"
Content-Length: nnnn
SOAPAction:
?
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"??>
??<SOAP-ENV:Body>
????<m:getListOfModels xmlns:m ="urn:MobilePhoneservice" >
????</m:getListOfModels>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
图Listing 6的SOAPAction没有值。这表明没有消息的目标的信息。 使用HTTP的SOAP响应 SOAP响应有两种类型: ●????????成功的SOAP操作产生的SOAP结果。 ●????????不成功的SOAP操作产生的SOAP错误消息。 HTTP/1.1 Content-Type:"text/xml"; Charset="utf-8"
Content-Length: nnnn
?
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
<SOAP-ENV:Body>
??<m:getListOfModelsResponse xmlns:m = "URI-Reference">
????<model>m1</model>
????<model>m2</model>
??</m:getListOfModels>
</SOAP-ENV:Body>
图Listing 7就是一个从SOAP服务返回的有意义的结果。 图Listing 8则是一个典型的SOAP错误消息。SOAP HTTP响应在HTTP中添加了通信状态信息的HTTP状态码的语义。当处理请求失败时,SOAP HTTP服务器必须发出一个包含带有SOAP错误元素的SOAP消息的HTTP 500内部服务错误的响应。 HTTP/1.1 500 Internal Server Error
Content-Type: "text/xml"; Charset="utf-8"
Content-Length: nnnn
?
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
??<SOAP-ENV:Body>
????<SOAP-ENV:Fault>
????<faultstring>Failed to process the request</faultstring>
????</SOAP-ENV:Fault>
??</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SOAP和e-mail HTTP并非是绑定SOAP消息的唯一解决方案。你可以在HTTP步使用的地方使用其他的机制如SMTP进行SOAP绑定。绑定SOAP到SMTP,你可以创建一个单向的通道。两个单向的消息可以建立请求/响应通讯。为了使用SMTP发送SOAP消息,你必须按照下面的步骤做: ●????????使用SMTP头的 MIME-Version字段 MIME-Version字段使用版本号区别不同版本的MIME(多用途网际邮件扩充协议).他允许邮件服务代理(如pop?服务)区别新老版本MIME产生的邮件消息。图Listing 9就是用了SMTP头的?MIME-Version字段。 TO: <info@waxsys.com>
From: <abc@punjab.com>
Reply-To: <abc@punjab.com>
Date: SAT,2 Feb 2002 16:00:00
Message-Id: <4FAB345C8D93E93B7A6E9@punjab.com>
MIME-Version: 1.0
Content-Type: text/xml; charset=utf-8
Content-Transfer-Encoding: QUOTED-PRINTABLE
?
<?xml version ="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
??<SOAP-ENV:Body>
????<prnt:echoString xmlns:prnt="http://waxsys.com">
??????<msgString>Put your mail Message</msgString>
????</prnt:echoString>
??</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
●????????使用SMTP头的 Content-Type字段 Content-Type字段用来标明消息体重的数据类型。”text/xml”就是一个可以去的值。图Listing 9就使用了Content-Type字段。 ●????????使用SMTP头的 Content-Transfer-Encoding字段 Content-Transfer-Encoding字段用来说明传输编码的类型,就是说你想传输什么样的数据,是字符格式还是二进制格式的。图Listing 9使用了
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
?
</SOAP-ENV:Envelope>
Header SOAP头是可选的。你可以跳过SOAP头直接在SOAP?
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
??<m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1">
??</m:Order>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
Body Body节点将会包含你想发送的消息。这是一个必需的节点,而它的字节点通常属于一个用户自定义的名称空间中。Listing 12显示了一个含有用户自定义名称空间“u”的SOAP消息。Body节点用来包含必需的信息。Body节点是SOAP消息必需的,而且它必须是SOAP Envelop节点的直接子节点。他必须直接跟在SOAP Header后面。如果没有Header节点,则直接跟在Envelop节点后面。Body可以包含字节点,字节点可以有其名称空间。 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
??<m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1">
??</m:Order>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
??<u:GetPrice xmlns:u="some URI" >
????<model>m1</model>
??</u:GetPrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Fault 这个节点指示错误消息。它必须在Body中出现而最多出现一次。通常,Fault节点出现在SOAP响应中表明SOAP请求出错了。 Fault的子节点: ●????????faultcode(fault标识) ●????????faultstring(fault描述) ●????????faultactor(引发错误的原因) ●????????detail(错误的细节。通常是相应遇SOAP请求的Body中名称空间的应用程序的错误细节。) Listing 13是一个典型的fault消息。 Listing 13 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1">
</m:Order>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring>Not necessary information</faultstring>
<detail>
??<d:faultdetail xmlns:d = "uri-referrence">
????<msg>
??????application is not responding properly.
????</msg>
????<errorcode>12</errorcode>
??</d:faultdetail>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
WSDL文件的SOAP请求 在大致介绍了SOAP消息的语法之后,我将演示如何为本系列文章中第一部分的MobilePhoneservice开发一个SOAP请求。在第一部分中你为MobilePhoneservice设计了一个完整的WDL接口。移动电话公司在MobilePhoneservice提供了两个方法:一个是getListOfModels,另一个是getPrice(modelNumber)。GetListOfModels没有参数,返回移动电话型号列表而getPrice(modelNumber)有一个参数modelNumber,返回请求型号的价格。你需要把他们做成SOAP请求的格式,在这之前我要展示一下SOAP请求和响应的一般格式。 <SOAP-ENV:Envelope xmlns:SOAP-ENV ="SOAP schema's URI"
<SOAP-ENV:Body>
??<Instance:"Method Name" xmlns:Instance= "URI where method is located">
????<parameter1>value</parameter1>
????<parametern>value</parametern>
??</Instance:"Method Name">
</SOAP_Envelop:Body>
</SOAP-ENV:Envelope>
一个SOAP请求或响应只能定义服务的一个方法。SOAP请求的一般形式如Listing 14所示。而Listing 16则是一个调用getListOfModels方法的实际请求。在Listing 16中,我提供了方法的名称和URI。由于getListOfModels没有参数,因此<m: getListOfModels>是一个空节点。 Listing 15 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
??<Instance:"Method Name"+"Response"
??xmlns:Instance="URI where method is located">
??<return>
????<responseparameter1>value</responseparameter1>
????<responseparametern>value</responseparametern>
??</return>
??</Instance: "Method Name"+"Response">
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Listing 15是一个一般的SOAP响应。Apach SOAP服务器在方法名后添加了Response关键字并将返回值封装在<return>节点中作为方法节点的直接子节点。如果返回值是一个复杂类型,那么<return>节点将包含一个或多个<item>节点。与Listing 15相比Listing 17则是方法getListOfModels的实际响应。Listing 17中返回值是Vector类型的,因此<return>节点包含了一个<item>节点的列表。与此类似的是Listing 18和Listing 19,这两个图展示了MobilePhoneservice的getPrice()方法的SOAP请求和响应。
在SOAP服务器上发布基于WSDL的服务 在这部分我们将把第一部分中的WSDL服务发布到一台Apache SOAP服务器上。Apache SOAP工具包把WSDL服务信息保存在一个发布描述文件中。发布描述文件包含了WSDL服务的名称及其方法。发布描述文件在运行时将这些信息提供给SOAP?服务器。发布描述文件还包含了实现接口的JavaBean组件的地址。 Listing 20 <isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment"
??id="URN:SERVICE-URN">
<isd:provider type="java"
??scope="Request"
??methods="EXPOSED-METHODS">
??<isd:java class="IMPLEMENTING-CLASS"/>
</isd:provider>
<isd:faultListener>org.apache.soap.server.DOMFaultListener
</isd:faultListener>
</isd:service>
Listing 20是发布描述文件的骨架,基于WSDL服务的发布描述需要三个信息(URN:SERVICE-URN,EXPOSED-METHO和IMPLEMENT-CLASS)。URN:SERVICE-URN是发布的服务的名称。EXPOSED-METHO服务的方法列表。在本次发布中就是getListOfModels和getPrice。IMPLEMENT-CLASS就是带有完整名称的java类。如samples.phonequote.MobilePhoneservice。本例的试验中你有下面的路径结构: Apache SOAP server: C:/foo/SOAP-2-2 Mobile pone service?实现 C:/foo/SOAP-2-2/samples/phonequotes/MobilePhoneservice 因此在安装SOAP工具包时实现类路径跟目录有关。我并没有提供实际的java实现类。这需要依据商务逻辑或者其他的什么东西。 <isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment"
id="urn:MobilePhoneservice">
<isd:provider type="java"
??scope="Request"
??methods="getListOfModels getPrice">
??<isd:java class="samples.phonequote.MobilePhoneservice"/>
</isd:provider>
<isd:faultListener>
??org.apache.soap.server.DOMFaultListener
</isd:faultListener>
</isd:service>
Listing 21就是第一部分中WSDL文件的完整描述。 SOAP客户端同SOAP服务器的通讯 我准备了一个例子演示SOAP客户端同SOAP服务器的通讯。因此我给出了三个清单:Startup.html(Listing 22),Operation.html(Listing 23)和Excute.jsp(Listing 24)。 Startup.html是一个简单的html文件。它是一个用户界面,由用户决定调用哪个SOAP方法。 Listing 22 <HTML>
<BODY bgcolor="Teal">
<br/>
<p align="center">
??<font size="5" face="Arial" color="white"><b>
??SOAP method invocation demo </b></font>
</p>
<hr/>
<font face="Arial" color="whitesmoke" size="3">
<br/><b>
??Click any of the method name to execute.<br/>
??1. Get the List of all Models that we manufacture....
????<a href="execute.jsp?index=1">
????<font color="orange"> GetListOfModels </font></a> <br/>
??2. Get the Price of any particular model......................
????<a href="operation.html">
????<font color="orange"> GetPrice </font></a>
</b>
</BODY>
</HTML>
Operation.html(Listing 23)让用户输入调用方法的参数。 Listing 23 <HTML>
<BODY bgcolor="Teal">
<br/>
<p align="center">
<font size="5" face="Arial" color="white"><b>
??GetPrice Operation input Form </b>
</font></p>
<hr/>
<p align="center">
<form action="execute.jsp" method="POST">
<input type="hidden" name="index" value="0">
<table textColor="white">
<tr><td>
<font color="whitesmoke"><b>Description :</b></font>
</td><td><font color="whitesmoke">
??Method GetPrice is used to Get Price of given Model Number</font>
</td></tr>
<tr><td>
<font color="whitesmoke"><b>Parameter(s)</b></font></td><td>
</td></tr>
<tr><td><font color="whitesmoke">Model Number </td></font>
<td><font color="whitesmoke">
??<input type="text" name="parameter" size="30">
??(required) </font>
</td></tr>
<tr><td>
??</td><td><input type="Submit" value="Invoke">
</td></tr>
</font>
</table>
</form>
</p>
</BODY>
</HTML>
Excute.jsp(Listing 24)才是重点。它侦查调用的方法及其参数,然后向远程服务器发送方法调用请求。 Listing 24 <%@ page language="java" import="java.util.Vector" %>
<%@ page import="java.net.MalformedURLException,java.net.URL" %>
<%@ page import="java.util.Vector" %>
<%@ page import="org.apache.soap.SOAPException,
????org.apache.soap.Constants" %>
<%@ page import="org.apache.soap.rpc.Call,org.apache.soap.rpc.Response,
????org.apache.soap.rpc.Parameter" %>
<%@ page import="org.apache.soap.transport.http.SOAPHTTPConnection" %>
<%@ page import="org.apache.soap.Fault" %>
?
<HTML>
<BODY bgcolor="Teal">
<br/>
<p align="center">
<font color="whitesmoke">
<%
??boolean isParameter = false ;
??SOAPHTTPConnection soapTransport = new SOAPHTTPConnection();
?
??// Address of the remote server.
??// Normally this should be dynamically passed and detected.
??// We have hard coded it only for demonstration.
??URL url = new URL ("http://localhost:8080/soap/servlet/rpcrouter");
?
??// Build the call.
??Call call = new Call ();
??call.setTargetObjectURI ("urn:MobilePhoneservice");
??call.setSOAPTransport (soapTransport);
??call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
?
??// We'll detect which method user selected
??// and give a call accordingly.
??// We'll pass parameters if present.
?
??if (request.getParameter("parameter")!=null)
??isParameter = true;
?
??if (request.getParameter("index").equals("0"))
??{
????call.setMethodName("getPrice");
????Vector params = new Vector();
????String message = new String (request.getParameter("parameter"));
????params.addElement (new Parameter("message",String.class,
????message,null));
????call.setParams(params);
??}
??else
????call.setMethodName("getListOfModels");
?
??Response resp = call.invoke ( url,/* actionURI */ "" );
??out.println("<p align=left>
??<font size=/"4/" face=/"Arial/" color=/"white/">
??Response of [ "+call.getMethodName()+" ]
??</font><hr/>");
?
??// Check the response.
??if (resp.generatedFault ()) {
????Fault fault = resp.getFault ();
????out.println("<b>Fault is:</b>"+ fault.getFaultCode ()
????+" ["+fault.getFaultString ()+"]");
?
??} else {
????Parameter result = resp.getReturnValue ();
????out.println("<b>Response is: </b>"+ result.getValue ()+"");
??}
%>
<font>
</p>
</BODY>
</HTML>
运行这个程序你需要两个Apache SOAP?服务器。一个用于用户跟主机的交互。另一个(又称远程服务器)用来发布第一部分中基于WSDL的服务。在Execute.jsp中硬编码的远程服务器地址(http://localhost:8080/soap/servlet/rpcouter)仅用于演示。实际上你将从WSDL文件中读出远程服务器地址。 SOAP中的简单数据类型和组合数据类型 下面介绍简单数据类型和组合数据类型的区别。我将展示在SOAP中如何封装它们。 简单数据类型包括string,float,integer,enumeration等等。如移动电话的名称就是string类型的。组合数据类型则是简单数据类型的组合体。如学生类型就可能有多个属性:string类型的姓名,int型的学号。 Listing 25就含有复杂数据类型Mobile。稍候你可以在你的SOAP请求中使用这种类型。 1<? xml version="1.0" ?>
2<xsd:schema xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
3???xmlns:xsd="http://www.w3.org/1999/XMLSchema">
4???targetNameSpace= "www.mobilephoneservice.com/phonequote">
5 <xsd:element name ="Mobile">
6 <xsd:complexType>
7???<xsd:element name="modelNumber" type="xsd:int">
8???<xsd:element name="modelName" type="xsd:string">
9???<xsd:element name="modelWeight" type="xsd:int">
10??<xsd:element name="modelSize" type="xsd:int">
11??<xsd:element name="modelColor">
12????<simpleType base="xsd:string">
13????<enumeration value="white" />
14????<enumeration value="blue" />
15????<enumeration value="black" />
16????<enumeration value="red" />
17????<enumeration value="pink" />
18????</simpleType>
19??</xsd:element>
20 </complexType>
21 </xsd:element>
22</xsd:schema>
Listing 25的第五行是类型的名称而第六行说明这是个复杂数据类型。复杂数据类型都有属性,七到十二行就是数据类型Mobile的属性。第七行说明Mobile类型有一个名称为modelNumber类型为int的属性。类似的是九、十行是相同类型不同名称的属性。第八行则是名称为modelName类型为string的属性。 十一行复杂一点,因为它包含了一个simpleType的子节点。我们在Mobile类型里面定义了一个简单类型。这个简单类型的名称是modelCOlor是enumaration(枚举)类型的。他有一个值为xsd:string的base属性,这说明了简单类型modelColor基类型是sting。枚举类型说明我们可以在其中选择一个作为属性的值。 在SOAP请求中使用组合类型 Listing 26演示了组合类型在SOAP请求中的使用。在Envelope的体中调用了m名称空间的addModel方法。Listing 26使用了Listing 25中定义的Mobile数据类型。 addModel方法有一个Mobile类型的参数。在Mobile之前我们用到了msd名称空间。Listiing 26的节点<SOAP-ENV:Envelope>声明了该名称空间。这是一个在SOAP请求中使用用户自定义类型数据的例子。 1 <SoAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
2 xmlns:xsd="http://www.w3.org/1999/XMLSchema"
3 xmlns:msd="www.mobilephoneservice.com/phonequote">
4 <SOAP-ENV:Body>
5???<m:addModel xmlns:m="www.mobilephoneservice.com">
6???<msd:Mobile>
7?????<modelNumber>1</modelNumber>
8?????<modelName>mlr97</modelName>
9?????<modelWeight>10</modelWeight>
10????<modelSize>4</modelSize>
11????<modelColor>white</modelColor>
12??</msd:Mobile>
13??</m:addModel>
14 </SOAP-ENV:Body>
15<SOAP-ENV:Envelope>
总结 现在我们学习了SOAP语法,请求,响应,HTTP绑定以及在SOAP中使用e-mail。你也看到了SOAP服务器是如何响应SOAP客户端的。最后,我简要的讲了一下用户自定义类型数据。自定义类型数据是一个需要子系学习的高级话题,在本系列的下一边文章中我们会更详细的讨论这个话题。而且我也检查了SOAP的交互能力(也就是SOAP如何在不同的卖主中执行的)。 原文链接:http://www-128.ibm.com/developerworks/webservices/library/ws-intwsdl2/index.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |