• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

用 Ruby on Rails 和 Action Web Service 创建 Web 服务

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

Action Web Service 模块将在 Ruby on Rails 中实现 Web 服务功能。Action Web Service 将创建 SOAP 和 XML-RPC Web 服务协议的服务器端支持。您可以声明和发布使用 Action Web Service 的 API。

Rails 是一种 Web 应用程序框架,其中包含使用模型-视图-控制器(Model-View-Control,MVC)模式创建以数据库为后端的 Web 应用程序所需的所有内容。Action Web Service 的最简洁定义可以在其 README 文件中找到:“Action Web Service 提供了一种用 Rails 发布可互操作的 Web 服务 API 而无需花费大量时间研究协议细节的方法”。在本文中,您将了解如何安装 Rails 及 Action Web Service 模块并且开始进行 XML-RPC 编程。

硬件和软件要求

任何连接到网络并能够运行 Ruby 的计算机都应当有足够能力处理本文中提供的代码。必须拥有 Ruby V1.86 或更高版本,以及 RubyGems 和 Rails。我们将讨论如何在运行 Microsoft® Windows® 的计算机中安装这些软件。

Web 服务的工作原理

常用缩写词
  • API — 应用程序编程接口
  • HTML — 超文本标记语言
  • HTTP — 超文本传输协议
  • REST — 具象状态传输
  • RHTML — 与 HTML 模板混合的 Ruby 代码
  • SOAP — 简单对象访问协议
  • UI — 用户界面
  • WSDL — Web 服务描述语言
  • XML — 可扩展标记语言
  • XML-RPC — 使用 HTTP 和 XML 的远程过程调用

Web 服务 是专门为基于网络进行可互操作交互而设计的软件系统。Web 服务是用 WSDL 文档定义的。其他系统将使用 SOAP 消息与 Web 服务交互,使用带有 XML 序列化的 HTTP 传输。Web 服务是一种抽象资源,它可以提供一组功能,通过代理实现,可以发送和接收消息。提供商实体 通过提供商代理提供 Web 服务的功能。请求者实体将用请求者代理使用 Web 服务的功能。

Web 服务将实现各种技术,包括 XML、SOAP 和 WSDL。XML 是标准的数据交换格式。Web 服务请求和响应都是作为 XML 消息发送的。在 XML 文档中指定的元素和属性都是遵循 XML 模式指定的。SOAP 提供了封装和交换 XML 消息的标准框架。WSDL 是可以在 http://schemas.xmlsoap.org/wsdl/ 中找到的 XML 文档,该文档用于定义把 Web 服务描述为一组针对消息执行的端点的名称空间。WSDL 文档将指定 Web 服务提供的操作(方法)及 XML 消息的格式。





创建 Web 服务

在详细讨论 Ruby on Rails 中的 Web 服务支持之前,我们将使用 Action Web Service 模块创建一项简单的 Web 服务。首先,我们将在 Windows 计算机中安装 Ruby。下面列出的步骤非常简要并且十分简单(要下载 Ruby 和 Ruby on Rails,或者要获得介绍如何使用 Ruby on Rails 的其他 developerWorks 文章,请参阅 参考资料):

  1. 对于 Windows 用户,下载 Ruby Windows 安装程序的最新的正式版(目前为 Ruby V1.8.6-25),然后双击可执行文件。在 C:/ruby 目录中安装 Ruby,同时也安装了用于安装其他 gem 的标准 Ruby 包管理器 RubyGems。接下来,安装 Rails。在 Ruby 的安装目录 C:/ruby 目录中,运行以下命令安装 Rails 及依赖关系:c:/ruby>gem install rails --include-dependencies。
  2. 在 Rails 2.0 版本中,默认包中不包括 Action Web Service gem。用以下命令安装 actionwebservice gem:c:/ruby>gem install actionwebservice。在撰写本文时,actionwebservice V1.2.6 是最新版本。如果使用较早版本的 Rails(早于 Rails V2.0),则默认包中包括 actionwebservice gem。
  3. 输入 C:/ruby>rails webservice 以创建 Web 服务的 Rails 应用程序。
  4. 在 app 目录中创建 apis 目录,然后创建 Web 服务 API 类 HelloMessageApi,该类将用于扩展 ActionWebService::API::Base 类。将以下 Ruby 脚本保存到 app/apis 目录的 hello_message_api.rb 中。

    清单 1. Web 服务 API 类 HelloMessageApi
    						
    class HelloMessageApi < ActionWebService::API::Base
      api_method :hello_message, :expects => [{:firstname=>:string}, 
    {:lastname=>:string}], :returns => [:string]
    
    
    end
    

  5. 创建一个控制器脚本,它将定义控制器类:HelloMessageController。将以下 Ruby 代码复制到控制器脚本中,然后将控制器脚本 hello_message_controller.rb 保存到 app/controllers 目录中。

    清单 2. 控制器类 HelloMessageController
    						
    class HelloMessageController < ApplicationController
     
    web_service_api HelloMessageApi
     web_service_dispatching_mode :direct
      wsdl_service_name 'hello_message'
      web_service_scaffold :invoke
    
      def hello_message(firstname, lastname)
        return "Hello "+ firstname +" "+lastname
      end
    end

  6. 输入 C:/ruby/webservice>ruby script/server 以启动 WEBrick Web 服务器。
  7. 用 URL http://localhost:3000/hello_message/wsdl 显示 Web 服务的 WSDL 文件。

    图 1. Web 服务 WSDL


  8. 用 http://localhost:3000/hello_message/invoke 调用 Web 服务。将显示 Web 服务的 API 方法。选择 HelloMessage 方法。

    图 2. 调用 Web 服务


  9. 要测试 Web 服务,请指定名字和姓氏,然后单击 Invoke。

    图 3. 调用 Web 服务方法


  10. 将输出返回值以及请求 XML 和响应 XML。

图 4. Web 服务的输出


让我们详细讨论 Web 服务。Web 服务 API 类将定义 Web 服务提供的方法。示例 API 类将定义 hello_message 方法,该方法将获取 string 类型的两个参数并返回字符串值。API 方法是用 ActionWebService::API::Base 类的 api_method 方法定义的。Web 服务的 WSDL 是从 API 类创建的。Web 服务 API 类将扩展 ActionWebService::API::Base 类。该控制器类包含可用于客户机的 Web 服务代码。web_service_api 选项将指定 API 定义类。web_service_dispatching_mode 选项将指定调度方法,其中远程调用程序将发送调用方法、端点 URL,以及指定如何将方法调用路由到实现方法的对象。

使用直接 调度模式,直接对控制器进行方法调用。API 方法实现是作为公共实例方法定义在控制器类中的。默认模式是直接模式。wsdl_service_name 选项将指定 Web 服务名称。web_service_scaffold 选项将生成方法调用的 Web 服务 scaffolding。Web 服务 scaffolding 类似于 Active Record 的 scaffolding。示例 Web 服务中指定的调用方法将列出与控制器关联的所有 API 中的所有方法。控制器类中的 hello_message 操作可用于客户机进行方法调用。





Web 服务 API 类

在上例中,Web 服务 API 类为 HelloMessageApi。Web 服务 API 类将扩展 ActionWebService::API::Base 类并将方法指定为可用于 Web 服务中的 API。下面讨论了该类中的一些方法。


表 1. ActionWebService::API::Base 方法
Method Description
api_method(name, options={}) 指定 API 方法;选项包括 :expects-Signature(用于方法输入参数)、:returns-Signature(用于返回值)、:expects_and_returns-Signature(用于输入参数和返回值)
api_method_name(public_name) 为公共方法名称指定服务方法名称
api_methods() 在此 API 上指定服务方法散列
has_public_api_method?(public_name) 指定此 API 中的公共方法是否拥有相应的服务方法
soap_client(endpoint_uri, options={}) 指定 SOAP 客户机
xmlrpc_client(endpoint_uri, options={}) 指定 XML RPC 客户机

定义 API 类的过程如下:

  1. 确定哪些方法可用于 API。
  2. 创建扩展 ActionWebService::API::Base 类的类。
  3. 使用 api_method 选项定义包括方法签名的方法。




调度

调度 是在 Web 服务中分配方法调用。调度方法将引用远程调用程序发送调用消息的位置,以及如何将方法调用路由到方法实现对象中。API 是基于调度方法实现的。有三种调度方法可用:

  1. 直接调度(Direct)
  2. 委托调度(Delegated)
  3. 分层调度(Layered)

直接调度

通过直接调度 方法,可以把 API 定义类与控制器类绑定在一起,并且在控制器类中实现作为公共实例方法的 API 方法。在前面讨论的示例应用程序中,直接调度被指定为 web_service_dispatching_mode :direct。

默认方法是直接调度方法。通过直接调度方法,控制器类只能实现一个 API。采用直接调度的 Web 服务的端点 URL 使用 http://SERVER/CONTROLLER_NAME/api 格式。

前面讨论的示例 Web 服务的端点 URL 为 http://localhost:3000/hello_message/api,它是在 WSDL 文档的服务元素中指定的。


清单 3. 端点 URL
				
<service name="hello_messageService">
 <port name="hello_messageHelloMessagePort" 
  binding="typens:hello_messageHelloMessageBinding">
  <soap:address location=
   "http://localhost:3000/hello_message/api" />
  </port>
  </service>

在直接调度模式下,如果 API 定义类与控制器类同名并且存储在 apiclass_api.rb 格式的 Ruby 文件的 app/apis 目录中,则可以省略 web_service_api 选项。在前面讨论的示例应用程序中,控制器类中不要求有 web_service_api 选项,因为 API 类存储在 hello_message_api.rb 中。使用直接调度方法开发 Action Web Service Web 服务的过程如下:

  1. 定义扩展 ActionWebService::Base 类的 API 类,然后定义 API 方法。
  2. 使用 web_service_api 选项将 API Web 服务类与控制器类绑定在一起。
  3. 用 web_service_dispatching_mode :direct 将调度模式设为 “direct”。
  4. 在控制器类中实现作为公共实例方法的 API 方法。
  5. 通过向控制器类中添加 scaffolding 来测试 Web 服务。

委托调度

direct 调度方法的限制是控制器类只能实现一个 API。在委托调度 方法中,控制器类可以实现多个 API。我们应当用示例讨论 delegated 调度。

定义两个 API 类:HelloMessageApi 和 DeveloperApi。把 HelloMessageApi 类存储到 app/apis 目录的 hello_message_api.rb Ruby 脚本中。HelloMessageApi 类将定义 hello_message API 方法,该方法将获取两个字符串参数,名字和姓氏,并返回字符串值。hello_message_api.rb 脚本如下所示:


清单 4. hello_message_api.rb
				
class HelloMessageApi < ActionWebService::API::Base
  api_method :hello_message, :expects => 
  [{:firstname=>:string}, 
  {:lastname=>:string}], :returns => [:string]

end

将 DeveloperApi 类存储在 app/apis 目录的 developer_api.rb Ruby 脚本中。DeveloperApi 类将定义获取两个字符串参数并返回字符串值的 developer 方法。developer_api.rb 脚本如下所示:


清单 5. developer_api.rb
				
class DeveloperApi < ActionWebService::API::Base
  api_method :developer, :expects => 
  [{:firstname=>:string}, 
{:lastname=>:string}], :returns => [:string]

end

创建所有 API 类的服务类。服务类将扩展 ActionWebService::Base 类。该服务类将实现 API 类中定义的方法。该 API 类是使用 web_service_api 选项与服务类绑定在一起的。HelloMessageService 类将实现 HelloMessageApi API 类。将 HelloMessageService 服务类存储为 app/models 目录中的 Ruby 脚本 hello_message_service.rb。hello_message_service.rb 脚本如下所示:


清单 6. hello_message_service.rb
				
class HelloMessageService < ActionWebService::Base
 web_service_api HelloMessageApi

def hello_message(firstname, lastname)
    return "Hello "+ firstname +" "+lastname
  end
end

同样地,创建 DeveloperApi API 类的服务类 DeveloperService。DeveloperService 类的 Ruby 脚本是作为 developer_service.rb 存储在 app/models 目录中。developer_service.rb 脚本如下所示:


清单 7. developer_service.rb
				
class DeveloperService < ActionWebService::Base
 web_service_api DeveloperApi

def developer(firstname, lastname)
    return "This Web service is developed by "+ firstname +" 
    "+lastname
  end
end

创建服务类的控制器类。用以下选项设置将调度模式设为 “delegated”:web_service_dispatching_mode :delegated。使用 web_service 选项将服务类与控制器类绑定在一起。例如,用以下声明将 HelloMessageService 类与控制器类绑定在一起:web_service :hello_message, HelloMessageService.new。

Hello_message 是表示 HelloMessageService 类的 Web 服务。要测试 Web 服务,请用 web_service_scaffold 选项 web_service_scaffold :invoke 向控制器类中添加 scaffolding。将控制器类存储在 app/controllers 目录中。控制器脚本 delegated_controller.rb 如下所示:


清单 8. delegated_controller.rb
				
class DelegatedController < ApplicationController
 web_service_dispatching_mode :delegated

 web_service :hello_message, HelloMessageService.new
 web_service :developer, DeveloperService.new
 web_service_scaffold :invoke
end

该控制器类不必命名为 DelegatedController。接下来,我们将测试 Web 服务。如果尚未启动,则启动 WEBrick Web 服务器:C:/ruby/helloservice>ruby script/server。用 URL http://localhost:3000/delegated/invoke 调用 Web 服务方法清单。在控制器类中指定的所有 API 服务类的 API 方法都将被列出。


图 5. 调用委托的 Web 服务


与直接调度方法相比,委托方法可以使用服务类将多个 API 类与控制器类绑定在一起。使用委托方法开发 Action Web Service Web 服务的过程如下:

  1. 将 API 类定义为通过 Web 服务实现。
  2. 给每个 API 类都创建一个扩展 ActionWebService::Base 类的服务类。用 web_service_api 选项将 API 类与服务类绑定在一起。
  3. 在服务类中实现作为公共实例方法的 API 方法。
  4. 创建一个控制器类并将调度模式设为 “delegated”。
  5. 用 web_service 选项将服务类与控制器类绑定在一起。
  6. 使用 web_service_scaffold 选项生成 Web 服务的 scaffolding 来测试 Web 服务。

分层调度

分层调度 方法的过程与委托调度方法十分相似,除了以下声明外:web_service_dispatching_mode :layered。每个方法调用是以服务名称为前缀的,格式为 servicename.methodname。还可以使用通过 web_service_scaffold 选项生成的 scaffolding 测试分层调度方法 Web 服务。





协议客户机

Action Web Service 将提供访问远程 Web 服务的一些客户机类。可以使用 web_client_api helper 函数从控制器内部访问远程 Web 服务,也可以使用 ActionWebService::Client::Soap 或 ActionWebService::Client::XmlRpc 类的实例直接访问远程 Web 服务。在本节中,我们将创建 Action Web Service Web 服务,并访问使用 web_client_api 函数的 Web 服务和直接实例方法调用。需要创建两个独立的 Rails 应用程序 — 一个用于 Web 服务,另一个用于客户机。通过输入 C:/ruby>rails helloservice 创建 Web 服务的 Rails 应用程序。

使用 web_service 脚本生成器创建带有 HelloApi API 类和 getMsg API 方法的 Hello Web 服务:

C:/ruby/helloservice>ruby script/generate web_service Hello getMsg

在 apis 目录中把 HelloApi API 类创建为 Ruby 脚本 hello_api.rb。在 controllers 目录中创建 hello_controller.rb 控制器脚本。HelloController 控制器类包括 getMsg 控制器动作。该控制器类还将指定 Web 服务名称 wsdl_service_name。Web 服务的 WSDL 在 Web 服务运行时可用。修改控制器脚本以指定 web_service_api 选项并用 web_service_scaffold 选项指定 scaffolding。web_service_api 选项将把控制器映射到 API 类中。修改 getMsg 控制器动作以获取字符串参数并返回字符串值。getMsg 方法将在 API 类中实现 getMsg 方法。修改后的控制器脚本如下所示:


清单 9. hello_controller.rb
				
class HelloController < ApplicationController
  wsdl_service_name 'Hello'

web_service_api HelloApi
web_service_scaffold :invoke


  def getMsg(name)
"Hello "+ name
 end
end

修改 HelloApi API 类以向 getMsg 方法签名中添加参数和返回值。HelloApi 类如下所示:


清单 10. HelloApi
				
class HelloApi < ActionWebService::API::Base
  api_method :getMsg, :expects => [:name=>:string], 
:returns => [:string]
end

接下来,我们将测试 Web 服务。用以下命令从 Web 服务目录中启动 Web 服务:C:/ruby>webservice>ruby script/server。使用 URL http://localhost:3000/hello/invoke 调用 Web 服务。该 Web 服务的 API 方法将被列出。单击 GetMsg 方法。


图 6. 调用 Web 服务 scaffolding


将显示名称的输入字段。您还可以选择协议:SOAP 或 XML RPC。在 Name 字段中指定一个值并单击 Invoke。


图 7. 调用 Web 服务方法


将用名称参数值 “Steve” 调用 getMsg Web 服务方法,并且输出返回值。此外,还显示请求 XML 和响应 XML 消息。


图 8. 从 Web 服务返回值


接下来,我们将使用 C:/ruby>rails helloadmin 创建客户机的 Rails 应用程序。在 helloadmin Rails 应用程序的 app 目录中创建 apis 目录,并将 hello_api.rb 脚本从 helloservice Rails 应用程序复制到 apis 目录中。创建 Web 服务客户机的控制器脚本:

C:/ruby/helloadmin>ruby script/generate controller helloadmin getMsg

将创建由 getMsg 控制器动作组成的 HelloadminController 控制器类。使用 web_client_api 函数从控制器类中访问 Web 服务 API:

web_client_api :hello, :xmlrpc, "http://localhost:3001/hello/api"

web_client_api(name, protocol, endpoint_uri, options={}) 方法使用指定的协议创建用名称参数指定的受保护方法,以与指定的端点 URI 通信。使用 xmlrpc 协议创建了 hello 方法以与端点 URI http://localhost:3001/hello/api 连接在一起。在 3001 端口上运行 Hello Web 服务,并在 3000 端口上用客户机访问 Web 服务。修改 getMsg 控制器动作以为 Web 服务方法调用的输出创建一个变量。使用用 web_client_api 创建的 hello 方法,用 name 参数作为方法输入调用 Hello Web 服务的 getMsg 方法。在 index.rhtml 视图模板中定义 name 参数值。控制器脚本 helloadmin_controller.rb 如下所示:


清单 11. helloadmin_controller.rb
				
class HelloadminController < ApplicationController

web_client_api :hello, :xmlrpc, "http://localhost:3001/hello/api"

    def getMsg

       @service_output= hello.getMsg(params[:name])
        
    end

end

还可以使用 ActionWebService::Client::Soap 或 ActionWebService::Client::XmlRpc 类的实例直接访问 Hello Web 服务。还可以使用 ActionWebService::Client::Soap 类的实例表示 helloadmin_controller.rb 脚本,如下所示:


清单 12. helloadmin_controller.rb
				
class HelloadminController < ApplicationController

    def getMsg

hello_client = ActionWebService::Client::Soap.new(HelloApi, 
"http://localhost:3001/hello/api")

       @service_output= hello_client.getMsg(params[:name])
        
    end

end

在 views/helloadmin 目录中创建 index.rhtml 视图模板,并且在 RHTML 模板中添加带有 “name” 输入字段的表单。在提交表单时,将调用 Helloadmin 控制器的 getMsg 方法。视图模板 index.rhtml 如下所示:


清单 13. index.rhtml
				
<html>
   <head>
      <title>Hello Web Service</title>
   </head>
   <body>
      <h1>Hello Web Service</h1>
      <p>
      This Rails application tests a Web service.
      </p>
      <%= start_form_tag :action=> 'getMsg' %>
      <p><label>Name</label><br/>
      <%= text_field 'name', '' %></p>
      <%= submit_tag "Get Message" %>
      <%= end_form_tag %>
   </body>
</html>

修改 getMsg.rhtml 视图模板以输出在 Helloadmin 控制器类的 getMsg 方法中定义的 @service_output 变量的值。getMsg.rhtml 视图模板如下所示:


清单 14. getMsg.rhtml
				
<html>
   <head>
      <title>Hello Web Service</title>
   </head>
   <body>
      <h1>Hello Web Service </h1>
      <p>
      
      </p>
      <p>
      <%= @service_output %>
      </p>
   </body>
</html>

接下来,我们将使用客户机 Rails 应用程序测试 Web 服务 Hello。用以下命令在 3001 端口上启动 helloservice 目录中的 Web 服务:

C:/ruby/helloservice>ruby script/server --port=3001

在默认端口 3000 上启动 helloadmin 目录中的客户机 Rails 应用程序:

C:/ruby/helloadmin>ruby script/server

示例应用程序将演示如何从协议客户机中访问 Web 服务。用 URL http://localhost:3000/helloadmin/index 调用 Helloadmin 控制器的索引控制器动作。将显示 index.rhtml 视图模板。指定一个名称值并单击 Get Message。


图 9. 用协议客户机测试 Web 服务


将调用 Helloadmin 控制器的 getMsg 方法。使用 hello 方法(使用 web_client_api 选项定义),可以访问 Hello Web 服务,以及调用 Web 服务的 getMsg 方法。Web 服务的输出显示在 getMsg.rhtml 视图模板中。


图 10. Web 服务的输出


使用协议客户机访问 Web 服务的过程如下:

  1. 创建 Web 服务的 Rails 应用程序。
  2. 创建 Web 服务。
  3. 定义一个或多个 API 方法并在控制器类中实现方法。
  4. 创建协议客户机的 Rails 应用程序。
  5. 定义 API 类和一个或多个 API 方法。
  6. 使用 web_client_api 选项、ActionWebService::Client::Soap 的实例或 ActionWebService::Client::XmlRpc 从客户机应用程序控制器访问 Web 服务。
  7. 在客户机控制器类中实现 API 方法。
  8. 在 3001 端口上启动 Web 服务。
  9. 在 3000 端口上启动客户机应用程序。
  10. 从 RHTML 视图模板中调用 API 方法并将 Web 服务输出输出到其他 RHTML 视图模板中。




结束语

虽然 Rails V2.x 的默认包中附带基于 REST 的 ActiveResource gem 而非基于 SOAP 的 Action Web Service gem,但是基于 SOAP 的 Web 服务也有它们的优点(请参阅 参考资料)。在本文中,我们讨论了如何使用 Action Web Service gem 创建基于 SOAP 和 XML-RPC 的 Web 服务,并且提供了若干个示例以帮助您开始使用这项技术。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
编程语言安全性排行榜:Ruby最佳,C语言漏洞最多?发布时间:2022-07-14
下一篇:
每个程序员都应该学习使用Python或Ruby发布时间:2022-07-14
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap