利用Ruby的SOAP4R编写SOAP服务器的教程

时间:2022-06-02 00:15:41

 什么是SOAP ?

简单对象访问协议(SOAP)是一个跨平台和语言无关的,基于XML的RPC协议,通常(但不一定)是HTTP。

它使用XML来编码信息使远程过程调用,HTTP在网络上从客户机到服务器来传输信息,反之亦然。

SOAP有几个优势超过其他技术,如COM,CORBA等为例,其相对廉价的部署和调试成本,它的可扩展性和易于使用,存在几种不同的语言和平台实现。

请参阅出简单的教程了解 SOAP

本教程将熟悉SOAP实现Ruby(SOAP4R)。这是一个基本的教程,所以如果需要深入细节,那么需要参考其他资源。
安装SOAP4R:

SOAP4R是由Hiroshi Nakamura编定,可以直接从网上下载Ruby的开发的SOAP实现:

注意:有可能已经安装了这个组件。

Download SOAP

如果知道 gem 实用工具,那么可以使用下面的命令安装SOAP4R和相关包。

$ gem install soap4r --include-dependencies

如果是在Windows上工作,那么需要下载一个压缩文件,从上面的位置,需要安装它使用标准的安装方法运行Ruby的 install.rb.
编写SOAP4R服务器:

SOAP4R支持两种不同类型的服务器:

  1.     CGI/FastCGI based (SOAP::RPC::CGIStub)

  2.     Standalone (SOAP::RPC:StandaloneServer)

本教程将详细编写一个独立的服务器。涉及编写SOAP服务器有以下步骤:
第1步 - 继承SOAP::RPC::StandaloneServer 类:

要实现自己的独立服务器,需要编写一个新类,这将SOAP::StandaloneServer 类的子类,如下:

 

复制代码 代码如下:
class MyServer < SOAP::RPC::StandaloneServer
  ...............
end

 

注意:如果想编写一个基于FastCGI的服务器,那么需要继承SOAP::RPC::CGIStub 类, 其余步骤将保持相同。
第2步 - 定义处理程序方法:

第二步是编写Web服务方法,希望向外界公开。

它们可以写成简单的Ruby方法。例如,让我们写了两个两个两个数相加,两个数相除的方法:

?
1
2
3
4
5
6
7
8
9
10
11
class MyServer < SOAP::RPC::StandaloneServer
  ...............
 
  # Handler methods
  def add(a, b)
   return a + b
  end
  def div(a, b)
   return a / b
  end
end

第3步 - 暴露处理程序方法:

下一步是我们定义的方法添加到我们的服务器。 initialize方法用于暴露服务的方法,用以下两种方法之一:

?
1
2
3
4
5
class MyServer < SOAP::RPC::StandaloneServer
  def initialize(*args)
   add_method(receiver, methodName, *paramArg)
  end
end

下面的参数说明:

利用Ruby的SOAP4R编写SOAP服务器的教程

 To understand the usage of inout or out parameters, consider the following service method that takes two parameters (inParam and inoutParam), returns one normal return value (retVal) and two further parameters: inoutParam and outParam:

?
1
2
3
4
5
6
def aMeth(inParam, inoutParam)
  retVal = inParam + inoutParam
  outParam = inParam . inoutParam
  inoutParam = inParam * inoutParam
  return retVal, inoutParam, outParam
end

现在,我们可以公开这个方法如下:

?
1
2
3
4
5
6
add_method(self, 'aMeth', [
  %w(in inParam),
  %w(inout inoutParam),
  %w(out outParam),
  %w(retval return)
])

第4步 - 启动服务器:

最后一步是通过实例的派生类的一个实例,并调用start方法来启动服务器。

?
1
2
3
4
myServer = MyServer.new('ServerName',
            'urn:ruby:ServiceName', hostname, port)
 
myServer.start

这是必需的参数的描述:

利用Ruby的SOAP4R编写SOAP服务器的教程

  例如:

现在使用上述步骤,让我们写一个独立的服务器:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
require "soap/rpc/standaloneserver"
 
begin
  class MyServer < SOAP::RPC::StandaloneServer
 
   # Expose our services
   def initialize(*args)
     add_method(self, 'add', 'a', 'b')
     add_method(self, 'div', 'a', 'b')
   end
 
   # Handler methods
   def add(a, b)
     return a + b
   end
   def div(a, b)
     return a / b
   end
 end
 server = MyServer.new("MyServer",
      'urn:ruby:calculation', 'localhost', 8080)
 trap('INT){
   server.shutdown
 }
 server.start
rescue => err
 puts err.message
end

执行时,服务器应用程序开始一个独立的SOAP服务在localhost上侦听8080端口的请求。它暴露了一个服务方法:add 和 div ,这需要两个参数并返回结果。

现在可以运行这个服务器后台如下:

?
1
$ ruby MyServer.rb&

编写SOAP4R客户端:

SOAP::RPC::Driver 类用于写入SOAP客户端应用程序提供支持。本教程将介绍这个类,显示其使用的应用程序的基础。

以下是最低要求的信息,需要调用SOAP服务:

  •     SOAP服务(SOAP端点URL)

  •     service方法(方法命名空间URI)

  •     service方法的名称及其参数

现在我们将编写一个SOAP客户端调用服务定义的方法在上面的例子名称为add和div。

以下是主要的步骤来创建一个SOAP客户端:
步骤1 - 创建一个SOAP驱动程序实例:

我们创建一个实例 SOAP::RPC::Driver 通过调用 new 方法如下:

?
1
SOAP::RPC::Driver.new(endPoint, nameSpace, soapAction)

这是必需的参数的描述:

利用Ruby的SOAP4R编写SOAP服务器的教程

 第2步 - 添加服务的方法:

要添加到SOAP SOAP服务方法到 SOAP::RPC::Driver 我们可以调用下面的方法使用 SOAP::RPC::Driver 实例:

driver.add_method(name, *paramArg)

下面的参数说明:

利用Ruby的SOAP4R编写SOAP服务器的教程

 第3步 - 调用SOAP服务:

最后一步是调用SOAP服务使用 SOAP::RPC::Driver 实例如下:

?
1
result = driver.serviceMethod(paramArg...)

这里serviceMethod是实际的Web服务方法和paramArg...是列表参数需要通过在服务方法。
例如:

根据上述步骤,我们将编写一个SOAP客户端如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/ruby -w
 
require 'soap/rpc/driver'
 
NAMESPACE = 'urn:ruby:calculation'
 
begin
  driver = SOAP::RPC::Driver.new(URL, NAMESPACE)
  
  # Add remote sevice methods
  driver.add_method('add', 'a', 'b')
 
  # Call remote service methods
  puts driver.add(20, 30)
rescue => err
  puts err.message
end