dojo的使用_将Dojo的JsonRestStore与您的REST服务一起使用

本文介绍了一种将自定义REST服务连接到Dojo的JsonRestStore的简便方法,展示了如何通过转换服务接口以满足JsonRestStore的要求,实现与预存REST服务的有效通信。

Dojo的数据抽象层dojo.data为Dojo应用程序提供了访问各种后端服务的标准API。 位于Dojo扩展库DojoX中的JsonRestStore使您可以快速将应用程序连接到后端表示状态传输(REST)服务。

JsonRestStore是将Dojo链接到REST服务的很好的解决方案。 但是,默认情况下,JsonRestStore对传递给服务并由服务返回的信息的格式有期望。 自定义这些交互的服务映射描述(SMD)工具充其量很难理解。

当Dojo应用程序作者需要与预先存在的后端REST存储进行通信时,当该存储的通信无法更改时,他们将使用自定义dojox.rpc.Service实现。

在本文中,学习一种简单的通用服务实现,用于将非标准REST服务连接到JsonRestStore。 通过一个实际的例子,探索如何使用它并将其扩展到自己的服务中。

要下载本文的源代码,请参阅“ 下载”部分。

服务实施示例

EasyRestService提供了四个REST操作的实现:POST(创建),GET(读取),PUT(更新)和DELETE(删除)。 对于每个活动,它都提供了在调用服务方法之前和之后挂接的功能。 调用生命周期为:

  1. 构造一个包含URL,参数和数据格式元数据的标准Dojo XHR调用结构。
  2. 调用该方法的参数转换器。 此方法可以更改调用结构(包括路径),并且可以用于转换调用结构以符合REST服务的期望。
  3. 通过将内容节点转换为JSON表示,填充调用结构的putData / postData / deleteData / getData节点。
  4. 使用更改后的XHR调用结构调用XHR方法。
  5. 将结果转换器添加到XHR回调中。 此方法可以更改结果的数据结构。 使用它可以将结果转换为JsonRestStore期望的结构。

清单1显示了示例代码。

清单1. EasyRestService源代码源
dojo.provide("com.ibm.developerworks.EasyRestService");

(function() {
  var pa = com.ibm.developerworks.EasyRestService = function (path, serviceImpl, schema) {
    // Enforce the dojox.rpc.Rest trailing slash functionality
    path = path.match(/\/$/) ? path : (path + '/');
    
    // A dojox.rpc.Service implementation is a function with 3 function members
    var service;
    // GET function
    service = function(id, args) {
      return _execXhr("get", id, args);
    };
    // POST function member
    service['post'] = function(id, value) {
      return _execXhr("post", id, value);
    };
    // PUT function member
    service['put'] = function(id, value) {
      return _execXhr("put", id, value);
    };
    // DELETE function member
    service['delete'] = function(id) {
      return _execXhr("delete", id);
    };
    
    // Generic XHR function for all methods
    var _execXhr = function(method, id, content) {
      // Transform the method string
      var methodCapitalised = method.substring(0,1).toUpperCase() 
        + method.substring(1).toLowerCase();
      var methodUpperCase = method.toUpperCase();
      var methodLowerCase = method.toLowerCase();
      
      // Get the transformer functions
      var argumentsTransformer = service["transform" + methodCapitalised + "Arguments"];
      var resultTransformer = service["transform" + methodCapitalised + "Results"];
      
      // Construct the standard query
      var serviceArgs = {
        url : path + (dojo.isObject(id) ? '?' + dojo.objectToQuery(id) : 
          (id == null ? "" : id)), 
        handleAs : "json",
        contentType : "application/json",
        sync : false,
        headers : { Accept : "application/json,application/javascript" }
      };
      
      // Transform the arguments
      // NOTE: argumentsTransformer has a reference to "service"
      serviceArgs = argumentsTransformer(serviceArgs, arguments);

      // Copy the content into the appropriate *Data arg
      // getData, putData, postData, deleteData
      // NOTE: If you want your arguments transformer to edit the *Data arg directly, 
      // move the arguments transformer invocation to after this call 
      serviceArgs[methodLowerCase + 'Data'] = content;
            
      // Kick off the call
      var xhrFunction = dojo['xhr' + methodCapitalised];
      var deferred = xhrFunction(serviceArgs);
      // Add our result transformer
      // NOTE: resultTransformer has a reference to "service" too
      deferred.addCallback(dojo.partial(resultTransformer, deferred));
      
      return deferred;
    };

    // Mix in the service hooks
    // Uses a "default" implementation that does nothing
    // Service hooks will have a reference to the "service" object in their context
    dojo.mixin(service, 
      new com.ibm.developerworks.EasyRestService.DefaultHooks(), 
      serviceImpl);
    
    // Now remove any default _constructor() methods
    // This is necessary as the JsonRestStore stack uses _constructor() differently
    delete service['_constructor'];
    // Remove the declaredClass member if it has been added
    delete service['declaredClass'];
    
    // Save the path away
    service.servicePath = path;
    // Save the schema
    service._schema = schema;
    
    return service;
  };
})();

dojo.declare("com.ibm.developerworks.EasyRestService.DefaultHooks", null, {
  transformGetArguments: function(serviceArgs) {
    // Alter serviceArgs to provide the information the backend
    // service requires
    return serviceArgs;
  },
  transformPutArguments: function(serviceArgs) {
    // Alter serviceArgs to provide the information the backend
    // service requires
    return serviceArgs;
  },
  transformPostArguments: function(serviceArgs) {
    // Alter serviceArgs to provide the information the backend
    // service requires
    return serviceArgs;
  },
  transformDeleteArguments: function(serviceArgs) {
    // Alter serviceArgs to provide the information the backend
    // service requires
    return serviceArgs;
  },
  transformGetResults: function(deferred, results) {
    /*
     * JsonRestStore expects the following format:
     * [
     *  { id: "1", ... },
     *  { id: "2", ... },
     *  ...
     * ] 
     */
    return results;
  },
  transformPutResults: function(deferred, results) {
    /*
     * JsonRestStore does not expect any specific content here
     */
    return results;
  },
  transformPostResults: function(deferred, results) {
    /*
     * JsonRestStore expects:
     * 1) A "Location" response header with location of the new item.
     * 		From the Dojo API:
     * 			The server’s response includes a Location header
     * 			that indicates the id of the newly created object.
     * 			This id will be used for subsequent PUT and DELETE 
     * 			requests. JsonRestStore also includes a 
     * 			Content-Location header that indicates the temporary
     * 			randomly generated id used by client, and this 
     * 			location is used for subsequent PUT/DELETEs if no 
     * 			Location header is provided by the server or if 
     * 			a modification is sent prior to receiving a response 
     * 			from the server.
     *    NB: There is no JS method for altering response headers.  
     *      You might wish to try overriding the 
     *      deferred.ioArgs.xhr.getResponseHeader() method with your
     *      own implementation.
     * 2) The new item in the following format:
     * { id: "1", ... }
     */
    return results;
  },
  transformDeleteResults: function(deferred, results) {
    /*
     * JsonRestStore does not expect any specific content here
     */
    return results;
  }
});

清单1中的代码复制了dojox.rpc.Rest的默认功能。 它可以与JsonRestStore一起使用,如清单2所示。

清单2. EasyRestService和JsonRestStore的默认用法
dojo.require("com.ibm.developerworks.EasyRestService");
dojo.require("dojox.data.JsonRestStore");

var store = new dojox.data.JsonRestStore({
  service: new com.ibm.developerworks.EasyRestService("https://mydomain.com/restservice"),
  idAttribute : "id"
});

默认情况下, EasyRestService实例不会以任何方式更改参数和结果。 EasyRestService无需更改DefaultHooks即可执行所需的参数和结果转换, EasyRestService提供了一种基于每个实例覆盖这些转换器的机制。

自定义EasyRestService

EasyRestService为提供自定义转换EasyRestService提供了一种简单的机制。 清单3中的示例更改了EasyRestService的行为,以便在执行之前记录GET调用结构。

清单3.自定义EasyRestService
dojo.require("com.ibm.developerworks.EasyRestService");

var transformers = { 
  transformGetArguments: function(args) { 
    console.log(args); 
    return args; 
  }
};
var service = new com.ibm.developerworks.EasyRestService(
  "https://mydomain.com/restservice", transformers);

同样,可以基于实例覆盖DefaultHooks所有转换器。

创建两个EasyRestService实例:一个用于合规服务,一个用于非合规服务。 该示例将它们用作JsonRestStore的两个实例的服务提供者,并针对商店发出基本访存。

数据存储

清单4清单5中 ,使用两个包含JSON结构的只读文件来模拟服务。

清单4.兼容的REST服务,ComplianceService.json
[
	{ id: 1, name: "Phil" },
	{ id: 2, name: "John" }
]
清单5.不合规的REST服务noncompatibleService.json
{ items : [
	{ id: 1, name: "Phil" },
	{ id: 2, name: "John" }
] }

商店和服务交互代码

JavaScript将使用清单6中的代码实例化并查询商店。

清单6.与商店交互JavaScript代码
// Create a store using a service that needs no transformations
compliantStore = new dojox.data.JsonRestStore({
  service : new com.ibm.developerworks.EasyRestService(
      "./compliantService.json"),
  idAttribute : "id"
});

// Cause an async fetch from the compliant service
dojo.create("p", {
  innerHTML : "Requesting from compliant service"
}, dojo.body(), "last");
compliantStore.fetch({
  onComplete : function(items, request) {
    console.log(items);
    // Log the number of items fetched
    dojo.create("p", {
      innerHTML : "Got " + items.length + " items from compliant service."
    }, dojo.body(), "last");
  }
});

// Create a store using a service which needs transformations
// to interpret the results
noncompliantStore = new dojox.data.JsonRestStore({
  service : new com.ibm.developerworks.EasyRestService(
      "./noncompliantService.json", {
        transformGetResults : function(deferred, results) {
          // This store wraps its results in an items object
          // so return the items object
          return results.items;
        }
      }),
  idAttribute : "id"
});

// Cause an async fetch from the noncompliant service
dojo.create("p", {
  innerHTML : "Requesting from noncompliant service"
}, dojo.body(), "last");
noncompliantStore.fetch({
  onComplete : function(items, request) {
    console.log(items);
 	// Log the number of items fetched
    dojo.create("p", {
      innerHTML : "Got " + items.length
          + " items from noncompliant service."
    }, dojo.body(), "last");
  }
});

摘要

在本文中,您学习了如何将自己的REST服务连接到JsonRestStore。 这些示例展示了一种转换服务接口以提供JsonRestStore所需签名的简单方法。 有关JsonRestStore期望的完整数据结构的信息,您应该参考DefaultHooks,DojoCampus的JsonRestStore文档和API文档中的注释。

有关JsonRestStore期望的完整数据结构的信息,请参阅“ 相关主题”部分。


翻译自: https://www.ibm.com/developerworks/java/library/wa-jsonreststore/index.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值