当前位置:IT教程网教程中心其他整理Web 服务 → 教程内容

用 Delphi 构建带 DB2 后端的 Web 服务

减小字体 增大字体 作者:佚名  来源:不详  发布时间:2007-1-8 17:37:00
Marco CantÙ
www.marcocantu.com
2002 年 12 月
本文向您展示了如何用 Delphi 7 Studio 构建使用 DB2 数据的 XML Web 服务

简介
Borland™ Delphi® 和 Kylix® 有许多与其它可视化开发工具不同的特性,其中包括对 XML Web 服务服务器和客户机应用程序的广泛支持。Delphi Web 服务支持基于简单对象访问协议(Simple Object Access Protocol,SOAP)— SOAP 是广泛应用的、用于实现 Web 服务的技术。(可在 http://www.w3.org/TR/SOAP/查找有关 SOAP 的更多信息。)

Web 服务是推动现有应用程序转向 B2B(企业对企业)应用程序的主要技术。为了帮助您着手了解这种技术,我将向您展示一个用 Delphi 构建的实际 Web 服务示例和一个测试客户机,该客户机处理来自 IBM® DB2® Universal Database™ 后端的数据。

用 Delphi 创建 Web 服务
Borland 首先在 Delphi 6 中添加了 Web 服务支持。与其它方法不同的是,它不但将这种技术集成到了开发环境中,而且还集成到语言本身。Delphi 语言很早以前就包括了“接口”概念,此概念类似于 Java™ 中的相应概念。现在,考虑到接口发布和远程调用这个通用机制,Borland 引入了对接口自省的支持。尤其是,这个支持被定制成用于一些现成组件的 SOAP 映射层。

说了这么多,让我向您展示如何用 Delphi 7 实际创建 Web 服务。使用 Delphi IDE 的 File | New | Other 菜单命令启动一个新工程,移到 New Items 对话框的 WebServices 选项卡,然后选择 SOAP Server Application。

因为通常将 Web 服务作为 Web 服务器扩展部署,所以必须确定哪种 Web 服务器体系结构最适合于您的应用程序。使用 Delphi,您可以在 Apache 模块(当然,在 Kylix 上也是可用的)、CGI、ISAPI(只能在带有 Microsoft IIS 服务器的 Windows® 上使用)和内部的 Web Application Debugger 之间进行选择。第一件需要注意的事情是,不要被为选择哪一个而捆住手脚:您此处的选择会影响主工程文件中的几行代码,但对 Web 服务器扩展或 Web 服务实际代码的开发几乎毫无影响。事实上,Delphi WebBroker 体系结构将服务器端程序的开发从正在使用的实际技术中抽象出来。您只需创建新的工程,并将现有应用程序的所有源代码文件添加到这个工程,就可以从一种模型迁移到另一种模型。

对于本文中的这个示例,我使用 Web App Debugger 模型。这种模型的特点在于一个独立的可执行文件(通过定制 Web 服务器使用套接字连接来激活)。Web App Debugger 应用程序本身可以让您跟踪调用,并查看应用程序的 HTTP 请求和响应。请注意,需要运行这个程序以测试本文中构建的服务器。使用这种技术的优点在于可以从 Delphi IDE 执行服务器应用程序,并可以立即开始调试它,而没有调试 Web 服务器的扩展库所需的麻烦。

既然已经选择了 Web 服务器体系结构,那么 Delphi 希望知道我是否有兴趣为我们的 Web 服务器创建接口。单击 Yes 按钮以激活 Interface 向导。在这个向导中,将输入正在创建的接口的名称,以及用来保存接口的文件名称。这个向导有助于为 Web 服务创建合适的体系结构,因此使用向导是个好主意。

Web 服务应用程序的结构
在这些步骤的结尾,Delphi 将生成 Web 服务工程的完整结构,包括:

  • 托管一些标准组件的 SOAP 数据模块。
  • 接口单元,它包括公开为 SOAP 服务器的 Delphi 接口的定义。
  • 实现单元,用于实现希望公开接口的方法。
  • 用来表示服务器的窗体,它是基于 Web Debugger 体系结构(成熟的 Windows 应用程序)。当然,我们会忽略这种窗体,因为这个工程仅用于开发用途。

既然 Delphi 已经生成了这个代码,该是开发 Web 服务的时候了。第一步,定义接口的方法。这是核心步骤,因为它表明了 Web 服务能做什么的定义。您可以采用两种方法实施这一步骤。第一种方法,使用现有的 WSDL(Web 服务描述语言,Web Service Description Language)文件,导入该文件以生成合适的 Delphi 接口。本文的示例将使用这种方法。第二种方法,用 Delphi 代码定义接口,使 WSDLHTMLPublish 组件(它是被缺省地添加至 Web 服务数据模块中的组件之一)将 Delphi 接口转换成公共的 WSDL。

>

定义 Web 服务接口和 WSDL
对于这个示例,我想构建这样的 Web 服务,它能够公开公司雇员的数据。这个 Web 服务将被映射到 DB2 中 SAMPLE 数据库内的 EMPLOYEE 表。在如下所示的 SoapEmployeeIntf 单元(请参阅源代码中的 SoapEmployeeIntf.pas 文件)中定义该 Web 服务的 Delphi 接口:


							type            ISoapEmployee =            interface (IInvokable)            ['{77D0D940-23EC-49A5-9630-ADE0751E3DB3}']            function GetEmployeeNames: string;            stdcall;
							function GetEmployeeData (EmpID: string): string;            stdcall;            end;
						

该单元还有一些内部的初始化代码,将接口注册到应用程序内的 SOAP 注册表。编写这个接口的结果是由 Web 服务应用程序生成一个 WSDL 文件,在用浏览器连接到该 Web 服务时会显示介绍性页面来描述这个 WSDL 文件,如 图 1 所示。

图 1. 当通过浏览器连接到该 Web 服务时所显示的关于该服务的描述。单击它即可下载描述该 Web 服务的 SOAP 接口的 WSDL 文件。
Web 服务描述的显示

另一个单元 SoapEmployeeImpl 用以下类提供了这个接口的实现:


						type            TSoapEmployee =            class(TInvokableClass, ISoapEmployee)            public
						function GetEmployeeNames: string;            stdcall;
						function GetEmployeeData (EmpID: string): string;            stdcall;
						end;
					

正如您所见,该类继承了 Delphi 库的 TInvokableClass,并实现了先前定义的接口。Web 服务的实际实现存在于上述两个方法以及一些用来管理正在返回的 XML 数据的助手函数中。

访问 DB2 数据库
dbExpress™ 体系结构提供了对 DB2 数据库的访问,在 Bob Swart 的文章中(位于本网站其它地方)讨论了该问题。这里的情况与 Swart 所描述的不同,因为本示例中的数据集只需读一次,所以可以安全地使用单向数据集,而不使用任何高速缓存。

所有连接性和 SQL 都由一个数据模块来托管,这是一个非可视组件的容器,以下 DFM 文件(在这个清单中只保留了几个关键元素)定义了此容器:


							object DataModule3: TDataModule3            object SQLConnection: TSQLConnection            ConnectionName = 'DB2Connection'            DriverName = 'DB2'            LoginPrompt = False            Params.Strings = (            'Database=SAMPLE'            'User_Name=***'            'Password=***')            VendorLib = 'db2cli.dll'            end
							object dsEmplList: TSQLDataSet            CommandText = 'select EMPNO, LASTNAME, FIRSTNME from EMPLOYEE'            SQLConnection = SQLConnection            object dsEmplListEMPNO: TStringField            object dsEmplListLASTNAME: TStringField            object dsEmplListFIRSTNME: TStringField            end
							object dsEmpData: TSQLDataSet            CommandText = 'select * from EMPLOYEE where EmpNo = :id'            Params = <            item            DataType = ftFixedChar            Name = 'id'            ParamType = ptInput            end>            SQLConnection = SQLConnection            end
							end
						

该数据模块有两个由 SQLDatSet 组件托管的 SQL 查询。第一个查询检索每个雇员的姓名和标识,第二个查询返回给定雇员的整个数据集。但是,我所面临的问题是如何将这些数据返回给远程客户机程序。在本示例中返回的是 XML 文档,而没有使用复杂的 SOAP 数据结构。

转换成 XML
在这个示例中,GetEmployeeNames 方法创建了具有雇员列表的 XML 文档,在文档中将雇员的姓和名作为值,将相关的数据库标识作为属性。这里我省略了助手函数 MakeXmlStr 和 MakeXmlAttribute 的代码,您可以在完整的源代码中找到这些代码,可通过本文的 下载获得完整的源代码:


						function TSoapEmployee.GetEmployeeNames: string;            var            dm: TDataModule3;            begin            dm := TDataModule3.Create (nil);            try            dm.dsEmplList.Open;            Result := '<employeeList>' + sLineBreak;            while not dm.dsEmplList.EOF do            begin            Result := Result + '  ' + MakeXmlStr ('employee',            dm.dsEmplListLASTNAME.AsString + ' ' +            dm.dsEmplListFIRSTNME.AsString,            MakeXmlAttribute ('id', dm.dsEmplListEMPNO.AsString)) + sLineBreak;            dm.dsEmplList.Next;             end;            Result := Result + '</employeeList>';            finally            dm.Free;            end;
						end;
					

第二个方法 GetEmployeeData 使用参数化的查询,并将结果字段格式化成不同的 XML 节点(使用我所编写的另一个助手函数 FieldsToXml,这里未列出):


						function TSoapEmployee.GetEmployeeData(EmpID: string): string;            var            dm: TDataModule3;            begin            dm := TDataModule3.Create (nil);            try            dm.dsEmpData.ParamByName('ID').AsString := EmpId;            dm.dsEmpData.Open;            Result := FieldsToXml ('employee', dm.dsEmpData);            finally            dm.Free;            end;
						end;
					

除了省略了一些次要的细节的情况之外(如果您不了解 Delphi 及其类库,可能会对其中某些细节感兴趣),已经完成了 Web 服务的服务器端代码。您可能想知道与 SOAP 相关的代码在哪里,但答案是这里没有此类代码!正如我们先前所见,对于 WSDL,Delphi 使用向导放置在 SOAP 数据模块中的两个组件(HTTPSoapDispatcher 和 HTTPSoapPascalInvoker 组件)自动地提供了 SOAP 引擎。

编写测试客户机
既然我已经启动并运行了 Web 服务,该是构建与该服务器通信的客户机的时候了。通常这是通过导入定义该 Web 服务的 WSDL 文件实现的。在这个特定案例中,必须将接收到的 XML 数据转换成更易于管理的形式。使用 Delphi XMLMapper 把从 Web 服务接收到的雇员列表转换成可以用 DBGrid 使之可视化的数据集。XMLMapper 是一个相当复杂的工具,我不想在本文中讨论它。目前,只使用本文源代码中可用的客户机程序(在 图 2中显示)。在以后的文章中,我将向您提供如何用 Delphi 编写 SOAP 客户机应用程序的完整详细信息。

图 2. 用来测试 Web 服务的客户机程序
用来测试 Web 服务的客户机程序

结束语
在本文中,我们了解到用 Delphi 构建 Web 服务,连接到 DB2 数据库以获取数据是多么轻松。尽管我们已经生成了 XML,但我们没有涵盖 Delphi 提供的用来支持数据库到 XML 映射的所有技术,此类技术相当多。实际上,在这个示例中,我直接地生成了 XML。一件需要注意的重要事项是:通过用 Kylix 重新编译我所生成的程序,并将它从调试版转换成 Apache 模块,该程序完全可以移植到 Linux 服务器上。这意味着这个领域还有许多可以讨论的问题。请等待下一篇文章,别走开!

广告位置