ruby on rails
Rails是一个Web应用程序框架,其中包括使用Model-View-Control(MVC)模式创建数据库支持的Web应用程序所需的一切。 Action Web Service的最简洁定义是在其README文件中:“ Action Web Service提供了一种使用Rails发布可互操作的Web Service API的方法,而无需花费大量时间来研究协议细节。” 在本文中,您将学习如何安装Rails和Action Web Service模块并开始使用XML-RPC编程。
硬件和软件要求
连接到能够运行Ruby的网络的任何计算机都应具有足够的处理能力来处理此处提供的代码。 需要Ruby V1.86或更高版本,以及RubyGems和Rails。 我们讨论了如何在运行Microsoft®Windows®的计算机上安装它们。
Web服务如何工作
Web服务是一种软件系统,旨在通过网络进行互操作的交互。 Web服务是用WSDL文档定义的。 其他系统使用SOAP消息与Web服务进行交互,该消息通过HTTP和XML序列化进行传输。 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文章):
- 对于Windows用户,请下载最新版本的Ruby Windows安装程序(当前为Ruby V1.8.6-25),然后双击可执行文件。 将Ruby安装在C:/ ruby目录中。 还安装了用于安装其他gem的标准Ruby软件包管理器RubyGems。 接下来,安装Rails。 从C:/ ruby目录(安装Ruby的目录)中,运行以下命令来安装Rails和依赖项:
c:/ruby>gem install rails --include-dependencies
。 - 使用Rails 2.0版本时,默认包中不包含Action Web Service gem。 使用以下命令安装
actionwebservice
gem:c:/ruby>gem install actionwebservice
。 在撰写本文时,actionwebservice
V1.2.6是最新版本。 如果使用的是Rails的早期版本(Rails V2.0之前的版本),则actionwebservice
gem将包含在默认软件包中。 - 通过输入
C:/ruby>rails webservice
为Web服务创建Rails应用程序。 - 在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
- 创建一个控制器脚本,该脚本定义一个控制器类:
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
- 通过输入
C:/ruby/webservice>ruby script/server
启动WEBrick WebC:/ruby/webservice>ruby script/server
。 - 显示具有URL
http://localhost:3000/hello_message/wsdl
的Web服务的WSDL文件。图1. Web服务WSDL
- 使用
http://localhost:3000/hello_message/invoke
Web服务。 将显示该Web服务的API方法。 选择HelloMessage
方法。图2.调用Web服务
- 要测试Web服务,请指定一个名字和一个姓氏,然后单击Invoke 。
图3.调用Web服务方法
- 返回值以及请求XML和响应XML被输出。
图4. Web服务的输出
让我们详细讨论Web服务。 Web服务API类定义了Web服务提供的方法。 示例API类定义了hello_message
方法,该方法采用两个string
类型的参数并返回一个字符串值。 使用ActionWebService::API::Base
类的api_method
方法定义API方法。 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服务支架。 Web服务支架类似于Active Record的支架。 在示例Web服务中指定的invoke方法列出了连接到控制器的所有API中的所有方法。 客户端类可使用控制器类中的hello_message
操作来进行方法调用。
Web服务API类
在前面的示例中,Web服务API类是HelloMessageApi
。 Web服务API类扩展了ActionWebService::API::Base
类,并指定了可用于Web服务中的API的方法。 该类的一些方法将在下面讨论。
表1. ActionWebService :: API :: Base方法
方法 | 描述 |
---|---|
api_method(名称,选项= {}) | 指定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类的过程如下:
- 确定要在API上提供哪些方法。
- 创建一个扩展
ActionWebService::API::Base
类的类。 - 使用
api_method
选项定义方法,包括方法签名。
派遣
调度是Web服务上方法调用的分布。 调度方法是指远程调用者将调用消息发送到何处,以及方法调用如何路由到方法实现对象。 基于调度方法实现API。 可以使用三种调度方法:
- 直接
- 委托
- 分层的
直接派遣
使用直接分派方法,API定义类将附加到控制器类,并且API方法在控制器类中作为公共实例方法实现。 正如前面讨论的示例应用程序中一样,直接调度被指定为web_service_dispatching_mode :direct
。
直接调度方法是默认方法。 使用直接分派方法,控制器类可以仅实现一个API。 具有直接分派的Web服务的端点URL为http://SERVER/CONTROLLER_NAME/api
格式。
前面讨论的示例Web服务的端点URL是http://localhost:3000/hello_message/api
,如WSDL文档的service元素中所指定。
清单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定义类与控制器类同名并且存储在app/apis
目录中的apiclass_api.rb
格式的Ruby文件中,则可以省略web_service_api
选项。 在前面讨论的示例应用程序中,在控制器类中不需要web_service_api
选项,因为API类存储在hello_message_api.rb
。 使用直接分派方法开发Action Web Service Web服务的过程如下:
- 定义一个API类,一个扩展
ActionWebService::Base
类的类,并定义API方法。 - 使用
web_service_api
选项将API Web服务类附加到控制器类。 - 使用
web_service_dispatching_mode :direct
将调度模式设置为“ direct”。 - 在控制器类中将API方法实现为公共实例方法。
- 通过将脚手架添加到控制器类来测试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类中定义的方法。 使用web_service_api
选项,API类与服务类一起附加。 HelloMessageService
类实现HelloMessageApi
API类。 将HelloMessageService
服务类作为Ruby脚本hello_message_service.rb
存储在app/models
目录中。 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
。 将控制器类存储在app/controllers
目录中。 控制器脚本delegated_controller.rb
如下所示。
清单8. proxyed_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服务的过程如下:
- 定义要由Web服务实现的API类。
- 为每个API类创建一个服务类,该类扩展了
ActionWebService::Base
类。 使用web_service_api
选项将API类附加到服务类。 - 将服务类中的API方法实现为公共实例方法。
- 创建一个控制器类,并将调度模式设置为“委托”。
- 使用
web_service option
将服务类附加到控制器类。 - 通过使用
web_service_scaffold
选项为Web服务生成支架来测试Web服务。
分层调度
分层调度方法过程与委托调度方法类似,不同之处在于以下声明: web_service_dispatching_mode :layered
。 每个方法调用均以servicename.methodname
格式的服务名称作为前缀。 还可以使用由web_service_scaffold
选项生成的支架来测试分层的分派方法Web服务。
协议客户端
动作Web服务提供了一些用于访问远程Web服务的客户端类。 可以使用web_client_api
帮助函数从控制器内部访问远程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目录中以Ruby脚本hello_api.rb
创建一个HelloApi
API类。 在controllers目录中创建了hello_controller.rb
控制器脚本。 HelloController
控制器类包括getMsg
控制器动作。 控制器类还指定wsdl_service_name
(Web服务名称)。 运行Web服务时,Web服务的WSDL可用。 修改控制器脚本以指定web_service_api
选项,并指定与脚手架web_service_scaffold
选项。 web_service_api
选项将控制器映射到API类。 修改getMsg
控制器操作以采用字符串参数并返回字符串值。 该getMsg
方法实现getMsg
方法在API类。 修改后的控制器脚本如下所示。
清单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服务框架
显示名称输入字段。 您还可以选择协议:SOAP或XML RPC。 在“名称”字段中指定一个值,然后单击“ 调用” 。
图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={})
方法使用指定的协议创建一个使用name参数指定的受保护方法,以与指定的端点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
视图模板,以输出变量@service_output
的值,该值在Helloadmin
控制器类的getMsg
方法中定义。 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
。 从helloservice
目录中使用以下命令在端口3001上启动Web服务:
C:/ruby/helloservice>ruby script/server --port=3001
从helloadmin
目录中的默认端口3000上启动客户端Rails应用程序:
C:/ruby/helloadmin>ruby script/server
该示例应用程序演示了如何从协议客户端访问Web服务。 使用URL http://localhost:3000/helloadmin/index
调用Helloadmin
控制器的索引控制器操作。 显示index.rhtml
视图模板。 指定一个名称值,然后单击“ 获取消息” 。
图9.使用协议客户端测试Web服务
Helloadmin
控制器的getMsg
方法被调用。 使用使用web_client_api
选项定义的hello
方法,可以访问Hello
Web服务,并调用该Web服务的getMsg
方法。 Web服务的输出显示在getMsg.rhtml
视图模板中。
图10. Web服务的输出
使用协议客户端访问Web服务的过程如下:
- 为Web服务创建Rails应用程序。
- 创建一个Web服务。
- 定义一个或多个API方法并在控制器类中实现该方法。
- 为协议客户端创建Rails应用程序。
- 定义API类和API方法。
- 使用
web_client_api
选项(ActionWebService::Client::Soap
或ActionWebService::Client::XmlRpc
web_client_api
的实例)从客户端应用程序控制器访问Web服务。 - 在客户端控制器类中实现API方法。
- 在端口3001上启动Web服务。
- 在端口3000上启动客户端应用程序。
- 从RHTML视图模板调用API方法,并将Web服务输出输出到另一个RHTML视图模板。
结论
尽管Rails V2.x在默认捆绑包中包含了基于REST的ActiveResource gem,而不是在基于SOAP的Action Web Service gem中,但基于SOAP的Web service也有其优势(请参阅参考资料 )。 在本文中,我们讨论了如何使用Action Web Service gem创建基于SOAP和基于XML-RPC的Web服务,并提供了一些示例来帮助您开始使用该技术。
翻译自: https://www.ibm.com/developerworks/opensource/library/os-ws-rubyrails/index.html
ruby on rails