用Ruby脚本在Project_Zero平台上构建Restful应用(二)

日期: 2009-06-21 作者:赵雄伟左超 来源:TechTarget中国 英文

  这里我们按照惯例将Ruby的事件响应函数名默认为:on+事件名,针对与Zero的Resources Event,有8个默认的事件响应函数:

  针对Collection资源的事件响应函数有:onList,onPutCollection,onCreate,onDeleteCollection

  针对Member资源的事件响应函数有:onRetrieve,onUpdate,onPostMember,onDelete

  在Ruby脚本中利用Zero提供的持久化机制对数据库进行操作

  Zero的Core API中提供了zero.data.Manager类封装了对数据库的访问操作,如对数据的增删改查的方法。要想在Ruby脚本中使用Zero平台提供的数据库访问能力,需要做一些改进。因为JRuby脚本编译后,脚本中的字符串类型会转化成RubyString类型,而zero.data.Manager并没有提供对RubyString的支持,所以需要提供一个代理类,将RubyString转化为Java的String类型。本文提供了一个zero.data.ruby.Manager类,部分代码如下:

  清单7:zero.data.ruby.Manager.java代码片段
 public class Manager {

 private zero.data.Manager manager;
 
 public static zero.data.ruby.Manager create(String dbKey) {
  Manager manager = new Manager();
  manager.manager = zero.data.Manager.create(dbKey);
  return manager;
 }
 
…………

 public Map<String, Object> queryFirst(RubyString sql) {
  String newSql = sql.toString();
  Map<String, Object> result = manager.queryFirst(newSql, null);
  return result;
 }

 public List<Map<String, Object>> queryList(RubyString sql) {
  String newSql = sql.toString();
 List<Map<String, Object>> result = manager.queryList(newSql, null);
  return result;
 }

………………
}
 
  将执行结果渲染到客户端

  Zero平台提供了两种方式来将执行结果渲染到客户端。一种是直接采用OutputStream或PrintWriter将结果写到HTTP response中,比如:

  清单8:Zero采用OutputStream向客户端发送HTTP response
 PrintWriter writer = (PrintWriter) zget(“/request/writer”);
 writer.println(“Hello World.”);
 
  另外一种就是利用Zero提供的ViewEngine API来创建不同形式的Response。目前提供了View,Error,JSON,XML四种renders。

  调用一个render需要以下步骤:

  ·指定相应的render,这个值在Global Context的“/request/view”项中设置
  ·把和render相关的数据设置到Global Context中
  ·调用ViewEngine.render()方法

  本文将采用JSON render将结果集以JSON的方式渲染到客户端。

  比如如下代码就是ViewEngine的基本调用方式。

  清单9:Zero采用ViewEngine向客户端发送HTTP response
GlobalContext.zput(“/request/view”,”JSON”)
 GlobalContext.zput(“/request/json/output”,result)
 ViewEngine.render()
 
  至此我们已经可以将RESTful HTTP URL映射到相应的Ruby脚本中,根据请求的事件映射到Ruby脚本的事件响应函数中,在Ruby的方法中使用Data Manager来访问数据库,使用ViewEngine将结果用多种形式返回给客户端。这样就完成了一个基本的RESTful Web服务的流程。

  示例场景:

  接下来我们通过一个简单的示例来展示上述对Zero的扩展如何应用到实际的工程中。示例的内容主要有:

  创建一个Zero应用程序,定义一个Customer资源,然后利用Ruby脚本为这个资源提供RESTful服务。

  创建一个示例应用

  实例具体的步骤如下:

  在数据库中创建Customer表,提供测试数据

  本示例中采用Zero自带的Derby数据库,数据库名为PRO_DB。示例的Customer表的SQL脚本如下:

  清单10:create.sql
 CREATE TABLE CUSTOMER (
   CUSTOMERID INTEGER NOT NULL GENERATED ALWAYS AS
    IDENTITY(START WITH 1, INCREMENT BY 1),
   FIRSTNAME VARCHAR(50) NOT NULL,
   LASTNAME VARCHAR(50) NOT NULL,
   COUNTRY VARCHAR(250),
   DESCRIPTION VARCHAR(250)
 )
 
 INSERT INTO CUSTOMER(FIRSTNAME,LASTNAME,COUNTRY,DESCRIPTION)
 VALUES (‘Simpson’,’Homer’,’USA’,’He is a Ruby Programmer’);
 
 INSERT INTO CUSTOMER(FIRSTNAME,LASTNAME,COUNTRY,DESCRIPTION)
 VALUES (‘Simpson’,’Maggie’,’USA’,’She is a Groovy Programmer’);
 
 INSERT INTO CUSTOMER(FIRSTNAME,LASTNAME,COUNTRY,DESCRIPTION)
 VALUES (‘Simpson’,’Bart’,’USA’,’He is a Java Programmer’);
 
 INSERT INTO CUSTOMER(FIRSTNAME,LASTNAME,COUNTRY,DESCRIPTION)
 VALUES (‘Simpson’,’Lisa’,’USA’,’She is a C++ Programmer’);
 
  配置Zero工程的Java Build Path

  本示例采用了JRuby作为Ruby的实现语言,利用Apache BSF脚本引擎在Java中调用JRuby脚本,所以需要在classpath中引入这两个jar文件。同时需要引入我们对Zero扩展的jar文件。本文对Project Zero所做的扩展已经打包成jar文件,可以从文后的附件中获得。Java Build Path配置如下:

                 

  图3. 示例程序的Java Build Path配置
 
  配置zero.config

  在工程的config/zero.config文件中添加使Zero支持Ruby脚本的配置

  清单11:示例程序的config/zero.config配置文件
# HTTP port (default is 8080)
/config/http/port = 8080

/config/db/PRO_DB = {
“class”: “org.apache.derby.jdbc.EmbeddedDataSource”,
“databaseName”: “PRO_DB”,
“user”: “APP”,
“password”: “APP”
}

/config/resources/defaultExtensions = [“.rb”]
/config/interpreters/.rb = “zero.extend.ruby.JRubyRestfulInterpreter”
 
  实现customer.rb脚本

  customer.rb需要写事件响应函数,来处理Zero内部定义的Resource事件。本例展示了如何获得Collection和Member资源。

  onList方法来处理如下的HTTP URL:http://localhost:8080/resources/customer,响应GET customer collection的事件。

  onRetrieve方法来处理如下的HTTP URL:http://localhost:8080/resources/customer/1,响应GET customer member的事件。

  清单12:customer.rb脚本
require “java”
include_class “zero.data.ruby.Manager”
include_class “zero.core.context.GlobalContext”
include_class “zero.core.views.ViewEngine”
include_class “zero.json.Json”
class Customer 
 def onRetrieve
  data = Manager.create(‘PRO_DB’);
  id = GlobalContext.zget(“/request/params/customerId”)
  result = data.queryFirst(“select c.customerId,c.firstname,c.lastname,
     c.description
  from customer as c where c.customerId = #{id}”);
  
  if(result)
    GlobalContext.zput(“/request/view”,”JSON”)
    GlobalContext.zput(“/request/json/output”,result)
    ViewEngine.render()
  else
   GlobalContext.zput(“/request/view”,”error”)
   GlobalContext.zput(“/request/status”,”404″)
   GlobalContext.zput(“/request/error/message”,”No Result Found”)
   ViewEngine.render()    
  end
 end
 
 def onList
  data = Manager.create(‘PRO_DB’)
  result = data.queryList(“select * from customer”)
  
  if(result)
    GlobalContext.zput(“/request/view”,”JSON”)
    GlobalContext.zput(“/request/json/output”,result)
    ViewEngine.render()
  else
   GlobalContext.zput(“/request/view”,”error”)
   GlobalContext.zput(“/request/status”,”404″)
   GlobalContext.zput(“/request/error/message”,”No Result Found”)
   ViewEngine.render()    
  end
 end

………………
end
 
  在customer.rb中可以从GlobalContext中获得request的参数,可以调用zero.extend.data.Manager来访问数据库,可以调用Zero的ViewEengine将Json对象返回到客户端。

  执行结果

  采用Firefox的Poster插件,可以模拟HTTP的访问,本文的测试基于Poster插件,更多关于Poster的内容可以参考文后的资料。

  访问Customer Collection资源:http://localhost:8080/resources/customer

                  

  图4. 用Poster插件向服务器发送http://localhost:8080/resources/customer请求
 
  返回结果:

  图5. 服务器针对http://localhost:8080/resources/customer请求返回的response信息,返回的是一个JSON对象的数组
 
  访问一个Customer member资源:http://localhost:8080/resources/customer/1

             

  图6. 用Poster插件向服务器发送http://localhost:8080/resources/customer/1请求
 
  返回结果:

                

  图7. 服务器针对http://localhost:8080/resources/customer/1请求返回的response信息,返回的是一个JSON对象。
 
  结束语:

  本文介绍了RESTful服务的基本概念,Project Zero提供RESTful服务时内部的事件流,以及如何在Project Zero进行扩展使其支持用Ruby脚本编写的RESTful服务,并结合一个简单的示例展示了如何利用我们提供的Zero扩展用Ruby脚本开发Zero的RESTful服务。您还了解到了如何利用BSF脚本引擎在Java中调用Ruby脚本。

  作者简介

  赵雄伟是一位IBM软件工程师,工作在IBM中国软件开发实验室企业应用开发部门,现在正从事企业电子商务应用的开发和支持工作,在Java开发和Web开发方面有丰富的经验,特别对Web应用的架构及SOA、SCA等有浓厚的兴趣,您可以通过zhaoxw@cn.ibm.com与他联系。
 
  左超是一位IBM软件工程师,工作在IBM中国软件开发实验室企业应用开发部门,目前从事企业电子商务应用的开发,您可以通过zuochao@cn.ibm.com与他联系。

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

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

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

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐