用 Ruby on Rails 和 Action Web Service 創建 Web 服務

火星人 @ 2014-03-12 , reply:0


  
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 服務,並且提供了若干個示例以幫助您開始使用這項技術。(責任編輯:A6)






[火星人 via ] 用 Ruby on Rails 和 Action Web Service 創建 Web 服務已經有200次圍觀

http://www.coctec.com/docs/linux/show-post-69025.html