天天看點

Rails下的Web Service開發簡介

[b]建立[/b]

先用generator 來建立service 參數為

generator web_service ServiceOne method_a method_b
           

rails會建立一個service_one_api.rb在/app/apis下,同時有service_one_controller在/app/controllers/下

注意 因為ruby完全動态,是以無法根據方法接口來自動生成webservice, 是以搞了一個xxx_api.rb來幹這個事情, 注意 rails對于對象之間的關系不會暴露到webservice外面去,隻是簡單的把字段id寫出去

[b]方法申明[/b]

在xxxx_api.rb中負責定義方法的參數, 定義一個web方法如下

api_method :xxxmethod_name, :expects=>... ,:returns =>

#:expects 如果忽略表示不能傳遞參數 :returns 忽略表示傳回為空
           

它們接收的參數隻能是如下情況之一

* symbol或者string 的基本類型

* Class類型隻支援ActionWebService::Struct或者ActiveRecord::Base子類

* 一個包含前面2個類型參數的數組

* 一個包含前面3個類型參數的hash 用來表明webservice參數名 (webservice友好)

比如 [[:string]] [Person] [{:lastname=>:string}] [:int,:int]

基本類型為 :int :string :base64(會自動轉為binary來傳送檔案) :bool :float :time :datetime(Ruby的DateTime) :date(Ruby的Date) 除此以為均非法

在Contoller中有如下指令

* wsdl_service_name 'SomeName' 設定目前service的名字(說不是必須的)

* wsdl_namespace 'http://xxx' 設定namespace 默扔為'urn:ActionWebService'

* web_service_api XXXApi 關聯controller和他的api類,如果是符合命名規範,可以省略此指令

* web_service_scaffold :somemethod 生成一個action能提供一個直接體驗webservice的web界面,友善調試

* web_service_dispatching_mode :layered | :delegated 設定dispatch mode, 省略表示 direct

[b]ActionWebService::Struct 使用[/b]

這個類是用來幫助組織webservice可以識别的資料對象(DTO) 通過member方法來定義域和類型, 例子如下

[b]webservice 分派方式[/b]

通過web_service_dispatching_mode來申明分派方式, 注意不要寫錯了,寫錯了rails不報錯,而且能給出無用但是合付xml文法的wsdl(一個沒有任何方法的服務)

* 直接配置設定, 實作寫在生成的controller中

layered dispatching 單獨實作ActionWebService::Base的子類(放在apis目錄下),定義public方法即可

delegated dispatching

申明web_service_dispatching_mode以後,使用web_service :my_serv_name ,XXXXService.new(相對靜态生成) 或者web_service :my_name {XXXService.new} 作延遲加載(可以在block中通路controller的變量了,同時也可以對my_name這個新添加的service_action作filter 了)

具體的三種方法我還沒有感覺出有什麼特别用處,目前對webservice認識還不足

[b]對webservice作 AOP 攔截[/b]

支援 before_invocation和after_invocation (:only 和 :except 文法), 如果before_invocation傳回false或者抛出異常或者直接return[false,"reason"], 調用都會中止

攔截方法接收兩個參數, 一個method_name, 一個method參數數組) 和 其他攔截類似, 還可以傳入block(|sourceobj,m_name,m_params|) 和實作攔截類(隻要實作interceptor(m_name,m_params)來攔截

[b]webservice的測試[/b]

預設已經生成好functional test

使用invoke來調用直接的servcie, 類似還有

invoke_layered(service_name, method_name, *args) invoke_delegated(service_name, method_name, *args)

url對應關系

[b]SOAP[/b]

預設controller有一個wsdl的action可以得到wsdl描述檔案,通過service.wsdl也一樣可以得到(routes.rb建立的),通過這個wsdl就可以得到所有的url資訊了

XML-PRC (沒有wsdl的情況) (其實在wsdl下方可以看到這些url,一樣是對XML-PRC有效的

layered dispatching

http://host/PATH/TO/CONTROLLER/api

delegated dispatching

http://host/PATH/TO/CONTROLLER/SERVICE_NAME
           

這裡的SERVICE_NAME就是web_service()方法的第一個參數

[b]調用外部webservice[/b]

在rails controller内部,通過 web_client_api :product,:soap, 'http://url' 就可以建立一個product方法代理服務,使用product.xxx即可

還可以使用ActionWebService::Client::Soap或者ActionWebService::Client::XmlRpc 來基于Api定義的類直接建立對象 shop

=ActionWebService::Client::Soap.new(ProductApi,"http://my.app.com/backend/api") product = shop.find_product_by_id(5)
           

如果服務和rails關聯不緊密, 就使用ruby的webservice包,不必用rails的了