您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 销售管理 > 使用Ajax调用SOAPWeb服务
Ajax已普遍用于许多知名的Web应用程序服务,例如GMail、GoogleMaps、Flickr和Odeo.com。通过使用异步XML消息传递,Ajax为Web开发人员提供了一种扩展其Web应用程序价值和功能的途径。这里介绍的WebServicesJavaScriptLibrary扩展了该基础机制,其通过引入对调用基于SOAP的Web服务的支持来增强Ajax设计模式。从浏览器中调用Web服务从Web浏览器中调用SOAPWeb服务可能会比较麻烦,这是因为大多数流行的Web浏览器在生成和处理XML方面都略有不同。所有浏览器都一致实现且用于XML处理的标准API或功能少之又少。浏览器实现人员一致支持的机制之一是XMLHttpRequestAPI,它是Ajax设计模式的核心。developerWorks网站最近发布的另一篇由PhilipMcCarthy撰写的的文章详细介绍了该API。XMLHttpRequest是一个用于执行异步HTTP请求的JavaScript对象。PhilipMcCarthy在其文章中描述了一个顺序图(请参见图1),此图对于理解XMLHttpRequest对象如何支持Ajax设计非常有帮助(请参阅参考资料,以获得指向全文的链接)。图1.PhilipMcCarthy的Ajax顺序图请访问Ajax技术资源中心,这是有关Ajax编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki和新闻。任何新信息都能在这里找到。从此图中,您可以清楚地看到XMLHttpRequest对象是如何工作的。一些运行在Web浏览器内的JavaScript创建了一个XMLHttpRequest实例和一个用于异步回调的函数。然后,该脚本使用XMLHttpRequest对象对服务器执行HTTP操作。在接收到响应后,调用回调函数。在该回调函数内,可能处理返回的数据。如果返回的数据碰巧是XML,则XMLHttpRequest对象将自动使用浏览器中内置的XML处理机制来解析该数据。遗憾的是,使用Ajax方法的主要难题在于XMLHttpRequest对象自动解析XML的详细过程。例如,假设我正在请求的数据是一个SOAP信封,其包含来自许多不同XML命名空间的元素,并且我希望提取yetAnotherElement中属性attr的值。(请参见清单1)清单1.一个包含多个命名空间的SOAP信封s:Envelopexmlns:s=:xsd=:xsi=:Header/s:Bodym:someElementxmlns:m=:n==urn:examplem:yetAnotherElementn:attr=abcxmlns:n=urn:foo//n:someOtherElement/m:someElement/s:Body/s:Envelope在Mozilla浏览器和Firefox浏览器中,提取attr属性值非常简单,如清单2所示。清单2.在Mozilla和Firefox中检索attr属性值的方法不能运用在InternetExplorer中varm=el.getElementsByTagNameNS('urn:example','yetAnotherElement')[0].getAttributeNS('urn:foo','attr');alert(m);//displays'abc'关于安全性由于涉及许多实际安全问题,因此在缺省情况下,大多数Web浏览器中的XMLHttpRequest对象都限制为只能与用户正在查看的Web页所在的域中承载的资源和服务进行交互。例如,如果我正在访问一个位于的页面,则XMLHttpRequest将只允许访问位于example.com域中的资源。对于阻止恶意应用程序代码潜在地对其不应该访问的信息进行不适当的访问,这种预防措施非常必要。因为这里介绍的Web服务客户机基于遗憾的是,以上代码无法在InternetExplorerVersion6中运行,因为该浏览器不仅没有实现getElementsByTagNameNS功能,而且事实上还使用了一种很糟糕的方法——将XML命名空间的前缀作为其元素和属性名称的一部分来对待。InternetExplorer缺少对XML命名空间的支持,这使得它很难处理命名空间密集的XML格式,例如采用独立于浏览器的方式的SOAP。即使要执行一些像提取结果中的属性值这样简单的操作,您也必须编写能够在多个浏览器中实现一致预期行为的特殊代码。幸运的是,这种特殊代码可以封装并重用。为了从Web浏览器中调用Web服务,并可靠地处理SOAP消息,您需要首先了解一些安全问题(请参见侧栏“关于安全性”)。此外,您还需要编写一个JavaScript脚本库(图2),以便将底层浏览器XML实现中的不一致情况抽象出来,从而使您能够直接处理Web服务数据。图2.在使用WebServicesJavaScriptLibrary的Web浏览器中通过Javascript调用Web服务图2中的WebServicesJavaScriptLibrary(ws.js)是一组JavaScript对象和实用功能,它们为基于SOAP1.1的Web服务提供了基本的支持。Ws.js定义了下列对象:WS.Call:一个包装了XMLHttpRequest的Web服务客户机WS.QName:XML限定名实现WS.Binder:自定义XML序列化器/反序列化器的基础WS.Handler:请求/响应处理程序的基础SOAP.Element:包装了XMLDOM的基本SOAP元素SOAP.Envelope:SOAPEnvelope对象扩展了SOAP.ElementXMLHttpRequest,所以这种限制同样适用于您将会调用的Web服务。如果您需要能够访问位于另一个域中的Web服务,您可以使用以下两种合理的解决方案:对JavaScript进行数字签名。通过对JavaScript脚本进行数字签名,您就告诉了Web浏览器可以信任该脚本不会执行任何恶意的活动,并且对XMLHttpRequest可以访问的数据的限制也应该取消。使用代理。一个简单的解决方案是,通过位于加载的页面所在的域中的代理资源来传递所有来自XMLHttpRequest的请求。该代理将XMLHttpRequest的请求转发到远程位置,并将结果返回给浏览器。从XMLHttpRequest对象的角度来看,这种交互发生在现有的安全配置之内。SOAP.Header:SOAPHeader对象扩展了SOAP.ElementSOAP.Body:SOAPBody对象扩展了SOAP.ElementXML:用于处理XML的跨平台实用方法ws.js的核心是WS.Call对象,该对象提供了调用Web服务的方法。WS.Call主要负责与XMLHttpRequest对象进行交互,并处理SOAP响应。WS.Call对象公开了以下三个方法:add_handler。向处理链添加请求/响应处理程序。处理程序对象在调用Web服务的前后被调用,以支持可扩展的预调用处理和后调用处理。invoke。将指定的SOAP.Envelope对象发送给Web服务,然后在接收到响应后调用回调函数。当调用使用文本XML编码的文档样式的Web服务时,请使用此方法。invoke_rpc。创建一个封装RPC样式请求的SOAP.Envelope,并将其发送到Web服务。当接收到响应时,调用回调函数。在通常情况下,WS.Call对象只不过是位于XMLHttpRequest对象顶层的瘦包装器(thinwrapper),该包装器能够执行许多简化处理的操作。这些操作包括设置SOAP1.1规范要求的SOAPActionHTTPHeader。使用ws.jsWebservicesJavaScriptLibrary提供的API非常简单。SOAP.*对象(SOAP.Element、SOAP.Envelope、SOAP.Header和SOAP.Body)提供了构建和读取SOAP信封的方法,如清单3所示,因而处理XML文档对象模型的底层细节就顺利地抽象出来。清单3.构建一个SOAP信封varenvelope=newSOAP.Envelope();varbody=envelope.create_body();varel=body.create_child(newWS.QName('method','urn:foo'));el.create_child(newWS.QName('param','urn:foo')).set_value('bar');清单4显示了由清单3中的代码生成的SOAP信封。清单4.构建一个SOAP信封Envelopexmlns==urn:fooparambar/param/method/Body/Envelope如果您正在创建的SOAP信封代表一个RPC样式的请求,则SOAP.Body元素提供了一个简便方法set_rpc(如清单5所示),该方法能够构造一个完整的RPC请求——包含一个指定的操作名称、一个指定的输入参数数组和一个SOAP编码样式的URI。清单5.构建一个RPC请求信封varenvelope=newSOAP.Envelope();varbody=envelope.create_body();body.set_rpc(newWS.QName('param','urn:foo'),newArray({name:'param',value:'bar'}),SOAP.NOENCODING);每个参数都作为一个JavaScript对象结构进行传递,且可能带有以下属性:name。一个指定参数名称的字符串或WS.QName对象。必需。value。参数的值。如果该值不是一个简单数据类型(例如,字符串、整数或其他),则应该指定一个能将该值序列化为适当的XML结构的WS.Binder。必需。xsitype:标识参数的XML模式实例类型的WS.QName(例如,xsi:type=int对应xsitype:newWS.QName('int','))。可选。encodingstyle:标识参数所使用的SOAP编码样式的URI。可选。binder:能够将参数序列化为XML的WS.Binder实现。可选。例如,如果要指定的参数名为“abc”、XML命名空间为“urn:foo”、xsi:type为“int”且值为“3”,则我会使用以下代码:newArray({name:newWS.QName('abc','urn:foo'),value:3,xsitype:newWS.QName('int',')})。一旦我为服务请求构建了SOAP.Envelope,我就会将该SOAP.Envelope传递到WS.Call对象的invoke方法,以便调用该信封内编码的方法:(newWS.Call(service_uri)).invoke(envelope,callback)另一种可选方案是手动构建SOAP.Envelope。我会将参数WS.QName、参数数组和编码样式传递到WS.Call对象的invoke_rpc方法,如清单6所示。清单6.使用WS.Call
本文标题:使用Ajax调用SOAPWeb服务
链接地址:https://www.777doc.com/doc-1584876 .html