使用 Dojo 处理 Web Services 响应

使用 Dojo 简化 Web Servicess 的使用

使用 Web Servicess 发布与语言和平台无关的功能。在客户端方面,Dojo 作为一个使用最少编程量实现富客户端体验的 JavaScript 工具,越来越受欢迎。学习利用您已经掌握的 Dojo 解析和处理 Web Services 响应。

Brian M. Carey, 高级系统工程师, Triangle Information Solutions

Brian Carey 是一位信息系统顾问,擅长 Java 企业应用程序的架构、设计和实现。



2011 年 6 月 13 日

什么是 Web Servicess?

Web Servicess 是一种通过 Hypertext Transfer Protocol (HTTP) 访问的基于 Web 的应用编程接口(API)。在主机端,特定的操作是使用 Extensible Markup Language (XML) 定义的,即 Web Servicess Description Language (WSDL)。客户端和主机之间的信息交换的标准也称为 Simple Object Access Protocol,或 SOAP。(事实上,Web Servicess 有很多缩写词。)

在实践中,Web Servicess 利用了一个集中访问点进行信息交换。顾名思义,它们提供了一种服务供所有客户端使用。例如,Web Servicess 可用于获取最新头条新闻、在线图书商店的最新列表或者某个特定地理位置的捕渔报告。另外,这些信息经常通过网站进行发布,如专业新闻创作或个人博客。

什么是 Dojo?

Dojo 是一个开放源码 JavaScript 用户界面(UI)工具套件,它促进了 JavaScript 应用的快速部署。它是一系列加快和简化 JavaScript 代码编写的 JavaScript 库。

Dojo 框架的其中一个主要的组件是 Dojo Base。这个部分的 Dojo 库负责处理复杂的事件处理、Asynchronous JavaScript + XML (Ajax) 调用、Cascading Style Sheets (CSS) 查询、效果等等。

Dojo Base 之上是一个名为 Dijit 的小部件 — Dojo 的其中最流行的特性。这是一系列可重用的组件,您可以直接拖放到您自己的应用中。为了定制您的应用的外观和体验,您只需要对大多数小部件进行简单的配置。

使用 Dojo 和 Web Services 构建一个应用

FishinHole.com 的董事会已经确定了通过一个 Web Services 显示公司的产品目录(并实现目录可搜索),从而更广泛地将产品通过 Web 推广出去,这样公司便可以占据相应的竞争优势。董事会要求您创建这个 Web Services 并创建一个原型来说明通过简单 Web 页面访问它的方式 — 明天之前完成。

由于这个公司已经使用 PHP 实现了在线显示目录,所以它也会使用 PHP 来处理 Web Services。有一个名为 NuSOAP 的 PHP 库可以简化使用 PHP 进行 Web Services 的快速开发过程,它支持大多数据的 SOAP 1.1 规范,也能够生成符合 WSDL 1.1 规范的文档。

现在考虑一下客户端的需求:这个 Web Services 其实 “非常简单”。它调用一个可以运行在本地个人电脑而不需要使用 PHP 翻译器(或其它相关技术)的 Web Services。然后有一个简单的带有 JavaScript 代码的 Hypertext Markup Language (HTML) 页面可以生成所需要的结果。虽然您一开始生成的结果是非常简单的,但是 Dojo 支持扩展,它能够在将来实现一些花俏的用户界面特性。由于您使用了 Dojo,那么您也可以选择使用它来处理 XML,从而保持开发的一致性。

部署一个简单的 Web Services

这样一个您使用了 PHP 和 NuSOAP 编码的 Web Services 会返回一个基于公司所销售的鱼饵类型的列表。在这个非常简单的例子中,鱼饵的类型只有三种:拖钓型、投掷型和其他。

清单 1 显示了这个简单的使用 PHP 和 NuSOAP 编写的符合 SOAP 的 Web Services。

清单 1. 一个使用 PHP 编写的简单 Web Services
<?php
require_once('nusoap.php');
$server = new soap_server;
$server->register('retrieveByType');

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 库。要使用这个库,您必须先下载。参考资料 中有关于下载 NuSOAP 的更多信息。

下一行代码初始化了一个名为 $server 的 PHP 对象。这个对象的类型是 soap_server,它是在 NuSOAP PHP 库中定义的。当客户端调用其中一个服务操作时,这个对象将处理这个操作并返回结果。

下一行代码将一个函数注册为一个 Web Services 操作。在这里,您只有一个操作,因此也只有一个函数。根据本例的要求,这个操作的名称和函数的名称是一样的(但这是一个非常好的实践做法,因为它可以避免混淆)。当您调用名为 retrieveByType 的 SOAP 操作时,相同名称的 PHP 函数就会被调用。

接下来是上面提到的 PHP 函数的实现。注意这个函数只接受一个参数:typetype 将会与以下两个字符串之一进行比较:trollingcasting。如果这两个字符串中有任意一个与参数相匹配,那么函数就会返回相应的鱼饵数组。如果不匹配,那么就会返回字符串 None found!

倒数第二行代码显示 Web Services 是如何处理操作调用的。您可以看到,参与这个调用的 Web Services 将会由 POST(与 GET 相对应)触发。这类似于一般 Web 应用中所使用的表单提交方式。这一行代码也会专门处理 null 值,它将 null 值转换为一个空字符串以避免后面的处理出现问题。

最后,这个服务器对象调用它的 service 函数。这个函数接受以 POST 方式提交的数据,然后返回正确的响应给客户端。

这样您就完成了这个 Web Services 的开发。将这个文件命名为 webservice.php,并将它保存在您使用的主机上。

使用 JavaScript 调用这个服务

因为您使用 Dojo 来处理和解析您新的 Web Services 返回的 XML,所以您必须在您的客户端代码的开头引用 Dojo 库(如 清单 2 所示)。

清单 2. 引用 Dojo 库
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js" 
	type="text/javascript"></script>

上面的代码位于您的 HTML 页面的 head 元素内。以这种方式引用 Dojo,您就不需要下载库文件,因为它已经存在 Web 上了。可惜,如果所引用的网站宕机了,那么您的应用也会宕机。幸好,Google 很少会发生宕机。

清单 3 显示了这个 Web Services 在 HTML 页面上是如何编程调用的。

清单 3. invokeService() 函数
function invokeService(type) {
    soapMessage = '<?xml version="1.0" encoding="ISO-8859-1"?>';
    soapMessage+='<SOAP-ENV:Envelope SOAP-ENV:";
    soapMessage+=;encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"';
    soapMessage+=' xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"';
    soapMessage+=' xmlns:xsd="http://www.w3.org/2001/XMLSchema"';
    soapMessage+=' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
    soapMessage+=' xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"';
    soapMessage+=' xmlns:si="http://soapinterop.org/xsd">';
    soapMessage+=' <SOAP-ENV:Body> <ns1:retrieveByType ';
    soapMessage+='xmlns:ns1="http://fishinhole.com">';
    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);              
}

虽然看起来编码量不少,但是这个清单的内容对于熟悉 Ajax 的开发人员来说是很简单的。

首先,一个符合 SOAP 规范的消息被构造成一个字符串。这个消息的大部分代码都是直接编写的。除了鱼饵类型,它是以下三个字符串之一:trollingcastingother。这些类型看起来很相似,只有 other 特别些(它将用于判断是否返回 None found! 结果)。

在创建了这个 SOAP 消息后,您还需要添加一些额外的代码来保证符合跨浏览器支持。然后,HTTP 请求对象会根据客户端所使用的浏览器类型来初始化。这个对象是 httpRequest

Web Services 的访问采用的是 POST 方法;这可以在 httpRequest 函数处理 httpRequest 时看出。您之前的编码预期会出现这个结果。您选择部署 Web Services 的位置将决定 url 输入参数的值(它的格式类似于 http://www.myhost.com/webservice.php)。

httpRequest 对象的 onreadystatechange 函数的调用对于本页面的功能实现非常重要。它被设置为 populateDiv,这是 Web Services 响应返回时作为回调函数的 JavaScript 函数的名称。

接下来几行代码的作用是设置具体的头信息。在这之后,Web Services 会在 send 函数被调用时正式调用。注意这个函数的输入参数是之前所创建的 SOAP 消息。

清单 4 显示的是 JavaScript 函数 populateDiv

清单 4. populateDiv 函数
function populateDiv(){
   	try {
       if(httpRequest.readyState==4) {
            if(httpRequest.status==200) {
            clearTimeout(valTimeout);
          var text = httpRequest.responseText;
          var dom = dojox.xml.parser.parse(text); 
          var docNode = dom.documentElement; 
          var html = "";

          var returnElement = docNode.childNodes[0].childNodes[0].childNodes[0];

          for (var i = 0; i < returnElement.childNodes.length; i++) { 
           html +="<br/>" + 
        	dojox.xml.parser.textContent(returnElement.childNodes[i]);
          }

          var resultDiv=document.getElementById("resultDiv");
          resultDiv.innerHTML = html;
         	}
        } 
   	 } catch(e) { 
       alert("Error!"+e.description); 
     }      
}

注意,因为您同时处理请求/响应机制和 XML 解析,所以使用 try/catch 编写整个函数。您可能希望捕捉所遇到的所有异常,然后输出这些异常以便调试。

这时,这里会执行几个检查。如果接收到一个响应,那么请求对象会注册为就绪状态 4。如果响应有效,那么它会注册状态为 200。

一旦接收到一个有效的响应,那么超时变量就会被清除,这意味着您不需要担心您的 Web Services 会超时。

接下来,代码将获取这个响应的实际内容 — 采用 XML 格式并且很可能与之前编写的响应非常相似。该内容拥有一个包含基于所选择的鱼饵类型的文本响应的元素。

最后,Dojo 会被调用来解析所返回的 SOAP 消息,然后在下一行代码中处理文档的根元素。

然后您会看到 NuSOAP Web Services 返回了一个或多个 item 元素。这些元素位于响应的第 4 层深度位置(即设置 returnElement 对象的那一行)。在某种程序上,您查看的是根元素的第 4 级子元素。为了查看这些元素,您需要遍历第 3 级子元素的所有子元素(这个元素名为 return,它反映了 JavaScript 对象的名称)。

遍历所有的第 4 级子元素,只提取这个元素的文本部分(这里是鱼饵的描述信息),并且在这个文本部分之前添加一个 <br/> 标签,从而在每一个鱼饵名称后面加一个空行来进行分隔。

最后,获取 DIV 元素,它是用于显示响应的。然后所构建的 HTML 会填充到这个 DIV 中,这样它就能即时显示响应内容。

测试

一旦您部署好客户端和 Web Services 代码,就可以测试您的原型代码。

这个客户端可以直接在您的本地计算机上运行。任何 Web 浏览器(如 Microsoft® Windows® Internet Explorer 或 Mozilla Firefox)都可以处理本地 HTML 文件,即使它使用了 JavaScript 代码。

当网页显示时,它会显示一个简单的下拉菜单,您可以选择一个鱼饵类型。如果您选择了Trolling,那么结果马上会显示在下拉菜单下面。再选择 Casting,那么结果会发生变化。如果您选择Other,那么您会看到 None found!

结束语

董事会在催促您完成工作;您必须按期创建一个 “非常简单” 的 Web Services。

更重要的是,您使用几种非常简单的技术(PHP、NuSOAP 和 Dojo)展示了一种可行的方法。通过这个方法,您展示了您的能力,也展示了如何快速有效地实现应用整合。最后,您使用这种方法消除 Web Services 实现的复杂性。

或许您很快就可以得到晋升。


下载

描述名字大小
本文所使用的 PHP Web Services 文件webservice.php1KB
客户端 HTML/JavaScript 代码client.html2KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development, SOA and web services
ArticleID=680388
ArticleTitle=使用 Dojo 处理 Web Services 响应
publish-date=06132011