如何结合Ajax与Web服务?

日期: 2010-12-20 作者:Brian M. Carey 来源:TechTarget中国 英文

  什么是Web服务?

  Web服务是使用万维网公开应用程序功能的方法。它通过使用开放协议来公开应用程序功能,因此任何使用服务的应用程序,只要能访问 Web,都可访问Web服务。

  典型的Web服务交互包括使用者(使用Web服务的远程应用程序)向服务发送XML消息。然后服务解析消息,回送响应,同样以XML格式。然后使用者以同样方式解析响应,将从服务接收到的信息投入使用。

  大多数情况下,Web服务中使用的XML语言是SOAP。SOAP原先是Simple Object Access Protocol的缩写,但由于某些原因已不是这样。协议包含三个部分:信封、数据类型规则,以及定义操作请求和响应的方法。

  Web服务在另一个XML文档中有定义,这个XML文档称为Web Services Description Language (WSDL)。WSDL指定了使用Web服务公开的操作、操作使用的数据类型定义、用于和Web服务通信的协议,以及Web服务本身的位置。

  Web服务的优势是允许用不同语言编写、在不同平台上开发的应用程序可以在广阔的Internet上相互通信。

  什么是Ajax?

  Ajax是Web开发人员用来实现富客户端表现的最先进的技术。它通过在不影响当前视图的情况下调用新请求来完成。然后返回一个XML文档显示给用户,通常作为当前视图的子页。简而言之,Ajax提供服务端动态内容,同时看上去像客户端动态内容。

  Ajax实现其功能主要通过使用XMLHttpRequest DOM API,Web开发人员直到Ajax 出现才开始使用。请求本身可以是GET或POST。

  对于任何一个请求,都会返回响应,返回的响应也可能是错误。如果响应没有错误,就会用响应的实际文本更新当前视图。

  记住伏尔泰的一句名言(即,“神圣罗马帝国既非神圣,亦非罗马,更非帝国”),深入研究各种Ajax实现会发现,Ajax不需要JavaScript代码,不需要XML,也不需要异步。除去那些,剩下的只有连接词(and)。但缩写词听上去很棒,因此业界决定保留它。

  Ajax与Web服务如何结合在一起

  想一想:富客户端体验,加上Internet上到处可访问的服务。是的,真棒。

  Ajax,如您所见,在幕后执行请求,并向Web页面显示出响应(或其中一部分),而不会更新整个网页。请求可以是简单的HTTP请求,发送给公开的Web服务的也可以是SOAP消息。然后Ajax例程中的JavaScript端解析响应(也是SOAP格式)并提取所需数据返回给应用程序,展示给用户。

  确实很简单。

  fishinhole.com的业务需求

  fishinhole.com的董事会希望其他Web应用程序可更容易地访问公司库存。他们想,如果其他网站,包括游钓论坛、博客,甚至是竞争对手零售商,都能轻松访问fishinhole.com的库存列表,销售将增加23.7%。

  您可能不关心23.7%这个数字式怎么来的,而是关注如何向其他Web应用程序公开库存。很快就可得出结论:要创建Web服务。Web服务可以让使用者根据鱼饵类型提交请求,查询库存。目前的鱼饵类型有Casting、Trolling和Other。Web服务根据使用者提供的鱼饵类型返回鱼饵清单。

  还该意识到,您的公司已超出Other类型鱼饵。应该在Web服务中妥善处理。

  部署简单的Web服务

  使用PHP创建简单的Web服务。PHP以及NuSOAP,是我见过的快速创建Web服务最简单的方法。

  首先,确认取得NuSOAP,将所有的PHP文件放在部署PHP Web服务的文件夹下。

  安装完NuSOAP后,就可以开始编写实际Web服务。清单 1 包含所有内容。

  清单 1. webservice.php
    

以下是引用片段:
<?php
require_once(‘nusoap.php’);
$server = new soap_server;
$server->register(‘hello’);
$server->register(‘retrieveByType’);
function hello($name) {
    return ‘Hello, ‘ . $name;
}
function retrieveByType($type) {
 if ($type == ‘trolling’) {
  $arr[0] = ‘Donzai Deep Swimmer 5 1/4 inch’;
  $arr[1] = ‘Yosubi Squid-like 4 inch’;
  $arr[2] = ‘Fortunata Imperial High Action’;
 } else if ($type == ‘casting’) {
  $arr[0] = ‘Silver Spring Mirrors Size 00’;
  $arr[1] = ‘Gold Spring Mirrors Size 0’;
  $arr[2] = ‘Mini Minnow Blue’;
 } else {
  $arr[0] = ‘None found!’;
 }
 return $arr;
}
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ”;
$server->service($HTTP_RAW_POST_DATA);
?>
 
  首先,注意require_once(‘nusoap.php’) 行。这一行允许PHP Web页面使用nusoap.php中定义的类。您也许想知道为何需要NuSOAP相关的其他PHP文件。实际情况是,nusoap.php依赖于这些文件,就像页面依赖nusoap.php。

  下一行实例化soap_server对象。不出所料,这将创建使用SOAP协议的Web服务。

  下一行注册retrieveByType函数以将其公开为Web服务操作。如果再往下看,会发现有个已定义函数,名为retrieveByType。那么为什么需要这一步? 因为如果不注册该函数,它只是可供包含它的本PHP页面或其他PHP页面调用的简单PHP函数。因此本行是通知soap_server对象将该函数公开为Web服务用户可用的操作。

  下一段代码实际是实现retrieveByType方法。这是个简单的PHP函数,接收一个参数:type,它可以是trolling、casting或other。如您所知,这些是fishinhole.com用户选的三个鱼饵类型。

  retrieveByType方法返回数组。数据包含请求类型特定的鱼饵列表。现在对trolling有三种不同鱼饵类型,casting有三种不同鱼饵类型。注意还有一种 “全部包含”,其中有Other和未识别类型。对于这些Web服务只简单返回None Found! 作为数组惟一元素。

  最后两行在Web服务被访问时执行。第一行检查是否有POST数据。如果没有,POST数据设为空字符串。第二行用来自POST的数据执行Web服务。POST数据包含SOAP消息。当查看使用者的时候将会看到更多。

  将该页面保存为webservice.php并放到安装NuSOAP的文件夹下。显然,需要将该页面放到能处理PHP文件的地方。目前大多数托管解决方案支持PHP,所以即使没有现成的PHP处理器,也不会有问题。

  现在通过访问以下URL快速测试Web服务:http://yourhost/yourdirectory/webservice.php。显然,需要将yourhost和yourdirectory分别用实际存放文件的主机和文件夹替换。

  得到的响应应该是SOAP响应(查看清单 2)。如果不是,则Web服务运行不正常。

  清单 2. SOAP响应
    

以下是引用片段:
<?xml version=”1.0″ encoding=”ISO-8859-1″ ?> 
<SOAP-ENV:Envelope 
SOAP-ENV:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” 
 
 
 

<SOAP-ENV:Body> 
<SOAP-ENV:Fault> 
<faultcode xsi:type=”xsd:string”>SOAP-ENV:Client</faultcode> 
<faultactor xsi:type=”xsd:string” /> 
<faultstring xsi:type=”xsd:string”>method ” not defined in service</faultstring> 
<detail xsi:type=”xsd:string” /> 
</SOAP-ENV:Fault> 
</SOAP-ENV:Body> 
</SOAP-ENV:Envelope>
 
  编写访问Web服务的页面

  从编写实际访问Web服务的JavaScript代码开始,如清单 3 所示。

  清单 3. invokeService() JavaScript函数
    

以下是引用片段:
function invokeService(type) {
 soapMessage = ‘<?xml version=”1.0″ encoding=”ISO-8859-1″?>’;
 soapMessage+='<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=””‘;
 soapMessage+=’ ‘;
 soapMessage+=’ ‘;
 soapMessage+=’ >’;
 soapMessage+=’ <SOAP-ENV:Body> <ns1:retrieveByType >’;
 soapMessage+=’ <type xsi:type=”xsd:string”>’ + type + ‘</type>’;
 soapMessage+=’ </ns1:retrieveByType> </SOAP-ENV:Body> </SOAP-ENV:Envelope>’;
 
 if(window.XMLHttpRequest) {
  httpRequest=new XMLHttpRequest();
 } else if (window.ActiveXObject) { 
  httpRequest=new ActiveXObject(“Microsoft.XMLHTTP”); 
 }
                  
 httpRequest.open(“POST”,url,true);
 if (httpRequest.overrideMimeType) { 
  httpRequest.overrideMimeType(“text/xml”); 
 }
 httpRequest.onreadystatechange=populateDiv;
      
 httpRequest.setRequestHeader(“Man”, url + ” HTTP/1.1″)
 httpRequest.setRequestHeader(“MessageType”, “CALL”);
 httpRequest.setRequestHeader(“Content-Type”, “text/xml”);
 httpRequest.send(soapMessage);
 valTimeout=setTimeout(“timeout(httpRequest);”,120000);
}            

  函数名为invokeService,接收一个参数:type。不用说,这对应于Web服务操作(retrieveByType)接收的type参数。换句话说,type参数是包含casting、trolling或other的字符串。

  函数的前几行组装SOAP消息。对于SOAP的详细描述已远远超出本文范围。尽管如此,XML的某些部分却比较直观。请注意XML其中一个元素直接对应操作名(retrieveByType)。该元素的子元素根据webservice.php文件中指定的参数名(type)来命名。并且那个元素值是传入该 JavaScript函数的字符串参数,也叫做type。

  下面几行创建跨浏览器兼容请求对象。这是用来访问Web服务的对象。

  请求对象创建后,函数设置回调函数,本例中是populateDiv()函数。这是在网页上显示库存列表的函数。

  函数然后设置头部。 值得引起注意的是,您正创建与SOAP兼容的内容类型:text/xml。还有,请注意url变量的使用。当创建自己的Web页面后,需要将变量指向自己Web服务的URL。看上去就像这样:http://www.myhost/myservicedir/webservice.php

  最后,使用请求对象发送SOAP消息,在服务不响应时设置超时。

  下一步,看看响应Ajax调用和显示库存的JavaScript代码,如清单 4 所示。

  清单 4. populateDiv() JavaScript 函数
    

以下是引用片段:
function populateDiv(){
 try {
      if(httpRequest.readyState==4) {
         if(httpRequest.status==200) {
            clearTimeout(valTimeout);
          var text = httpRequest.responseText;
     if (window.DOMParser) {
  parser=new DOMParser();
  xmlDoc=parser.parseFromString(text,”text/xml”);
     } else {
         xmlDoc=new ActiveXObject(“Microsoft.XMLDOM”);
  xmlDoc.async=”false”;
  xmlDoc.loadXML(text); 
     } 
 
            var html = “”;
     for (i=0;i<xmlDoc.getElementsByTagName(“item”).length;i++) {
      html += “<br/>” + 
             xmlDoc.getElementsByTagName(“item”)[i].childNodes[0].nodeValue;
     }
     var resultDiv=document.getElementById(“resultDiv”);
     resultDiv.innerHTML = html;           
         }
      } 
 } catch(e) { 
     alert(“Error!”+e.description); 
 }      
}
 
  使用过Ajax的人对前面几行都应该很熟悉。回想一下,每次请求对象经历状态改变的时候都会调用这个函数。这里特别要注意的是当请求对象返回有效响应时(200 代码)。

  当返回有效响应,清空超时并获取响应文本。记住,响应文本其实是SOAP响应,因此是XML格式。这意味着需要使用JavaScript编程语言来将XML解析成重要信息。

  再看下面几行。这几行实例化跨浏览器兼容XML文档对象,它可由JavaScript编程语言解析。由于SOAP响应是XML文档,因此可像其他XML文档一样解析。

  下一步创建一些HTML。以空HTML字符串开始。然后,将SOAP消息解析成item元素。请记住,Web服务返回一个数组。有可能item元素不止一个。for循环实际是说 “对每个item元素,做以下事情。”

  “以下事情” 是指:JavaScript代码获取item元素的第一个子元素。这个例子中,只有一个子元素,是个简单字符串。然后它提取该子元素的值,即库存中的一项。出于美观的目的,我在库存项前加上<br/>标记。这样列表每项都在单独行中显示。最后,所有行连接成现在的HTML,当for循环完成后,就有了完整列表。

  当HTML完成后,就可以将其放到页面上。本例中,名为resultDiv的div元素内容将用刚创建的HTML重写。结果是,当用户在页面上从下拉框选择新类型时,库存项清单就会出现。

  说道HTML,看看实际Web页面所需的HTML,如清单 5 所示。

  清单 5. 客户端的HTML
    

以下是引用片段:
<body>    
   <div style=”position:relative;left:0px;background-color:blue;margin:0px;”>   
   <h2 align=”center”><font color=”#ffffff”>FishinHole.com Web Service</font></h2></div>
   <table align=”center” cellpadding=”6px” cellspacing=”6px” width=”400″ border=”0″>
      <tr>
         <td width=”80″ valign=”center”><font color=”black”>
          Lure Type:</font></td>
         <td>
   <select name=”lureType” id=”lureType” onchange=”changeTypes()”>
    <option value=””>-SELECT-</option>
    <option value=”trolling”>Trolling</option>
    <option value=”casting”>Casting</option>
    <option value=”other”>Other</option>
   </select>
         </td>
  <td width=”150″> </td>
         <tr>
          <td colspan=”3″>
            <div id=”resultDiv”></div>
          </td>
       </tr> 
    </table>    
</body>

  这里没什么特别复杂的。下拉框有三种鱼饵类型:trolling、casting和other。我使用了onchange属性,这样当用户选择新的鱼饵类型时,调用Ajax请求的JavaScript代码会自动执行。

  还要注意,resultDiv div元素出现了。这是库存清单显示的地方。

  测试

  将刚创建的HTML页面放在可解释HTML和JavaScript代码的平台上。如果有Microsoft® Windows®操作系统,将这个页面放到硬盘上。

  接下来,就是访问Web页面。会在屏幕中间看到下拉框。现在,所选条目应该是-SELECT-。将其改成Trolling。等待几秒钟,您会看到三项的库存列表显示在屏幕上。祝贺您,测试成功!

  如果遇到问题,确认url变量设置是否对应。还有,JavaScript代码可能会报告异常,并弹出窗口,其中是描述。这会提示错误的线索。

  结束语

  Web服务是向可访问Internet的用户公开操作的功能强大的方法。Ajax是向Web应用程序用户提供丰富体验的方法,它可改变显示内容而不刷新页面。您可以同时使用二者来创建功能强大的Web应用程序,它可以模拟分布式对象应用程序,并呈现出专业的界面。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • SAP收购CallidusCloud 与Salesforce竞争

    一直被称为后台办公巨头的SAP现在似乎也想在前台办公大展拳脚。 最新的迹象是SAP收购CallidusClou […]

  • 移动HTML5挑战何在?

    当HTML5出现时,许多开发者和应用架构师视之为创建平台独立应用、简化你的设备支持以及当新的移动设备OS版本发布时减少应用相关问题的机会。

  • HTML5语义要素分析与解释

    Web设计界的最新热门是HTML5。但是当开发者四处看看时,要想弄明白HTML5究竟是什么却没有想象中那么的容易。

  • API设计如龙生九子 各不相同

    IT咨询管理公司CA Technologies对API产业做了个问卷调查,问卷内容涉及API设计风格以及管理部署的新动向。调查结果表明,JSON与XML可谓两分天下。