扩展Web服务客户机

日期: 2008-07-08 作者:James Snell 来源:TechTarget中国

  使用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库的功能。


  概述


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


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


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


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


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



  图1. 从Web浏览器内使用Web服务JavaScript库调用Web服务资源框架服务
 
  wsa.js中定义的主要对象包括:


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


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


  ·WSRF.Request.GetResourceProperty:WS-ResourceFramework GetResourceProperty操作的包装对象。
  ·WSRF.Request.GetMultipleResourceProperties:WS-ResourceFrame GetMultipleresourceProperties操作的包装对象。
  ·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   >
    <Address>http://www.example.org/services/HelloWorld</Address>
    <ReferenceParameters>
      <abc: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   >
   <Address>http://localhost:9080/SoapAjax2/services/DeviceService</Address>
    <ReferenceParameters>
      <abc:DeviceID   >ABC123</abc:DeviceID>
    </ReferenceParameters>
  </EndpointReference>
 
  当使用wsa.js中定义的机制在SOAP内进行表示时,WSRF EndpointReference中的信息将以SOAP消息Header的形式出现,如清单5中所示。


  清单5. WSRF GetResourceProperty请求
                <Envelope   >
   <Header>
    <To >
      http://localhost:9080/SoapAjax2/services/DeviceService</To>
    <abc:DeviceID >ABC123</abc:DeviceID>
   </Header>
   <Body>
   <GetResourceProperty
   
    >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)的支持。

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

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

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

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • AWS MEAN堆栈+JavaScript=快速搭建应用

    开发人员在构建Web应用时有许多选择。市面上有无数的框架和语言可选,而像AWS这样的云平台可以方便地部署和扩展应用程序。

  • JDK 8u40更新:新增功能抢先看

    俗话说长江后浪推前浪,一代新人换旧人,Java更新版本交替,也是这样一个道理。甲骨文又给Java添加了哪些新功能。

  • 移动浏览器到云:JavaScript地位正在扩张

    不难发现人们非常喜欢在前端开发中使用JavaScript。但是,令我们惊讶的是后端开发也如此青睐JavaScript,促进了基于云和基于数据中心的托管应用的发展。

  • 移动HTML5挑战何在?

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