如何结合Dojo和JAX-RS创建RESTful服务?

日期: 2010-10-11 作者:Kevin Haverlock 来源:TechTarget中国 英文

  在客户端和服务器端的简易实现

  最新版本的IBM? WebSphere? Application Server Feature Pack for Web 2.0,为您创建Ajax样式架构提供一个端到端的解决方案。在客户端,功能部件包提供开源Dojo JavaScript工具箱。在最新版的功能部件包中JAX-RS (基于Apache Wink项目)提供服务器端库,可用来实现连接Dojo的RESTful服务。

  除了广泛的用户界面小部件外,Dojo还提供了丰富的数据服务API,可轻松地连接服务器端Web服务。Dojo数据API从显示用户界面的小部件中抽象出惟一数据格式概念。Dojo数据提供基本数据存储用来读取JSON数据,还有一些其他的格式,例如XMLStore、CsvStore等等。如果您使用Dojo的树型小部件,那么您就可以选择您想要使用的数据存储,并且数据存储负责树型小部件数据处理服务。

  Dojo的数据存储很容易连接到RESTful服务,RESTful服务中引入JAX-RS。JAX-RS的Apache Wink实现使创建您自己定制的Web服务变得很容易。因此如果您想,也就是说使用Dojo的树型小部件来描述文件系统的表示形式,那您需要实现协议Dojo用法来描述文件系统的表示形式。Dojo为您提供客户端服务时,您也需要写入服务器端实现中。JAX-RS 有助于服务器实现变得简单易懂。

  一个示例

  让我们用一个示例来说明。图 1 展示了客户端和服务器端的交互。在这个例子中,您可以以目录格式显示初始FIFA World Cup Soccer球队。您可以在服务器端采用目录结构,在客户端创建一个树型表示。在左边,diji.Tree是用来显示包含在服务器中的目录信息的Dojo UI小部件。Dijit.Tree依赖dijt.tree.ForestStoreModel和dojox.data.FileStore。dijit.tree.ForestStoreModel是从dojox.data.FileStore返回的数据之间的一个映射层。ForestStoreModel负责创建一个含有目录清单虚拟根节点的“Files”,并负责将所有内容放入根节点下。dojox.data.FileStore负责打开服务器端的采用JAX-RS实现的RESTful服务连接。

  服务器端运行一个RESTful服务,实现rest/filestore/filelist请求。JAX-RS服务从dojox.data.FilesStore读取HTTP GET请求并将数据以JSON格式返回dojo.data.FileStore。数据返回的格式是JSON,dojox.data.FileStore支持此格式。

图 1. 服务器端和客户端的RESTful交互

图 1. 服务器端和客户端的RESTful交互

  我们来看看服务器端返回的JSON数据属性。在图 1 中,服务器返回的JSON数据格式如下:

  •   path表示当前路径。
  •   modified含有关于何时进行最后一次目录修改的数据。
  •   size表示文件系统上目录的大小。
  •   name是显示的目录名。
  •   children是一个JSON阵列,还有当前目录的子目录名。

  值得一提的是在这个实例中使用了一个惰性加载模型。惰性加载意味着只有用户目前正在导航的目录被返回。惰性加载是更高效的,因为您只请求需要被显示的数据。

  客户端实现

  进一步了解这个实现设计,清单 1 显示了一个使用Dojo的HTML页面的部分客户端代码清单。这段代码使用了3个Dojo提供的JavaScript类:dijit.Tree、dijit.tree.ForestStoreModel和dojox.data.FileStore。

  清单 1
    

以下是引用片段:
<body class=”soria”>
  <div dojoType=”dojox.data.FileStore” jsId=”countryStore”   
       url=”rest/filestore/filelist” pathAsQueryParam=”true”></div>
  <div dojoType=”dijit.tree.ForestStoreModel” jsId=”countryModel”     
       store=”countryStore” rootId=”myfiles” rootLabel=”Files”  
       childrenAttrs=”children”>
  </div>
  <div dojoType=”dijit.Tree” id=”mytree” model=”countryModel” ></div>
  </body> 

  上述代码中,dojox.data.FileStore提供了一个从文件系统中读取文件信息的轻量级JavaScript实现。该实现提供一些信息,例如文件大小、最后一次修改数据,如果输入是一个目录,那么还有其子目录。dojox.data.FileStore的URL参数是其余服务的位置。pathAsQueryParam参数使您既可以提供一个含有文件或目录路径的 URL 查询参数,也可以包含路径作为 URL 请求的一部分(如果这个值被设为false)。

  清单 1 中的dijit.tree.ForestStoreModel将一个根节点和diji.tree中的多个根条目连接起来。例如, dijit.tree.ForestStoreModel使您可以在另一个根节点“Files”中显示目录,如图 1 所示。dijit.tree.ForrestStoreModel提供参数来设置rootId,可用来查询您 JavaScript 代码中的根节点。此外,rootLabel可以设置成包含应该被显示的文本标签。childrenAttrs参数指定应该被命名的子条目属性。如果您从图 1 中重新调用,JSON数据包含一个子条目阵列。childrenAttrs参数给您提供如何命名属性的灵活性。

  最后,dijit.Tree是将要显示树的UI小部件。这个参数包括模型名以及树的JavaScript ID。

  服务器端实现

  浏览器客户端实现已完成,让我们来看看一个JAX-RS后端实现的示例。dojox.data.FileStore有一个协议实现,使数据源存储可以理解从服务器收到的JSON内容。除了JAX-RS,您也可以使用一个Web 2.0功能部件包提供的帮助程序实用工具库JSON4J。JSON4J库提供一组易于构造JSON数据格式的类。

  我们来看WorldCupGroup类,它有两个方法,见清单 3。JAX-RS使用注释来减少样板文件代码并提供一个简要的注释。清单 2 显示了这个类定义。

  清单 2
    

以下是引用片段:
 @Path(“/filestore”)
public class WorldCupGroup { … }  

  清单 3

以下是引用片段:
@GET 
@Path(“filelist”)
@Produces(MediaType.APPLICATION_JSON) 
// returns a list of files in JSON format that match the request  
public JSONObject getFileList(@QueryParam(“path”) String path) { 

  在这个例子中,@Path值与URI路径有关。例如,在RESTful服务请求(在清单 3 中定义的)/rest/filestore/filelist,/filestore/表示到RESTful服务的PATH URI。

  清单 3 中定义了您的RESTful服务调用的方法。@GET 定义了HTTP GET方法,@PATH进一步细化URI使其更具体;在此例中是 /rest/filestore/filelist。@Produces定义了将要返回的MIME媒体类型:在本例中,该方法返回转换成一个MIME类型的应用程序/json的 JSON 数据,这就是Dojo的dojo.data.FileStore所预期的。@QueryParam是JAX-RS用来通知要传递给getFileList方法的查询参数值。例如,在清单 4 中的HTTP GET请求中,@QueryParam (“path”) 值是 C://artifactstore//FIFA World Cup Group。

  清单 4
    

以下是引用片段:
GET http://localhost:8080/rest/filestore/filelist?path=C://artifactstore//FIFA World 
Cup Group 

  代码的另一部分包含构造描述文件系统的JSON数据流的信息。例如,createFileItem方法从文件系统中读取信息,然后构造一个稍后返回dojox.data.FileStore的JSON对象。清单 5 显示了完整的服务器端实现代码。

  清单 5
    

以下是引用片段:
package com.example.filestore;
import java.io.File;
import java.io.IOException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import com.ibm.json.java.JSONArray;
import com.ibm.json.java.JSONObject;
@Path(“/filestore”)
public class FIFAWorldCup {   
  public static final String ROOT_DIR = “C:\artifactstore\”; 
 
  // returns a list of files in JSON format that match the request 
  @GET 
  @Path(“filelist”)
  @Produces(MediaType.APPLICATION_JSON)   
  public JSONObject getFileList(@QueryParam(“path”) String path) {
    
    JSONObject ret     = new JSONObject();
    JSONArray filelist = new JSONArray();
    JSONObject items   = new JSONObject();
    
    if (path == null) {
      path=this.ROOT_DIR;
    }
     
   /** Method to construct a JSONObject representing the File 
    *  as a DataStore item.
    *
    * @param file The file contained within rootDir to reference.
    *
    * @return JSONObject of the file, or null if file was null or not 
    * contained within the root path of the FileStore.
    */
   private JSONObject createFileItem(String parent,File file) throws
                                                       IOException {
    JSONObject item = new JSONObject();
    if (parent != null && file != null) {           
      String filePath = file.getAbsolutePath();
           
      //Make sure the request is contained within the root directory           
      if (filePath.startsWith(this.ROOT_DIR)){
        item.put(“name”, file.getName());
        item.put(“modified”, new Long(file.lastModified()));
        item.put(“size”, new Long(file.length()));
        item.put(“path”, filePath);
        item.put(“directory”, new Boolean(file.isDirectory())); 
        // if this is a directory, then add the children
        if (file.isDirectory()) {                
          File[] child = file.listFiles();                    
          JSONArray children = new JSONArray();
          if (child.length > 0) {  
            for (int j = 0; j < child.length; j++) {                
              children.add(child[j].getName());                         
              item.put(“children”, children);
            }
          }      
          else { 
           // since this directory has no children, place an empty child
           item.put(“children”,children);
          }
        }
      }
    }
    return item;
   }
} // end of class definition 

  结束语

  最新版本的IBM WebSphere Application Server Feature Pack for Web 2.0提供了创建端到端的RESTful服务所需的库。在客户端,您有一个由Dojo组成的功能强大的开源JavaScript工具箱。对于服务器端实现,您有基于Apache Wink项目的JAX-RS库。文中给出的代码表示一个简单样例后端实现dojox.data.FileStore。此外,协议实现可以被添加,例如查询和对于您的数据可能是惟一的用户定义选项。

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

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

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

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • JSON如何开发API?

    随着开发者遭遇像企业之间业务对业务连接这类的应用对应用问题,他们的第一反应往往是,“这里为什么我们不能用一个API就行了呢?”

  • 控制状态下为何对比REST友好与REST架构

    要想控制住云中状态,架构师应该先实现一种REST友好界面,而不是考虑设计出一种REST架构模型。

  • API设计如龙生九子 各不相同

    IT咨询管理公司CA Technologies对API产业做了个问卷调查,问卷内容涉及API设计风格以及管理部署的新动向。调查结果表明,JSON与XML可谓两分天下。

  • 八个超实用的jQuery技巧攻略

    jQuery是JavaScript最好的库之一,主要用于制作动画、事件处理,支持Ajax及HTML脚本客户端。文中分享了8个超实用的jQuery代码技巧攻略,希望你会喜欢。