[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的了