dojo的使用

    技术2024-03-28  90

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

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

    JsonRestStore是一个数据存储,通过使用GET,PUT,POST和DELETE命令与服务器进行HTTP / REST交互,通过标准提供了完整的读取,写入和通知功能。 它使您可以使用带有JavaScript的Dojo Data API与服务器端数据库/永久数据存储进行通信,并有效地处理创建,读取,更新和删除(CRUD)操作。

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

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

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

    服务实施示例

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

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

    Processed: 0.015, SQL: 9