用Delphi 6开发Web Service初探
简介:“网络就是计算机,软件就是服务”的思想已经逐步深入人心。由于Web Services能够通过网络把服务直接递送给终端用户,而且由众多主流厂商所支持和描绘的美好前景也让我们心动不已。据有关报告预计,2002年多数企业将会对于Web服务产生关心。另外,在2004年Fortune 2000家企业引进的应用软件解决方案之中,Web服务将占很大的比重。最近,关于如何建立Web Service的文章较多,但大多是用VS.NET完成的,而关于如何用Delphi 6开发的文章较少。本文介绍了一个用Delphi 6开发Web Service的简单的例子,以达到抛砖引玉之效果。
一、 Web Service概述
尽管关于Web Service是什么有各种各样的理解,但下面的定义有助于读者从不同侧面、不同层次了解Web Service。第一:Web Service就是一个应用程序。它通过WEB向外界提供了如何调用自身功能/服务的说明(WSDL)。这可以让任何人从任何地方使用它所提供的这些服务。或者这样说,Web Service是指可以通过Web技术实现动态联动的软件。
第二:Web Service是新兴的电子商务应用(IBM公司高级副总裁兼软件部执行官Steve Mills语)。Web Service使在Web上的彼此互联和交互更容易、更有效,并可以大大降低目前在B2B等环境下进行编码定制时所需的时间。第三:Web Services是透过网络享用远程服务的一种概念。第四:Web Services是建立可互操作的分布式应用程序的新平台。Web Services的主要目标是跨平台的可互操作性。Web Services平台是一套标准,它定义了应用程序如何在WEB上实现互操作性。第五:Web Services是指一套软件工具,以及一种旨在使软件通过互联网发挥类似拼装玩具作用的整体处理方式。第六:Web Service是一种想把全世界的Internet/Intranet变成一个虚拟计算环境的观念和技术。第七:Web 服务是一个被包装成单一实体,且被发布以供其它程序使用的功能集合,或者说Web 服务是Internet上一系列能够以编程的方式调用的相关的应用程序功能。还有一些其它的说法,但通过这些定义,我们可以看出Web Services的基本理念是:把软件做成服务,并且遵从相应的标准,让不同的系统可以跨越平台,彼此相互兼容,具有进行无缝通信和数据共享的能力。
接着,我们看看关于Web Services的几个核心概念。第一:Web Services若要让异构平台上不同系统可以相互通信和共享数据,那数据在WEB上传输必须以一定的标准和格式进行,这个表示数据的标准就是XML(所以微软称之为XML Web Services)。第二:不同系统遵从什么协议发送和接收这些标准的XML数据从而达到相互通信的目的呢?这个必须遵守的协议就是SOAP(Simple Object Access Protocol简单对象访问协议)。SOAP是在2000年5月8日由Microsoft 和IBM等公司参与制定的规范。SOAP不与任何一种对象模式(如DCOM、CORBA等)相关,它是一种独立的、通用的、基于XML标准的、文本的对象间访问协议。简而言之,SOAP是运用 XML 技术之远程过程调用 ( Remote Procedure Call) 的通讯协议。SOAP把对象间的访问请求和响应都打包成XML文档,在对象间传递。由于SOAP传递的消息都以XML文档形式发送和接收,它最理想、最自然的实现方式就是HTTP,所以客户端仅需具备基本 TCP/IP 网络环境,即可享用全球各处之 Web Services。第三:其他系统如何知道你的Web Services是完成什么功能的?你如何让其他系统知道你的Web Services提供了哪些服务?解决办法就是WSDL(Web Service Description Language-Web 服务描述语言)。它用机器可阅读的格式描述了你的Web Services,从而让其他系统可以调用你所提供的服务。只要我们能够取得特定Web Service的WSDL,就可以从其中了解它提供的服务,以及如何呼叫这个Web Service。WSDL也是 XML ,只是有一定的规范要求。服务端提供 WSDL 文件最重要的用途就是向客户端提供服务端接口的描述。第四:你的Web Services如何发布以便让世界上任何一个地点的人或系统得知你有这项服务从而调用它?或者作为服务请求者,你如何搜索你需要的Web Services呢?这个概念为UDDI( Universal Description, Discovery, Integration-通用描述、发现与集成)。类似于yahoo提供的搜索网站的引擎和B2B电子商务的产品目录搜索,Web Service的提供者必须在UDDI注册中心注册,而服务的请求者若搜索某项服务,可到UDDI注册中心查询。UDDI注册中心扮演了服务的代理者的角色。现在有商业的UDDI运营商和公众UDDI注册中心。三者的关系如下图所示:
图1 服务提供者、服务请求者、服务代理者的关系
UDDI与XML、SOAP(简单对象访问协议)以及WSDL(Web服务描述语言)一起成为Web Services的事实上的核心标准。
二、如何用Delphi 6开发Web Services
Web Service可以由任何的技术开发,Delphi6作为Microsoft Window平台的Web Services 基础环境与开发工具,将 RAD便利性带入Web Services 开发领域,简化了开发Web Services应用程序复杂度,让开发人员专注于应用面的开发,而无须顾及繁琐的Web Services规格面制作。下面我们以一个简单的例子说明如何用Delphi 6开发Web Services。这个例子中我们提供了查询成绩的服务,客户端(服务请求者——可以是浏览器、Windows程序甚或Linux程序,在这里,为了简单起见,我们用了传统的Windows程序)可以输入学号,查询出相应的成绩来。
1、创建服务
首先我们要建立一个成绩表,名称为Grade。我们在SQL SERVER里面建立一个TEST库,在其下建立Grade表,它有三个字段,分别为StudentID、Name、Grade。随后我们随便向里面添加一些数据。然后我们配置一下ODBC,在系统DSN中添加一个数据源,名称起为Grade,指向我们刚才建立的TEST库。如图二所示:
图2 配置ODBC
接着我们在Delphi6里启动New | Web Services | Soap Server Application,确定后,在接下来的对话框中选择Web App Debugger executable。我们选择这种类型制作Web Services是因为这个形态可以让我们在开发时便于调试。设置其CoClass Name为MyWebServicesTest1,如下图所示:
图3 建立Web Services
这时Delphi会自动给我们生成一个Form和一个WebModule,WebModule中的几个组件是帮助我们用SOAP进行通信和发布WSDL的,有了它们,我们就可以开始集中精力编写实际的应用代码了。现在我们New一个Data Module ,在File菜单里选择New|Data Module,在其上放置一个ADOQuery以连接我们的数据,设置其ConnectionString属性为Provider=MSDASQL.1;Password=sa;Persist Security Info=True;User ID=sa;Data Source=Grade(选择Build,然后选择微软提供的ODBC驱动,选下一步,使用指定的数据源名称Grade,输入用户名称和密码确定即可)。将该单元保存为dm。如图所示:
图4 连数据源
现在我们要定义要存储学生信息的结构。我们New一个Unit,在file菜单里选择New|Unit,写上如下的代码:
unit DataType;
interface
Uses InvokeRegistry;
Type
TStudentInfo=Class(TRemotable)
Private
FName : String;
FGrade : Single;
published
Property Name : String Read FName Write FName;
Property Grade : Single Read FGrade Write FGrade;
end;
implementation
Initialization
RemClassRegistry.RegisterXSClass(TStudentInfo);
Finalization
RemClassRegistry.UnRegisterXSClass(TStudentInfo);
end.
因为学生信息需要传递到客户端,所以它必须从 TRemotable 类派生。将这个Unit保存为DataType。
接着,我们要建立用户请求服务的接口,这个接口只有一个取得成绩的功能。New一个Unit,写上如下的代码:
unit ServicesInterface;
interface
Uses InvokeRegistry,DataType;
Type
ISoapGrade=Interface(IInvokable)
['{9884ADA8-8FDC-4002-94A3-2370A269018F}'] //注意,要给这个接口分配//一个GUID,在Delphi里用Crtl+Shift+G产生。
Function GetGrade(Number:Integer):TStudentInfo;StdCall; //调用这个接口函数
//将返回一个TstudentInfo类型的数据。
End;
implementation
Initialization
InvRegistry.RegisterInterface(TypeInfo(ISoapGrade));
end.
将这个单元保存为ServicesInterface。
然后我们要编写这个接口的实现类。在Unit2(WebModule单元)里添加实现类的定义。完整的代码如下:
unit Unit2;
interface
uses SysUtils, Classes, HTTPApp, WSDLPub, SOAPPasInv, SOAPHTTPPasInv, SoapHTTPDisp, WebBrokerSOAP;
type
TWebModule2 = class(TWebModule)
HTTPSoapDispatcher1: THTTPSoapDispatcher;
HTTPSoapPascalInvoker1: THTTPSoapPascalInvoker;
WSDLHTMLPublish1: TWSDLHTMLPublish;
private
{ Private declarations }
public
{ Public declarations }
end;
var
WebModule2: TWebModule2;
implementation
uses WebReq,InvokeRegistry,DataType,ServicesInterface,dm;
Type
TSoapGrade=class(TInvokableClass,ISoapGrade)
Protected
Function GetGrade(Number:Integer):TStudentInfo;StdCall;
End; //定义这个接口类
Function TSoapGrade.GetGrade(Number:Integer):TStudentInfo;StdCall;
Begin
Result:=TStudentInfo.Create;
If ( Not Assigned( DataModule3)) Then
DataModule3:=TDataModule3.Create(Nil); //如果DataModule3没有创建,则创建它。
Try
With DataModule3.ADOQuery1 Do
Begin
active:=false;
sql[0]:='select * from Grade where StudentID='+inttostr(Number)+';
active:=true;
//根据用户输入的学号和数据库连接。
If (Not Eof) Then
Begin
Result.Name:=FieldByName('Name').AsString;
Result.Grade:=FieldByName('Grade').AsFloat;
//从数据库里取得合适的值给要传递的信息。
End
Else
Begin
Result.Name:='未查询到!'; Result.Grade:=0;
End;
Close;
End;
Finally
DataModule3.Free; DataModule3:=Nil;
End;
End;
initialization
WebRequestHandler.WebModuleClass:=TWebModule2;
InvRegistry.RegisterInvokableClass(TSoapGrade);
end.
到现在,我们已经创建了一个Web Services!保存,编译,运行,即在Web App Debugger那里完成了此Web Services的注册工作。那么我们这个Web Services提供了什么功能?如何调用它?这些问题可以通过看看它的WSDL来看到。我们启动Web App Debugger(在Tools菜单下),然后启IE,在地址栏里输入:
http://localhost:1024/server.MyWebServicesTest1/wsdl/IsoapGrade,即可看到用XML语言写成的WSDL,有了它,服务请求者就可以调用我们的服务了。 2、实现客户端,调用服务
我们建立一个普通的应用程序,在form上面放置3个label、3个edit和2个button以及一个HTTPRIO1(在WebServices组件页里),将HTTPRIO1的URL属性设为
http://localhost:1024/server.MyWebServicesTest1/soap,以便利用SOAP通信。界面如下图所示: 图5 客户端的传统windows程序界面
接着为了让这个客户端程序知道我们刚才建立的Web Services的WSDL以便请求服务,我们必须在客户端那里导入WSDL以便获得服务的接口。幸运的是,我们根本不必很麻烦的自己编程,Delphi已经给我们做了。启动New | Web Services |Web Services Importer,然后输入WSDL所在URL地址为:
http://localhost:1024/server.MyWebServicesTest1/wsdl/IsoapGrade,接着确定产生,Delphi自动会为我们产生两个unit,这样接口的事情就全部交给Delphi,我们就不必管了。如图所示: 图6 引入WSDL
最后,在Form1的确定按钮的OnClick事件里添加如下的代码:
procedure TForm1.Button1Click(Sender: TObject);
Var
Student:TStudentInfo;
begin
Student:=(HTTPRIO1 As ISoapGrade).GetGrade(StrToInt(Edit1.Text));
If (Assigned(Student)) Then
Begin
Edit2.Text:=Student.Name;
Edit3.Text:=floattostr(Student.Grade);
End;
end;
并注意要在unit1的uses中添加unit2和unit3。保存,编译。至此我们的客户端程序开发完毕,调用Web Services是不是很简单?下图是客户端调用的结果:
图7 调用的执行结果
目前互联网上已经有一些网站罗列了许多Web Services,例如
http://www.xmethods.com,上面有关于各个Web Services说明以及WSDL的描述,读者若有兴趣可以自己编写客户端程序引入上面的WSDL。当读者能够利用自己编写的客户端跨越各种平台和网络结构,调用地球另一侧的人也许用java写成的Web Services时,相信你一定为Web Services的强大而欢欣鼓舞。
三、小结
从上面的例子我们可以看到,只要理解了Web Services的概念,熟悉了Web Services的开发步骤,在Delphi的帮助下,开发Web Services将不是一件很困难的事情。Web Services最适合用于开发跨平台和跨网络进行通信(因为使用http协议为防火墙所允许)的程序,可以跨越异质架构,联系客户、供应商、企业伙伴以及企业内部之信息系统,是电子商务B2B集成的最佳选择。各个公司只要把商务逻辑“暴露”出来,成为Web Service,就可以让任何指定的合作伙伴调用这些商务逻辑,而不管他们的系统在什么平台上运行,使用什么开发语言。但也没有必要把所有的软件都做成Web Services,正如“尺有所短,寸有所长”一样,传统的windows程序也大有用武之地。Web Services是目前很热门也是正在迅速发展着的一项技术,本文只是作者在学习中的一点小体会,肯定有理解不深刻甚或错误的地方,欢迎大家予以指正。