2006 年 5 月 25 日

使用 Asynchronous JavaScript and XML (Ajax) 设计模式实现基于 Web 浏览器的 SOAP Web 服务。在 本系列的第 1 部分“ 使用 Ajax 调用 SOAP Web 服务,第 1 部分” 中,作者引入了一个简单的用于调用 SOAP Web 服务的基于 Web 浏览器的 JavaScript 库。在接下来的讨论中,作者将实现对 Web 服务寻址语言 (Web Services Addressing Language) 和 Web 服务资源框架 (Web Services Addressing Language) 规范的支持,以便扩展 JavaScript 库的功能。

概述

请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何新信息都能在这里找到。

在 本系列的第 1 部分,我介绍了一个跨浏览器的 JavaScript 库,其中提供了一个简单的 SOAP Web 服务客户机,该客户机可以发出采用 RRC 编码和文档-文本样式的请求。该客户机包含对请求和响应处理程序、自定义 XML 序列化器/反序列化器以及 SOAP Header 的支持;所有这些支持都将在这个 WS-Addressing 和 WS-ResourceFramework 实现中用到。

ws.js (在第 1 部分中引入的)中定义的主要对象包括:

  1. WS.Call:包装 XMLHttpRequest 的 Web 服务客户机
  2. WS.QName:XML 限定名称实现
  3. WS.Binder:自定义 XML 序列化器/反序列化器的基对象
  4. WS.Handler:请求/响应处理程序的基对象
  5. SOAP.Element:包装 XML DOM 的基本 SOAP 元素
  6. SOAP.Envelope:扩展自 SOAP.Element 的 SOAP Envelope 对象
  7. SOAP.Header:扩展自 SOAP.Element 的 SOAP Header 对象
  8. SOAP.Body:扩展自 SOAP.Element 的 SOAP Body 对象
  9. XML:用于处理 XML 的跨平台实用方法

这一组对象中有五个对象对 WS-Addressing 和 WS-ResourceFramework 实现非常关键:WS.QNameSOAP.ElementWS.HandlerWS.BinderWS.Call。我强烈建议重新阅读一下第一篇文章,以回顾这些对象的基本功能。

在本文中,我将引入两个新的 JavaScript 文件。第一个文件定义支持 WS-Addressing 的对象 ( wsa.js );而第二个文件定义支持 WS-ResourceFramework 的基本实现的对象 ( wsrf.js )。


图 1. 从 Web 浏览器内使用 Web 服务 JavaScript 库调用 Web 服务资源框架服务

wsa.js 中定义的主要对象包括:

  1. WSA.EndpointReference:WS-Addressing EndpointReference 对象。
  2. WSA.EndpointReference.ReferenceParameters:WS-Addressing EPR 引用参数的容器。
  3. WSA.EndpointReference.Binder:WSA.EndpointReference 对象的 XML 序列化器/反序列化器。
  4. WSA.MessageContext:WS-Addressing SOAP 消息 Header 元数据的容器。
  5. WSA.Handler:将 WS-Addressing SOAP 消息 Header 插入 SOAP 信封的请求处理程序。

wsrf.js 中定义的主要对象包括:

  1. WSRF.Request.GetResourceProperty:WS-ResourceFramework GetResourceProperty 操作的包装对象。
  2. WSRF.Request.GetMultipleResourceProperties:WS-ResourceFrame GetMultipleresourceProperties 操作的包装对象。
  3. WSRF.Resource:用于调用 WS-ResourceFramework 操作的客户机接口。

请注意,虽然这可能意味着要了解大量的新 JavaScript 对象,但它们所提供的 API 都经过了专门设计,以尽可能减少在实际调用 Web 服务时必须进行的工作量。例如,如果您跳到清单 8,您将发现,通过使用 API,您只需使用寥寥数行代码即可调用与 WS-ResourceFramework 兼容的 Web 服务中的方法--而无需受底层 SOAP 实现细节的困扰。





回页首


实现 WS-Addressing 支持

Web 服务寻址规范定义了用于向 SOAP 信封插入寻址信息的机制。WS-Addressing 的核心是一个称为 EndpointReference 的对象,该对象可作为对特定 Web 服务实例的引用和说明。(请参见清单 1。)除了 EndpointReference 之外,WS-Addressing 规范还定义了许多 SOAP 消息 Header,可以将其用于直接在 SOAP 信封中传递寻址信息。

wsa.js JavaScript 库提供了许多实现了对 WS-Addressing EndpointReference 和 SOAP 消息 Header 元素的基本支持的对象。


清单 1. 一个简单的 WS-Addressing EndpointReference
                <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://www.example.org/services/HelloWorld</Address>
<ReferenceParameters>
<abc:foo xmlns:abc="urn:foo">This is a test</abc:foo>
</ReferenceParameters>
</EndpointReference>

WSA.EndpointReference 对象用于表示 WS-Addressing EndpointReference,如清单 2 中所示。通过将此代码与上面的 XML 进行比较,您应当能够很好地理解 API 的操作方式。


清单 2. 创建与 WSA.js 相关的 EndpointReference
                var epr = 
new WSA.EndpointReference(
"http://www.example.org/services/HelloWorld");
var epr_rp = epr.create_reference_parameters();
epr_rp.create_child(
new WS.QName('foo','urn:foo','abc')).
set_value('This is a test');

WSA.EndpointReference 的 API 目前支持 WS-Addressing 信息模型所定义的 Address 和 ReferenceParameters 属性。目前尚未实现 Metadata 属性,因为这个属性对于此处实现的客户机基本功能并不重要。

WS-Addressing SOAP 消息 Header 应该设置在 Web 服务客户机发送给服务的 SOAP 信封上。由于在 ws.js JavaScript 库中定义的 WS.Call 对象将隐藏使用底层 SOAP 信封的细节,因此请使用 WS.Handler 来为您插入恰当的 Header。

Web 服务客户机将针对每个请求、响应和错误调用 WS.Handler 对象的各个方法。对于 WS-Addressing 实现,提供了一个 WSA.Handler,以使用相应的 WSA.MessageContext 对象(其中包含要插入到消息中的信息)。清单 3 演示了这一过程。


清单 3. 使用 WS-Addressing 上下文和处理程序
                var address = 'http://www.example.com/services/HelloWorld';
var ctx = new WSA.MessageContext();
ctx.to = new WSA.EndpointReference(address);
ctx.replyto = new WSA.EndpointReference(WSA.ANONYMOUS);
ctx.action = address + '#SayHello'

var handler = new WSA.Handler();
handler.set_context(ctx);

var call = new WS.Call('');
call.add_handler(handler);

WSA.MessageContext 对象中的属性与每个 WS-Addressing SOAP 消息 Header 相对应:

  • to:一个 WSA.EndpointReference 对象,其 Address 指定表示信息目的地的绝对 URI。
  • from:一个 WSA.EndpointReference 对象,标识消息的发送方。
  • replyto:一个 WSA.EndpointReference 对象,标识回复应送达的位置。
  • faultto:一个 WSA.EndpointReference 对象,标识错误应送达的位置。
  • action:一个绝对 URI,标识消息应触发的操作。
  • messageid:唯一标识消息的绝对 URI。
  • relatesto:标识相关消息的 URI 对的数组。URI 对中的第一个 URI 标识关系类型;第二个 URI 指定相关消息的唯一 Message ID。

WSA.Handler 向用于调用 Web 服务的 WS.Call 对象进行了注册后,WS.Call 对象就会在每次请求时调用该处理程序,向其传递对 SOAP.Envelope 对象的引用。处理程序将从 WSA.MessageContext 中提取信息,并向消息中插入恰当的 Header,如清单 5 中所示。





回页首


实现 WS-ResourceFramework 支持

Web 服务资源框架定义了一个使用 Web 服务标准访问和操作有状态资源的实例的约定。各个资源均使用 WS-Addressing EndpointReference 进行标识和引用。可以使用一些常见操作来检索或修改资源的属性。

wsrf.js JavaScript 库提供了支持 GetResourceProperty 和 GetMultipleResourceProperties 操作的部分 Web 服务资源框架实现。该 API 是以 ws.js wsa.js API 为基础构建的,主要是为了演示这两个脚本的使用而设计的,而不是为了提供全面的 WS-ResourceFramework 实现。

WS-ResourceFramework 操作是定向到特定 Resource 实例的文档-文本 SOAP 请求。目标资源是用 WS-Addressing EndpointReference 标识的,如清单 4 所示。


清单 4. WSRF EndpointReference
                <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://localhost:9080/SoapAjax2/services/DeviceService</Address>
<ReferenceParameters>
<abc:deviceid xmlns:abc="urn:deviceservice">ABC123</abc:deviceid>
</ReferenceParameters>
</EndpointReference>

当使用 wsa.js 中定义的机制在 SOAP 内进行表示时,WSRF EndpointReference 中的信息将以 SOAP 消息 Header 的形式出现,如清单 5 中所示。


清单 5. WSRF GetResourceProperty 请求
                <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Header>
<To xmlns="http://www.w3.org/2005/08/addressing">
http://localhost:9080/SoapAjax2/services/DeviceService</To>
<abc:deviceid xmlns="urn:deviceservice">ABC123</abc:deviceid>
</Header>
<Body>
<GetResourceProperty
xmlns="http://docs.oasis-open.org/wsrf/rp-2"
xmlns:ns="urn:foo">ns:bar</GetResourceProperty>
</Body>
</Envelope>

wsrf.js 提供的 API 用于隐藏使用 SOAP Envelope 的所有细节以及允许与 WS-ResourceFramework Web 服务交互所必需的 WS-Addressing Header。不过,稍微注意一下此代码,您就会发现此代码的工作方式的许多重要方面。

清单 6 演示了 WSRF GetResourceProperty 操作的包装对象。此包装对象由 wsrf.js 库内部使用,其中包含了创建 SOAP 信封和构建操作所必需的 XML 的基本机制。请注意,该对象利用了 ws.js 提供的 SOAP.Element 和 SOAP.Envelope API。在包装对象初始化阶段传入的“qname”参数是所请求的属性的 XML 限定名称。


清单 6. WSRF GetResourceProperty 请求包装对象
                WSRF.Request.GetResourceProperty = Class.create();
WSRF.Request.GetResourceProperty.prototype = {
initialize : function(qname) {
this.envelope = new SOAP.Envelope();
this.set_qname(qname);
},
set_qname : function(qname) {
var body = this.envelope.create_body();
var method = body.create_child(
WSRF.Request.QNAME_GETRESOURCEPROPERTY);
if (!qname.namespace) qname.namespace = '';
if (!qname.prefix) qname.prefix = 'ns';
method.declare_namespace(qname);
method.set_value(qname.value_of());
}
};

清单 7 中包含了来自 WSRF.Resource 对象的代码片段。您所看到的代码的作用在于:创建 WS.Call 对象,准备将用于设置恰当的 SOAP 消息 Header 的 WSA.Handler 对象,创建 WSRF.Request.GetResourceProperty 包装对象以及调用各个 Web 服务操作。


清单 7. 调用 WSRF GetResourceProperty
                get_resource_property : function(qname,callback) {
var call = new WS.Call(this.address);
var handler = new WSA.Handler();
var wsactx = new WSA.MessageContext(this.epr);
handler.set_context(wsactx);
call.add_handler(handler);
var req = new WSRF.Request.GetResourceProperty(qname);
call.invoke(req.envelope,callback);
}

为了对 WS-ResourceFramework Web 调用 GetResourceProperty 操作,应用程序只需要提供目标 WS-Resource 的 EndpointReference 和标识被检索的属性的 WS.QName 对象即可,如清单 8 中所示。


清单 8. 最终结果
                var ADDRESS = 'http://localhost:9080/SoapAjax2/services/DeviceService'

function getDeviceName(deviceid,container) {
var epr = new WSA.EndpointReference(ADDRESS);
var epr_rp = epr.create_reference_parameters();
epr_rp.create_child(
new WS.QName(
'deviceid',
'urn:deviceservice')).set_value(deviceid);
var res = new WSRF.Resource(ADDRESS,epr);
res.get_resource_property(
new WS.QName('DeviceName','urn:deviceservice'),
function(call,envelope) {
$('soap').innerHTML = arguments[2].escapeHTML();
}
);
}

清单 8 将对 WS-Resource 的调用包装在可以从 HTML 页中的任何位置调用的适当函数中。清单 9 提供了一个按钮,该按钮可以从名为 id 的输入字段传入一个设备 ID,并在名为 result 的元素中显示响应 SOAP 信封。


清单 9. 调用 getDeviceName
                <input 
value="Invoke the Web Service"
type="button"
onclick="getDeviceName($('id').value,$('result'))" />





回页首


后续部分

在 这一部分中,您了解了在本系列第 1 部分中引入的 Ajax Web 服务客户机可以如何进行扩展,以支持更高级的 Web 服务标准(如 Web 服务寻址和 Web 服务资源框架)。在下一部分中,作者将讨论对 Web 服务描述语言 (Web Services Description Language) 的支持。






回页首


下载

描述 名字 大小 下载方法
Sample project ws-wsajax2code.zip 14 KB HTTP
关于下载方法的信息


参考资料

学习
  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文。

  • 在本系列的第 1 部分“构建 Web 服务客户机”中,作者引入了一个简单的用于调用 SOAP Web 服务的基于 Web 浏览器的 JavaScript 库。

  • 您可以参阅 本系列的其他文章。

  • Ajax 技术资源中心:developerWorks 上所有有关 Ajax 的问题都可以在这里找到解答。

  • High Availability Disaster Recovery (HADR)——了解 DB2 UDB V9 中的功能,该产品可提供高可用性解决方案,用于针对部分或完全站点故障提供保护。

  • 面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序——Philip McCarthy 在这篇文章文中向 Java 开发人员介绍了 Ajax(developerWorks,2005 年 9 月)。

  • JavaScript Framework——了解 Web Services JavaScript Library 所基于的原型框架。

  • XMLHttpRequest API——从 XUL Planet 网站上了解更多关于 XMLHttpRequest API 的内容。

  • Exploit the Document Object Model to create enhanced Web application——了解更多关于 Microsoft Internet Explorer 6.0 所使用的 XML 文档对象模型的信息(developerWorks,2004 年 2 月)。

  • Mozilla Web Services——了解更多关于 Mozilla/Firefox 内置 Web 服务支持的信息。

  • Web Services Resource Framework——了解更多关于 oasis Web Services Resource Framework 活动的信息。

  • Web Services Addressing——了解更多关于 W3C Web Services Addressing 活动的信息。

  • 标准发展路线——了解标准和规范对于 SOA 和 Web 服务开发工作的影响和重要性。

  • Architecture: Build for the future——访问 developerWorks 的体系结构专区,以获取提高您的体系结构方面的技能的各种资源。

  • 请访问 SOA and Web services 专区,以获得数百篇关于如何开发 Web 服务应用程序的文章以及入门级、中级和高级教程,您将大开眼界。

讨论
  • developerWorks 博客——加入 developerWorks 社区。



关于作者


James Snell 是 IBM 的 software group 中的 emerging Internet technologies 小组的一名设计师兼策略专家,在这个小组中,他在 Web 服务技术不断发展的体系结构和实现中起到了积极的作用。他是 Programming Web Services with SOAP(O'Reilly 和 Associates 出版)一书的合著者。您可以通过 jasnell@us.ibm.com与 James 联系。

[转]使用 Ajax 调用SOAP Web 服务,第 2 部分: 扩展 Web 服务客户机的更多相关文章

  1. AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas的示例代码

    这篇文章主要介绍了AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. xcode – Cordova plugin.xml添加“Header Search Paths”条目

    我希望将Cordova插件添加到Xcode项目后,在“HeaderSearchPaths”下添加一个新条目.如何在Cordovaplugin.xml文件中进行配置?

  3. ios – iPhone 6 Plus横向模式中的奇怪错误,带有标签和固定元素

    我有一些疯狂的问题iPhone6Safari(主要是iOS9,虽然iOS8也有一些小故障),标签模式打开.所有固定元素都以纵向和横向正确定位,但在横向模式下不可见和/或移动,并打开一个或多个标签.即使它们不可见,它们仍然可以点击并与其他内容重叠.旋转设备在一定程度上解决了问题,以及在标签之间切换.将元素位置从固定设置为静态和背面也有帮助.HTML:CSS:应用程序非常大,但我已经成功地在codep

  4. ios – 使用CocoaPods post install hook将自定义路径添加到HEADER_SEARCH_PATHS

    解决方法在Podfile中定义一个方法:然后在post_install中调用该方法:

  5. ios – 为什么Web Inspector向我显示“无检查应用程序”?

    什么可能是一个可能的原因,什么可以解决?解决方法我有同样的问题,这是因为我正在运行iOS8,通过将Safari更新到7.1来修复.

  6. ios – 如何使用XIB自定义tableView Section Header?

    我正在尝试为UITableView创建自定义的节标题.我找到了一些参考资料,说明如何在代码中完成这项工作.我试图确定是否可以在InterfaceBuilder中创建UIView并使用它来自定义标题,类似于如何为UITableViewCell执行此操作?

  7. 应用程序关闭时的iOS任务

    我正在构建一个应用程序,通过ajax将文件上传到服务器.问题是用户很可能有时不会有互联网连接,并且客户希望在用户重新连接时安排ajax调用.这可能是用户在离线时安排文件上传并关闭应用程序.应用程序关闭时可以进行ajax调用吗?

  8. swift - The Proxy Pattern

    我在实际工作中vc也仿照过Foundation的delegate:button:内涵业务逻辑,底层实现;每个button是一个类,业务逻辑需要未知的参数和处理之后未知的结果反馈UI:点击button之后界面的改变,UI实现未知的参数和未知的结果反馈,也就是实现这个代理这样以来UI的定制,很灵活很容易,代码思路依然清晰如初。哪个是主体哪个是代理并不重要关键是看定义所说whichisusedwhenanobjectisrequiredtoactasaninterfacetoanotherobjectorres

  9. Swift 引入 Object-c 代码

    如果要在Swift引入OC的代码:1.创建一个header文件工程名:Bridging-Header.h2、设置path在target-BuildSettings-SwiftCompiler-CodeGeneration中的Object-cBridgingHeader填入此文件的路径,这个路径是基于项目工程文件夹的,写的时候注意,如果出错,看日志查路径即可。

  10. Swift retrieved by calling -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:

    保存提示:之前一直都是用纯代码,现在用XIB和StoryBoard,经常碰到的问题,现在记录下来;哈哈哈,这样就显示出来了。

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部