注:该文章节选自作者的《Visual FoxPro程序设计参考手册》
创建一个Web服务是一个复杂的过程,这涉及到要使用Internet信息服务(IIS)、Visual FoxPro COM服务程序和简单对象访问协议(SOAP)。在这节中将结合上节中介绍的XMLAdapter和在20.4节中介绍的CursorAdapter来建立一个可以通过HTTP进行获取和修改SQL Server 2000附带示例数据库Northwind中Customers表的Web服务实例。该Web服务的流程图18-11所示。可以看出,这是一个3层架构的客户/服务器模式。
图18-11 Web服务流程图
创建Web服务,首先要建立一个COM服务程序,然后才可以使用Visual FoxPro的Web服务发布向导将COM升迁为Web服务。
新建一个名为MyWebService的项目,然后在项目中使用以下代码创建一个叫做MyClass的.prg文件,在其中建立了一个ChangeCustomer类。
DEFINE CLASS ChangeCustomer AS Session OLEPUBLIC
DataSession=2 &&私有数据工作期
PROCEDURE Init
SET MULTILOCKS ON
ENDPROC
PROCEDURE GetCustomerInfo HelpString "获取客户信息"
LOCAL oXMLAdapter AS XMLAdapter,oCA AS String,cXML AS String
oCA=CREATEOBJECT("MyCursorAdapter") &&建立CursorAdapter对象
oCA.CursorFill() &&按oCA的Alias属性指定的名称生成临时表
oXMLAdapter=NEWOBJECT("XMLAdapter") &&建立XMLAdapter
oXMLAdapter.AddTableSchema(oCA.Alias) &&加载临时表到XMLAdapter对象
oXMLAdapter.ToXML("cXML") &&生成XML字符串
RELEASE oXMLAdapter,oCA &&释放对象实例
RETURN cXML &&返回XML字符串
ENDPROC
PROCEDURE UpdateCustomer(cXML AS String) HelpString "更新客户信息"
LOCAL oXMLAdapter AS XMLAdapter,oCA AS CursorAdapter
oXMLAdapter=NEWOBJECT("XMLAdapter") &&建立XMLAdapter
oXMLAdapter.UTF8Encoded=.F.
oXMLAdapter.IsDiffGram=.T.
oXMLAdapter.LoadXML(cXML,.F.) &&加载XML
oCA=CREATEOBJECT("MyCursorAdapter")
oXMLAdapter.Tables(1).ChangesToCursor(oCA.Alias) &&还原缓冲表
oCA.CursorAttach(oCA.Alias) &&将还原出的缓冲表与CursorAdapter建立关联
=TABLEUPDATE(.T.) &&发送更新
RELEASE oXMLAdapter,oCA
ENDPROC
PROCEDURE Error(nError AS Integer,cMethod AS String,nLine AS Integer)
LOCAL cText AS String
cText=cMethod+" 错误号="+LTRIM(STR(nError,5))+" 行号="+LTRIM(STR(nLine,8))+" "+MESSAGE()
COMRETURNERROR(cText,_VFP.ServerName)
ENDPROC
ENDDEFINE
*!* 建立基于CursorAdapter的子类,用于连接到SQL Server
DEFINE CLASS MyCursorAdapter AS CursorAdapter
Alias="Customer"
BreakOnError= .F.
DataSourceType="ODBC"
Tables="Customers"
SendUpdates=.T.
AllowDelete=.T.
AllowInsert=.T.
AllowUpdate=.T.
UpdateType=1 &&发送更新方式为UPDATE
WhereType=1 &&Where子句类型为仅由KeyFieldList属性指定的主关键字段组成
KeyFieldList="CustomerID"
UpdatableFieldList="CustomerID, CompanyName"
UpdateNameList="CustomerID Customers.CustomerID, CompanyName Customers.CompanyName"
BufferModeOverride= 5 &&开放式表缓存
cConnectionString="Driver={SQL Server};Server=localhost;Uid=sa;Pwd=;Database=northwind"
PROCEDURE Init &&类实例化时直接建立连接
This.DataSource=SQLSTRINGCONNECT(This.cConnectionString, .T.)
This.SelectCmd="SELECT CustomerID, CompanyName FROM Customers"
This.CursorSchema ="CustomerID C(5), CompanyName C(40)"
ENDPROC
FUNCTION Destroy() &&在释放对象时断开与SQL Server的连接
SQLDISCONNECT(This.DataSource)
ENDFUNC
ENDDEFINE
上面代码中的GetCustomerInfo( )方法用于将Customers的CustomerID和CompanyName字段中的所有内容以XML格式返回给客户端;UpdateCustomer( )方法根据客户端发送来的Diffgrams格式的XML更新到Customers表。
在17.4.2节中详细介绍了编译COM对象的方法与原理,因此这里只简单介绍步骤。在正式编译前,需要预编译一下自动服务程序,才可以设置自动服务程序的项目信息。单击项目管理器的Build(编译)命令按钮,打开Build Options(编译选项)对话框,选择Multi-threaded COM server(多线程COM服务程序)选项进行连遍,编译成功后,该COM组件自动在本地计算机的Windows中注册并可用。
在项目管理器上单击鼠标右键,在弹出的快捷菜单上选择Project Info(项目信息)菜单项,打开如图18-12所示Project Information对话框,在Servers选项卡的Instancing(实例)下拉列表中选择服务类型为Multi Use(多重使用)。
单击项目管理器中的Build按钮重新连编项目为Multi-threaded COM server。
要在服务器上发布Web服务,需要IIS的支持。IIS在Windows XP中是作为可选组件提供的,可以在Windows的控制面板中双击“添加或删除程序”图标打开“Windows组件向导”对话框,在组件列表中复选“Internet信息服务(IIS)”组件,并单击“下一步”按钮进行安装,如图18-13所示。安装成功后,可以打开Internet Explorer浏览器,在地址栏中输入“http://127.0.0.1”,可打开默认的站点页面。
图18-12 设置服务类型
图18-13 添加IIS组件
在安装好IIS后,应该为要发布的Web服务建立一个虚拟目录,以方便调用,步骤如下:
(1)在控制面板中双击“管理工具”图标,打开“管理工具”窗口。
(2)在“管理工具”窗口中双击“Internet信息服务”图标,打开“Internet信息服务”窗口,如图18-14所示。
(3)在“默认站点”节点上单击鼠标右键,在出现的快捷菜单中,选择“新建”菜单项下的“虚拟目录”选项,打开“虚拟目录创建向导”对话框,如图18-15所示。
(4)单击“下一步”按钮,在出现的如图18-16所示的“别名”文本框中为虚拟目录指定一个名称“FoxWebService”,通过该名称可以引用一个硬盘上的实际物理目录。
(5)单击“下一步”按钮,在出现的如图18-17所示的“目录”文本框中指定一个存放Web服务内容的实际物理目录。
(6)单击“下一步”按钮,将出现如图18-18所示的设置目录权限画面,如图设置后,单击“下一步”按钮,在出现的画面中单击“完成”按钮,虚拟目录将被成功创建到“默认网站”节点中,如图18-19所示。
图18-14 “Internet信息服务”窗口
图18-15 “虚拟目录创建向导”对话框
图18-16 建立虚拟目录别名
图18-17 设置物理目录
图18-18 设置目录权限
图18-19 虚拟目录添加完成后
可以使用Visual FoxPro的Web Service向导来创建和发布Web服务,步骤如下:
(1)选择Visual FoxPro Tools菜单中Wizards菜单项下的Web Service子菜单项,打开XML Web Services Publisher(Web服务发布器)对话框,如图18-20所示。在COM Server(COM服务程序)下拉选项框中选择要发布的.dll组件,如果组件没有包含在列表中,可以单击后面的省略(…)按钮进行选取。
(2)单击对话框中的Advanced(高级)按钮打开如图18-21所示的XML Web Service Location(Web服务位置)对话框,在Select Location下拉选择要发布的虚拟目录位置。
图18-20 XML Web Services Publisher对话框
图18-21 XML Web Service Location对话框
(3)虚拟目录选择正确后,单击图18-21中的Select(选择)按钮,将打开可对Web服务的Options(选项)、Methods(方法)和Namespaces(命名空间)进行设置的对话框。具体设置分别如图18-22、图18-23、图18-24所示。完成后单击OK按钮返回到如图18-20所示的对话框。
(4)单击图18-20所示的Generate(生成)按钮将创建并发布Web服务,在Visual FoxPro生成Web服务的文件后,出现Web服务发布结果对话框,显示一个包含COM server、.WSDL文件、ISAPI或ASP 侦听的编译结果列表。如图18-25所示。
图18-22 设置Web服务选项
图18-23 设置Web服务支持的方法
图18-24 设置Web服务的命名空间
图18-25 Web服务发布结果
在Web服务发布成功后,将在图18-21的File Output Path(文件输出路径)文本框中指定的目录中生成3个文件(2个.wsml文件和一个.wsdl文件),在该示例中,所生成的文件是ChangeCustomer.WSDL、ChangeCustomer.wsml和ChangeCustomerClient.wsml。这3个文件都是XML文件,可以直接在浏览器或文本编辑器中查看。
当在IntelliSense中注册Web服务后,在书写有关已注册Web服务的程序代码时,IntelliSense可以随时进行代码输入提示。注册步骤如下:
(1)选择Visual FoxPro Tools菜单下的IntelliSense Manager菜单项,打开IntelliSense Manager窗口,如图18-26所示。
(2)单击Type页框中的Web Services按钮,在打开的对话框的WSDL URL Location(WSDL URL位置)文本框中输入所建立WSDL文件的URL,如图18-27所示。然后单击Register按钮进行注册。
图18-26 IntelliSense Manager窗口
图18-27 指定WSDL URL并注册Web服务
在Visual FoxPro中可以通过SoapClient30对象调用Web服务,SoapClient30对象为客户端提供了一种通过SOAP协议发送请求到服务器端并处理服务器应答的高级接口。其使用方法如下:
oSoapClient=CREATEOBJECT("MSSOAP.SoapClient30") &&建立对象
在建立SoapClient30对象后,应该使用对象的MSSoapInit( )方法来初始化对象,在初始化期间,所有可在认证服务器(认证服务器在WSDL文件中指定)上的指定的操作将绑定SoapClient30对象,所以,这时就可以使用SoapClient30对象调用在服务器中定义的操作了。MSSoapInit( )方法的语法格式如下:
oSoapClient.MSSoapInit(WSDLFile,ServiceName,Port,WSMLFile)
参数说明如下:
WSDLFile
字符型。该参数是WSDL文件的URL,用于描述由服务器提供的服务,或者是包含在WSDL文件中的一个字符串。如果该参数的第一个字符是“<”,表示该参数值是一个WSDL字符串;否则,表示该参数值是一个WSDL文件。
ServiceName
字符型。可选的。该参数是在WDSL文件中的服务。如果忽略该参数、或为NULL、或为空字符串(""),在初始化SoapClient30对象时,则使用在WSDL文件中指定的第一个服务。
Port
字符型。可选的。该参数是在WSDL文件的端口名称,用来包含在SOAP请求信息中的指定操作。如果忽略该参数、或为NULL、或为空字符串(""),在初始化SoapClient30对象时,则使用在WSDL文件中指定的第一个端口。
WSMLFile
字符型。可选的。该参数是WSML文件的URL,在使用自定义类型映射程序时,该参数是必须的。
现在的问题是如何获得这些参数名称?使用浏览器或其他文本编辑器中打开所生成的WSDL文件,如图18-28所示。其中的service元素便是服务的名称,port元素是端口名称。
图18-28 ChangeCustomer.WSDL文件片段
由于在该示例中只建立了一个服务,所以,可以只指定WSDLFile即可。例如,下面的语句可以Web服务调用在COM组件中的GetCustomerInfo( )方法来获得Customers表中数据。
oSoapClient=CREATEOBJECT("MSSOAP.SoapClient30")
oSoapClient.MSSoapInit("http://CCB-ZHJ/FoxWebService/ChangeCustomer.WSDL") &&初始化SoapClient30对象
cXML=oSoapClient.GetCustomerInfo() &&获得XML格式的Customers表中的数据
?cXML
新建一个如图18-29所示的表单。在“读取数据”按钮的Click事件中加入下列代码,用于从SQL Server数据库中读取信息,并在表格Grid1中显示出来。
oSoapClient=CREATEOBJECT("MSSOAP.SoapClient30")
oSoapClient.MSSoapInit("http://CCB-ZHJ/FoxWebService/ChangeCustomer.WSDL")
cXML=oSoapClient.GetCustomerInfo() &&获得XML格式的Customers表中的数据
RELEASE oSoapClient
SET MULTILOCKS ON
IF USED("curCustomer") &&关闭表
USE IN curCustomer
ENDIF
*!* 将XML转换为临时表
oXMLAdapter=CREATEOBJECT("XMLAdapter")
oXMLAdapter.LoadXML(cXML,.F.)
oXMLAdapter.Tables(1).Alias="curCustomer"
oXMLAdapter.Tables(1).ToCursor()
SELECT curCustomer
=CURSORSETPROP("Buffering",5)
*!* 设置表格
WITH Thisform.Grid1
.RecordSourceType=1
.RecordSource="curCustomer"
.ColumnCount=2
.Columns(1).Header1.Caption="客户编号"
.Columns(1).ControlSource="curCustomer.CustomerID"
.Columns(1).Width=80
.Columns(2).Header1.Caption="公司名称"
.Columns(2).ControlSource="curCustomer.CompanyName"
.Columns(2).Width=200
ENDWITH
Thisform.Refresh
在“发送更新”按钮的Click事件中加入下列代码,用于将Grid1中经过编辑的数据发送到SQL Server服务器并更新数据。
*!* 生成Diffgrams格式的XML文档
oXMLAdapter=CREATEOBJECT("XMLAdapter")
oXMLAdapter.AddTableSchema("curCustomer")
oXMLAdapter.RespectCursorCP=.T. &&与UTF8Encoded配合设置按临时表的代码页进行编码
oXMLAdapter.UTF8Encoded=.F.
oXMLAdapter.IsDiffgram=.T. &&设置按Diffgram格式输出
oXMLAdapter.ToXML("cXML",,.F.,.T.,.T.) &&保存变动内容到cXML变量
*!* 发送更新
oSoapClient=CREATEOBJECT("MSSOAP.SoapClient30")
oSoapClient.MSSoapInit("http://CCB-ZHJ/FoxWebService/ChangeCustomer.WSDL")
oSoapClient.UpdateCustomer(cXML)
RELEASE oSoapClient
执行表单并单击“读取数据”按钮,效果如图18-30所示。数据编辑后,可以单击“发送更新”按钮进行保存。
图18-29 XML Web服务示例
图18-30 表单执行效果
当一个Web服务程序在本地计算机中调试完毕后,需要将其分发到实际的Internet服务中。
手动分发Web服务是一个复杂的过程,步骤如下:
无论是在客户端还是在服务器端,Visual FoxPro都需要SOAP Toolkit 3.0的支持,才可以使用或提供Web服务。可以从http://msdn.microsoft.com/webservices/downloads/下载最新的安装版本。
Visual FoxPro程序需要运行库的支持,这些文件包括:VFP8T.DLL、VFP8R.DLL、VFP8RCHS.DLL、MSVCR70.DLL、GDIPLUS.DLL和MSXML3.DLL。可以将这些文件复制到与COM组件相同的目录下。
在将WSDL文件分发到服务器之前,应该将图18-26中所示的<soap:address location="http://CCB-ZHJ/FoxWebService/ChangeCustomer.WSDL" />更换为服务器实际的URL,如:<soap:address location="http://www.vfptop.com/FoxWebService/ChangeCustomer.WSDL" />。
将COM组件和先前生成的ChangeCustomer.WSDL、ChangeCustomer.wsml和ChangeCustomerClient.wsml文件一同复制到服务器的指定目录中,并将COM组件注册,注册方法请参考17.4.3中的介绍。
在服务器上建立虚拟目录的方法请参考前面的介绍。建立虚拟目录后,应该将WSDL文件类型映射到SOAP的wsdlgen3.dll支持库(这在使用Visual FoxPro的Web Service向导发布Web服务时,向导会自动做这项工作)。建立映射的方法是从Windows的“开始”菜单进入MS-DOS,并定位到C:/Program Files/MSSOAP/Binaries目录下,执行SOAPVDIR.CMD脚本命令,该命令的语法格式如下:
SOAPVDIR.CMD [command VdirName [DirectoryPath]] [-s:server][-w:root]
参数说明如下:
command
指定要执行的命令,可以是CREATE、UPDATE或HELP。其中,CREATE指定建立一个新虚拟目录并映射.wsdl扩展名到SOAP Toolkit 3.0 ISAPI处理程序(SOAPIS30.dll);UPDATE指定更新一个已存在虚拟目录的.wsdl扩展名到SOAP Toolkit 3.0 ISAPI处理程序的影射;HELP指定提供有关SOAPVDIR.CMD脚本的详细帮助。
VdirName
指定虚拟目录名称。
DirectoryPath
可选参数。指定虚拟目录指向的物理目录路径,在使用CREATE 命令时应该指定该路径。
-s
可选参数。指定一个网络服务器实例,1是默认服务器。
-w
可选参数。指定根虚拟目录,root是默认虚拟目录。
例如,要映射.wsdl扩展名到FoxWebService虚拟目录,命令格式和执行结果如图18-31所示。
图18-31 建立.WSDL到wsdlgen3.dll的映射
也可以使用Visual FoxPro附带的InstallSheild Express来分发Web服务,这个工具可以帮助你做大部分的工作,如Visual FoxPro安装运行时刻库、注册COM组件、SOAP等。但是你仍旧需要自己动手建立虚拟目录和建立.wsdl到SOAP的映射。有关InstallSheild Express的详细使用方法请参考24.2.1节的介绍。