直到不久以前,Delphi才拥有了开发Web服务程序(Web services)的能力.在以前的版本中,你可以选择诸如CORBA,DCOM,TCP/IP套接字等协议来开发多层的应用程序.虽然使用这些协议有一定的优点,但是它们也存在着不同的限制--而且它们都需要你在客户端表示出服务器端的对象.然而,Delphi 6允许你利用简单对象访问协议(SOAP)来使用(或者开发)Web服务程序
。
在我的两篇系列文章的下面的第一篇中,我将解释什么是Web服务并将向你展示如何在Delphi 6中使用已经存在的Web服务程序(不管它是用什么语言,在什么环境下编写的).
SOAP
SOAP提供了一条新的途径来将分散的层次连接在一起.它使用XML作为描述语言并且在许多情况下是高效的,但是目前最通用的用法之一是将它使用在Web服务的场合.你可以将一个Web服务看成是一个在Web 服务器上运行的远程对象,而这个远程对象的方法(服务)可以通过SOAP对外界开放.对Web服务及其方法的描述可以通过Web服务描述语言(WSDL)来实现,WSDL是XML的一个子集.实际上,以后我们将能够看见Delphi 6中编写的Web 服务能够自动为它们的对象界面生成正确的WSDL.
使用Web服务
浏览XMethods或者SalCentral Web services这样的中间网站你可以得到一些可用的Web服务的列表.(它们是在多种环境中编写的,比如说Delphi 6,Visual Studio.NET,Lucin SAL,等等)在本文中,我们将使用两个Web服务:Number to Words--数字转换成单词(由Tom Chamberlain在Delphi中编写而成)和BabelFish服务(来自AltaVista,XMethods用SOAPLite实现).我们的目的是要将一个数字(比方说,42)转化成单词,然后将它们从英文翻译成德文.你可以在这里下载和本文配套的例子文件.
数字到单词
Number to Words Web服务程序是用Delphi 6写成的.你可以从PowerOfZen获得WSDL描述文本.(这个网页能够生成WSDL,也就是一段列出你的需求的XML,以便生成一个引入的方法使你能够在Delphi 6中使用它).
为Web服务新建一个Delphi 6工程并将它保存为Client.dpr.现在,你必须生成一个导入部件来让IWordsForCheck界面能够运转起来.选择"文件|新建|其他"菜单,单击WebServices标签,然后选择Web服务导入图标,一个如图A所示的对话框将显示出来.在这里你粘贴上前面获得的WSDL URL.
单击"生成"按钮来生成IWordsForCheck界面的导入单元:
type
IWordsForCheck = interface(IInvokable)
[''{C3530212-5440-4CC4-82ED-5AA3F0984AAF}'']
function GetWordsForCheck(const Value: Double): WideString; stdcall;
end;
注意IWordsForCheck界面是从IInvokable界面继承而来的(需要这样做是因为你需要能够使用这个远程的Web服务).
调用GetWordsForCheck过程
现在,让我们回到Delphi工程的主单元然后在"使用"列表中加入导入单元(要么通过选择"文件|使用单元"菜单,要么通过显式的将它添加到"使用"列表中去).在应用程序主窗口中,我们将使用三个编辑框,如图B所示.第一个编辑框(输入框)将包含一个阿拉伯数字.第二个编辑框(输出框)将包含用英文单词表示的数字.第三个编辑框我们将在本文的后面使用,它将包含同样的数字,但是是用另外一种语言描述的.我们用一个按钮来启动事件,但我们首先需要一个更重要的部件来使这一切运转起来.打开部件调色板中的WebServices标签然后拖出第一个部件,HTTPRIO(它代表着一个可以通过HTTP访问的远程对象).
HTTPRIO
你还记不记得我们用来生成导入单元所需的WSDL时使用的那个URL吗?导入单元只是标明了IWordsForCheck界面和这个界面的方法,GetWordsForCheck.它并没有指明到哪里找到这个Web服务.那正是你需要告诉给HTTPRIO组件的信息,同样是使用WSDL URL.确保你没有发生任何输入错误(最好是简单的拷贝粘贴),将WSDL URL放在HTTPRIO 组件的WSDLLocation属性栏里:
http://powerofzen.com/cgi-bin/wordsforchecks.exe/wsdl/IwordsForCheck
然后,打开服务属性的下拉列表并选择IWordsForCheckservice(唯一的选项).最后,打开端口属性的下拉列表IWordsForCheckPort(它也是唯一的选项).现在HTTPRIO已经作好准备来连接和使用Web 服务了.
真正的使用过程发生在按钮的onClick事件处理函数里.我们首先需要从HTTPRIO组件里提取出IWordsForCheck界面(其效果就是激活远程Web服务).一旦我们获得了这个界面,我们就能调用它的方法了(在此例中,就是那个唯一的方法GetWordsForCheck).
procedure TForm1.Button1Click(Sender: TObject);
var
WordsForCheck: IWordsForCheck;
Number: Integer;
begin
WordsForCheck := (HTTPRIO1 AS IWordsForCheck); // 连接
Number := StrToInt(Edit1.Text);
Edit2.Text := WordsForCheck.GetWordsForCheck(Number);
end;
当我们在第一个编辑框中输入42然后点击按钮,将形成一个到远程Web服务的连接,IWordsForCheck界面将被提取出来(如果我们能够连接到Web服务的话),而后数字42将被转换成"FORTY TWO DOLLARS AND 00 CENTS".
BabelFish
你也可以在一个程序中使用不止一个Web服务.为了演示,让我们首先看看BabelFish翻译Web服务(基于AltaVista的BabelFish)将怎样把我们所得到的结果从英文翻译到德文.参看XMethods BabelFish Service Details来获得更详细的信息.
我将把使用WSDL URL(http://www.xmethods.net/sd/BabelFishService.wsdl)来生成导入单元并将WSDL URL写入到另一个HTTPRIO组件的WSDLLocation属性的任务留给你.不要忘了同时设定服务和端口两个属性.然后你就可以象下面一样添加最终代码:
procedure TForm1.Button1Click(Sender: TObject);
var
WordsForCheck: IWordsForCheck;
Number: Integer;
BabelFish: BabelFishPortType;
begin
WordsForCheck := (HTTPRIO1 AS IWordsForCheck); // Connect
Number := StrToIntDef(Edit1.Text,0);
Edit2.Text := WordsForCheck.GetWordsForCheck(Number);
BabelFish := (HTTPRIO2 AS BabelFishPortType); // Connect
Edit3.Text := BabelFish.BabelFish(''en_de'',Edit2.Text)
end;
使它变得更好
不幸的是,BabelFish服务每次只翻译文本中的一个单词.如图C所示,对于 "FORTY TWO",你将得到"VIERZIG ZWEI",它的意思是"四十"和"二"而不是"四十二".为了消除这种限制,并且同时开发出英语到荷兰语的翻译服务(BabelFish现在还没有提供这种功能),我决定编写自己的Number to Dutch Words(将数字用荷兰语表示)的Web服务.那将是我们下一次讨论的题目.同时,如果你对Delphi 6中使用Web服务有任何疑问或者你希望看到更多的例子,有空的时候请访问我的Web站点上的SOAP部分.