rails笔记: webservice

web service

创建

先用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写出去

方法申明

在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

ActionWebService::Struct 使用

这个类是用来帮助组织webservice可以识别的数据对象(DTO) 通过member方法来定义域和类型, 例子如下

class Person < ActionWebService::Struct
    member :id, :int
    member :name, :string
end

webservice 分派方式

通过web_service_dispatching_mode来申明分派方式, 注意不要写错了,写错了rails不报错,而且能给出无用但是合付xml文法的wsdl(一个没有任何方法的服务)

  • 直接分配, 实现写在生成的controller中
  • layered dispatching 单独实现ActionWebService::Base的子类(放在apis目录下),定义public方法即可

    class ProductService < ActionWebService::Base
    web_service_api ProductApi
    def find_all_products Product.find(:all).map{ |product| product.id end }
    def find_product_by_id(id) Product.find(id) end end

  • 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认识还不足

对webservice作 AOP 拦截

支持 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)来拦截

webservice的测试

默认已经生成好functional test

使用invoke来调用直接的servcie, 类似还有

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

url对应关系

SOAP

默认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()方法的第一个参数

调用外部webservice

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

posted @ 2006-01-24 10:49  tech.cap  阅读(587)  评论(0编辑  收藏  举报