Ruby中的SOAP編程

來源:互聯網
上載者:User

3。Ruby 和 SOAP

簡易物件存取通訊協定 (SOAP)(SOAP)很快的成為了遠端程序呼叫(RPC)的標準協議。(更多關於SOAP的資訊可以分別參看http://www.linuxmagazine.com/2001-10/soap_04.html 和 http://www.linuxmagazine.com/2002-08/webs_01.html)

Ruby提供了對SOAP的強大支援,不管在用戶端還是服務端來說都是這樣的,使用SOAP4R,只需要4部分就能建立一個SOAP請求:

  1. 一個端點 (endpoint), 或者處理SOAP請求的網路地址,一個endpoint一般來說都是運行在WEB伺服器環境中的代碼,但是也有一些其它的SOAP傳輸,包括郵件。
  2. 一個命名空間(namespace), 定義了一個環境內容,在這裡解析調用的方法名。
  3. 一個方法名稱。 遠端程序呼叫的方法的名字。
  4. 一組參數。


使用SOAP4R的時候,我們需要在建立SOAP驅動的時候指定前兩個參數,第三個參數則是為這個驅動Binder 方法時候使用,最後的參數是調用實際需要的方法的時候使用。

 

比如,我們有一個處理銷售訂單的SOAP運行在http://my.server.com,我們要在用戶端訪問這個服務,先要建立一個 SOAP::Driver 對象,建立這個對象的時候需要指定命名空間和伺服器位址(建立這個對象的方法的前兩個參數和記錄日誌有關,這裡我們可以不用考率)

NS  = "urn:ordersService"SVR = "http://my.server.com/orders"drv = SOAP::Driver.new(nil, nil, NS, SVR)

一旦我們建立了這個驅動,就可以用它的addMethod方法增加我們需要向伺服器調用的方法的名稱,第一個參數是這個方法的名稱,其餘的參數是這個方法需要的參數名,這裡,我們需要訪問的方法名為orders_for_product(譯者註:此處是否應該是orders_for?),傳給它的參數十客戶帳號和產品代碼。(Ruby不用WSDL描述SOAP介面)

 

drv.addMethod("orders_for", "cust_acct","prod_code")

一旦所有的東西都完成,我們可以用這個方法任意次數的向伺服器調用:

customers.each do |cust_acct|  products.each do |prod_code|    orders = drv.orders_for(cust_acct, prod_code)    process(orders)  endend

這個例子也要得益於Ruby語言的動態性,比如orders_for方法動態加到了SOAP驅動對象,所以我們可以用drv.orders_for來調用這個方法。而且我們也不需要定義這個方法的傳回值的形式,SOAP驅動會自動將從伺服器得到的結果轉換為適當地Ruby對象。

為了更詳細的說明一下,我們來看一個真正的例子。清單4顯示了如何用SOAP從googel搜尋引擎取得查詢結果,這段代碼基於Ian Macdonald的google.rb。運行這個程式之前,你需要在google 上註冊一下 (http://www.google.com/accounts) ,然後取得一個key,在第三行指定你得到的key。

 

 

清單4: 使用SOAP查詢google

 1   require "soap/driver" 2   ENDPOINT = 'http://api.google.com/search/beta2' 3   NS = 'urn:GoogleSearch' 4   KEY = "get_a_key_from_google" 5 6   fail "Missing query args" if ARGV.empty? 7 8   query = ARGV.join(" ") 910   soap = SOAP::Driver.new(nil, nil, NS, ENDPOINT)11   soap.addMethodWithSOAPAction(12     'doGoogleSearch', NS, 'key', 'q', 'start', 'maxResults', 13       'filter','restrict', 'safeSearch', 'lr', 'ie', 'oe')14   res = soap.doGoogleSearch(15     KEY, query, 0, 10, false, nil, false, nil, 'latin1', 'latin1')1617   puts "Estimated result count: " + res.estimatedTotalResultsCount1819   res.resultElements.each do |entry|20     puts21     puts "#{entry.URL}: #{entry.title}"22     puts entry.snippet23   end

實際的google查詢是在google的伺服器上由方法doGoogleSearch執行的,這個方法接收10個參數(關於這10個參數的具體意義,可以參考google的web API文檔),但是我們的例子裡,我們只是指定了查詢條件,其它參數我們都使用了預設值。在第11行,我們給SOAP驅動增加了方法doGoogleSearch,第14行我們調用這個方法,執行真正的查詢。

從google返回的結果是很複雜的對象,從高層來看,這個結果包括這個查詢本身的一些資訊,比如開始和結束的索引值,查詢用到的條件,查詢消耗的時間等。查詢結果存在一個數組裡面。這和你手工在google頁面上查詢看到的編號的結果一樣。每條查詢結果記錄本身也是很複雜的對象,在我們的例子裡,我們只取出了它的標題,url,和一部分文本。

 

SOAP介面把我們的工作變得很簡單,它自動建立對結果對象的迭代,建立返回結果對象的各種屬性的存取方法,然後,我們可以簡單的使用:

res.resultElements.each do |element|  ...end

如果你在命令提示字元下運行清單4的程式,查詢參數為"ruby soap",結果如下:

 

$ ruby google_search.rb ruby languageEstimated result count: 206000http://www.ruby-lang.org/en/: <b>Ruby</b> Home Page  <b>...</b> Japanese Page If you can read this oriental 
<b>language</b>, <br> you can get more information about <b>Ruby</b>.
Site <b>...</b>http://slashdot.org/developers/01/08/11/2211254.shtml: Slashdot
| Progra.... <b>...</b> Programming in the <b>Ruby</b> <b>Language</b>.
<b>...</b> This discussion has<br> been archived. No new comments
can be posted.http://dev.rubycentral.com/faq/rubyfaq.html: The
<b>Ruby Language</b> FAQ The <b>Ruby</b> <b>Language</b> FAQ. Originally by:
Shugo Maeda.<br> Now maintained by Dave Thomas with help
from Andy Hunt. <b>...</b>

(註:此表為譯者折行之後的結果,原來的內容可能超出寬度,影響閱讀)

在Ruby中編寫一個SOAP伺服器端也是非常簡單的。你所需要做的就是需要發布的介面對象,然後把這些對象發布的SOAP伺服器的servlet上。你所編寫的對象不需要知道SOAP的任何什麼東西。比如,清單5表示的是一個簡單的類,有一個簡單的方法double,接收一個參數,返回兩個這個參數相加的結果。

清單5: The file doubler.rb, the Ruby SOAP doubling class

class Doubler  def double(arg)    arg + arg  endend

要在SOAP伺服器中訪問這個方法,我們需要把它組裝到SOAP伺服器的命名空間上。在Ruby中,最簡單的方法是使用web伺服器工具箱WEBRick。結合soaplet.rb這個servlet代碼(在SOAP4R包的samples/webrick目錄下),我們可以用很少的一些代碼來實現一個完整的SOAP伺服器,代碼見清單6。

 

清單6: A Ruby SOAP server

 1   require 'webrick' 2   require 'soaplet' 3   require 'doubler' 4 5   server = WEBrick::HTTPServer.new(:Port => 2001) 6 7   soaplet = SOAP::WEBrickSOAPlet.new 8   soaplet.addServant('urn:doublerService', Doubler.new) 9   server.mount("/doubler", soaplet)1011   trap("INT") { server.shutdown }12   server.start

前三行只是簡單的引入了需要的庫,soaplet,Double類等。第5行是建立一個web server必須得步驟(本例連接埠為2001),第7行建立了一個soaplet(一個把SOAP請求發送到一個對象的servlet)。第8行把這個servlet幫定到一個Doubler對象,第9行將這個soaplet映射到web server的/doubler。第12行啟動了伺服器處理序序,但是第11行幹什麼用呢?當你啟動一個WEBRick服務時,這個伺服器程式將處理請求,返回結果,但是,我們想我們的伺服器程式能完整的關閉,第11行就是為了完成這種功能,這一行給server註冊了一個處理SIGINT訊號的處理器,當收到這樣的訊號時,調用server的shutdown方法,在大多數作業系統下,control-c將產生SIGINT訊號,所以,我們可以在命令提示字元下控制我們的網頁伺服器。

我們可以用下面清單7中的SOAP用戶端程式來測試一下伺服器端。第10行還展示了rescue的另一個特點:這個語句首先嘗試將參數(傳過來的時候為字串)轉換為整型,如果轉換失敗,則rescue將會捕捉這個異常,並且返回原來的參數。這樣的結果是double方法能接收的參數可以是整型的和字串型的,讓我們看看用戶端啟動並執行時候會有什麼不同。

$ ruby soap_client.rb 12 wiki24wikiwiki$

傳入參數為12,我們得到的結果為24,當我們傳入字串wiki的時候,我們得到的是wikiwiki。Ruby中類型的多態性也傳播到了SOAP介面。因為double方法是arg+arg,所以如果參數為整型,返回兩個數相加的結果,如果參數為字串,則返回兩個字串串連的結果。

 

清單7: The doubler SOAP client

 1   require "soap/driver" 2 3   SVR = 'http://localhost:2001/doubler' 4   NS  = 'urn:doublerService' 5 6   soap = SOAP::Driver.new(nil, nil, NS, SVR) 7   soap.addMethod('double', 'arg') 8 9   ARGV.each do |arg|10     arg = (Integer(arg) rescue arg)11     puts soap.double(arg)12   end

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.