用vfp编写Web Service(一)

写在前面

半年来,一直想写一篇关于用 Visual FoxPro 7 编写 Web Service 的文章,但总不成愿。这回不是我偷懒,为了了解这种新技术我和我的朋友们经历了种种“磨难”。这里略作回忆,也算是新春来临之际对“往年”的回眸——算是没有浪费太多的生命。

磨难一:发布向导不能正确发布Web Service。

7月份就拿到了 Visual FoxPro 7,查遍Sample,没有发现有关于 Web Service 的 Demo。但在Help里以及微软对 Visual FoxPro7 的宣传里,都信誓旦旦的:我们支持开发 Web Service…… 还好在 Msdn 里看到了一篇名为《Creating Web Services with Visual FoxPro》的文章。真的很不幸,按部就班做实验却不能正确发布 Web Service。经过反复研究,我认为这是一个 Bug,还好发现了能绕过这个Bug的路径。这个时候已经是10月份了……

磨难二:原来 Web Service 是无状态的!

真是浪费生命啊,还好我已经不是专业的 Visual FoxPro 程序员了,业余的消闲,没有压力。大家记得BOE上的我写的《Visual FoxPro 7 全新登场-- XML 在 COM 组件数据集传递中 的意义》一文吗?那篇东西的示例,原本是为本文的 Web Service 准备的:当代码仅编译为 COM 被使用时,一切都在我的设想中;而进一步发布为Web Service,怪问题产生了—— Web Service 不能记忆我对它命令。经研究原来 Web Service 是“无状态”的(“无状态”在前几年就看到过了,当时无法理解。没想到现在 Web Service 帮我理解了这个概念,也算因祸得福)。

磨难三:Xmltocursor()对中文支持有问题!

自以为已经能用 Visual FoxPro 编写一些小的 Web Service 应用了,于是向一位网友鼓吹:用Web Service做你那个应用吧!人家很仔细,第二天就告诉了我一个大问题:用 xmltocursor() 没法正确处理包含中文的 xml 文档,很多中文字符会被截断!昏倒,又是一个Bug!那个时候微软已经宣布将要发布Visual FoxPro7的SP1,于是我就一边等待SP1,一边寻找其他的解决方案。黄天不负有心人,west-wind竟然提供了这么一套类库wwXML,功能比Visual FoxPro7对XML的支持更强大,对中文支持也很好!

(经过测试,Visual FoxPro 7 的 SP1 已经解决了对中文字符的处理的问题)

磨难四:SP1竟然这么难安装!

1月16号,微软发布了 SP1。鬼知道,他们的安装程序是怎么做的——只能在Win9x下正确安装,win2000、xp 下都不行(听说有人在 Win2000 下成功安装了 SP1,真佩服他们的运气……)。还好论坛的 QXF 同志,把他在 win98 下安装的sp1后发现的更新文件打了包,分发给大家。现在,如果你装不上SP1 的话,只要在计算机里作如下处理就行了。

1.关闭Visual FoxPro7
2.拷贝文件DW15.EXE、DWINTL.DLL到Visual FoxPro7的HOME()目录。
3.在计算机里查找并替换VFP7.EXE、VFP7R.DLL、VFP7T.DLL、VFP7RENU.DLL、VFP7Runtime.MSM、VFPOLEDB.DLL、VFPOLEDB.MSM

闲话就说那么多了,让我们开始吧!

系统要求

1.各种版本的 Win2000及 Win Xp,并安装 IIS (其他版本的Windows没有试过)
2.安装Visual FoxPro7,建议安装SP1
3.安装 SOAP Toolkit 2.0(在 Visual FoxPro 7 安装盘里就有)
4.SQL Server 7 或者 SQL Server 2000

范例介绍

数据源

这个 Web Service 提供了两个数据查询的方法,分别是:检索系统中所有发票的功能以及查询某段时间中销售总额的功能。

我采用了SQL Server 的Demo数据库NorthWind为数据来源,为了凸现Visual FoxPro的威力,我有把这个数据库转换成为Visual FoxPro的本地DBC库。数据库的名称是:web_service.dbc,包含着13个表,这与SQL Server 里的NorthWind数据库是一致的!

好了,我们现在有两个一样的数据来源,一个是本地的DBC,另一个是远程的SQL Server数据库。在待会的试验中,我们会同时在这两个数据源中查询数据,大家就会看到 Visual FoxPro 在远程(异构)数据处理上的简便、灵活。

还有一些工作要做。我们知道,Visual FoxPro 访问远程数据库的方法是Remote View(远程视图) 和 SPT。其中 Remote View 是很有特色的,它的数据源是远程数据,但它本身又是本地 DBC 的成员,这样就能实现 Visual FoxPro 对远程数据源的快捷管理、完美融合。

这里根据需要我们要建立三个Remote View,分别对应 NorthWind数据库里的Orders、Order details 表和视图 invoices:可以通过如下命令完成:

CREATE SQL VIEW orders_sql REMOTE CONNECTION localSQLServer as select * from orders
CREATE SQL VIEW Order_details_sql REMOTE CONNECTION localSQLServer as select * from [order details]
CREATE SQL VIEW invoice_sql REMOTE CONNECTION localSQLServer as select * from invoices

这里用到连接“localSQLServer” 可以用如下命令生成:(大家可根据各人系统不同情况建立合法的连接!)

CREATE CONNECTION LocalSQLServer CONNSTRING "DRIVER=SQL Server;SERVER=BOEWORKS;UID=sa;PWD=;DATABASE=Northwind"

在试验中,我们还要用到由本地数据所产生的Local View(本地试图),它的效果与 invice_sql 一致,只不过前者的数据来源于本地的DBC,后者来源于SQL Server的NorthWind数据库。可以用如下代码实现:(如果你用视图设计器设计这个视图,你会发现视图设计器“报错”,这是因为:Visual FoxPro 的视图设计器不支持太过复杂的 SQL 语句。所以设计复杂视图时,应该直接手写代码,其实这也是众多SQL高手的通常做法!)

CREATE SQL VIEW invoice_vfp as ;
SELECT Orders.shipname, Orders.shipaddress, Orders.shipcity,;
Orders.shipregion, Orders.shippostalcode, Orders.shipcountry,;
Orders.customerid, Customers.companyname AS customernam,;
Employees.firstname+" "+Employees.lastname AS salesperson,;
Orders.orderid, Orders.orderdate, Orders.requireddate,;
Orders.shippeddate, Shippers.companyname AS shippername,;
Order_details.productid, Products.productname, Order_details.unitprice,;
Order_details.quantity, Order_details.discount,;
Order_details.unitprice*Order_details.quantity*(1-Order_details.discount) AS extendedprice,;
Orders.freight;
FROM northwind!employees INNER JOIN northwind!orders;
INNER JOIN northwind!customers;
INNER JOIN northwind!shippers;
INNER JOIN northwind!order_details;
INNER JOIN northwind!products ;
ON Order_details.productid = Products.productid ;
ON Orders.orderid = Order_details.orderid ;
ON Orders.shipvia = Shippers.shipperid ;
ON ;
Orders.customerid = Customers.customerid ;
ON Employees.employeeid = Orders.employeeid

基类

#define CL chr(13)+chr(10)
DEFINE CLASS FoxBaseClass as Session
DataSession=2
DataBasePath="D:\Data\"

PROCEDURE Init()
LOCAL cText as String
cText="开启时间"+TRANSFORM(TIME())
STRTOFILE(cText,'c:\FoxWebService.txt',.t.)

ENDPROC

PROCEDURE Destroy
LOCAL cText as String
cText="关闭时间"+TRANSFORM(TIME())
STRTOFILE(cText,'c:\FoxWebService.txt',.t.)
ENDPROC

PROCEDURE OpenDataBase()
OPEN DATABASE this.DataBasePath+"northwind.dbc" SHARED

ENDPROC

PROCEDURE CloseDataBase()
CLOSE DATABASES

ENDPROC

FUNCTION ConnectSQLServer() as Integer
LOCAL iConn as Integer
iConn=SQLCONNECT("LocalSQLServer")
RETURN iConn

ENDFUNC

PROCEDURE DisConnectSQLServer(iConn as Integer)
SQLDISCONNECT(iConn)

ENDPROC

PROCEDURE Error(nError as Integer,cMethod as String, nLine as Integer)
LOCAL cText as String
cText=;
'出错时间:'+transform(datetime())+CL+;
'错误代码:'+str(nError,4)+CL+;
'错误提示:'+message()+CL+;
'错误方法:'+cMethod+CL+;
'错误行号:'+transform(nLine)+CL+CL
strtofile(cText,'c:\FoxWebService.txt',.t.)
comreturnerror("Fox Web Service",cText)
ENDPROC
ENDDEFINE

分析上面的代码,有几点需要讲解:

1.控制本地数据所在的路径

DataBasePath="D:\Data\"

2.打开、关闭本地数据库:

PROCEDURE OpenDataBase()
PROCEDURE CloseDataBase()

3.连接到SQL Server和从SQL Server断开连接(其实本例中没有使用这两个方法,因为我们使用了远程视图。远程视图能够自动控制连接!)

FUNCTION ConnectSQLServer() as Integer
PROCEDURE DisConnectSQLServer(iConn as Integer)

4.出错控制

PROCEDURE Error(nError as Integer,cMethod as String, nLine as Integer)

5.记录对象的建立与摧毁(这是为了证明Web Service是“无状态”的,具体我们等会再说)

具体实现代码

DEFINE CLASS FoxWebService as FoxBaseClass olepublic

FUNCTION GetInvoice(iType as Integer) as string
LOCAL cXML as String

this.OpenDataBase()

IF iType=0 &&SQL Server 数据表
USE invoice_sql ALIAS invoice
ELSE &&Fox 数据库
USE invoice_vfp ALIAS invoice
ENDIF

CURSORTOXML("invoice","cXML",3,48,0,"")
USE IN invoice

this.CloseDataBase()

RETURN cXML

ENDFUNC

FUNCTION GetSumSales(dStart as Date,dEnd as Date) as Double

this.OpenDataBase()
SELECT sum(b.Unitprice*b.Quantity*(1-b.Discount)) as Sumsalse from orders a INNER JOIN order_details_sql b ON a.orderid=b.orderid ;
where a.orderdate>=dstart and a.orderdate<=dEnd into ARRAY result
IF _tally>0 then
RETURN result[1]
ELSE
RETURN 0
ENDIF

this.CloseDataBase()
ENDFUNC

ENDDEFINE

从代码上我们可以发现,FoxWebService 是FoxBaseClass的子类,继承了所有FoxBaseClass的特性。同时它还被赋予了OlePublic关键字,表明它可以编译成为COM对象!

FoxWebService 只有两个方法,分别实现不同的两个功能,具体如下:

功能一:查询所有发票信息,用户可以指定从DBC本地数据库返回信息还是从SQL Server返回信息。

FUNCTION GetInvoice(iType as Integer) as string

当参数 iType 等于 0 时,从SQL Server 里返回Invoice信息;其他情况下,从本地的 DBC里返回Invoice 信息。具体通过调用两个不同的视图来实现:

IF iType=0 &&SQL Server 数据表
USE invoice_sql ALIAS invoice
ELSE &&Fox 数据库
USE invoice_vfp ALIAS invoice
ENDIF

到这里,大家也许会问了,怎么把一个数据集合(表)返回出去,这个问题我在《Visual FoxPro 7 全新登场-- XML 在 COM 组件数据集传递中 的意义》一文里已经讲的很清楚了:用cursortoxml()把数据集合转化成为XML字符串返回:

CURSORTOXML("invoice","cXML",3,48,0,"")

功能二:返回一个时间段内的销售金额合计

如果您研究过数据库结构的话,这句查询是很容易完成的。但这里我加了一个有意思的要求:销售主档(orders)的数据要来源于本地的DBC,销售明细(Order Details)的数据要来源于远程 SQL Server 表。且不论这个要求是否合理(这里,我们只谈论技术实现),这显然是异构数据库之间的关联查询:用了Visual FoxPro 可以简单的实现:

SELECT sum(b.Unitprice*b.Quantity*(1-b.Discount)) as Sumsalse from orders a INNER JOIN order_details_sql b ON a.orderid=b.orderid ;
where a.orderdate>=dstart and a.orderdate<=dEnd into ARRAY result
IF _tally>0 then
RETURN result[1]
ELSE
RETURN 0
ENDIF

看到了吗?很简单——我这里实际上是关联了本地的Orders表与远程视图order_details_sql。order_details_sql打开时,Visual FoxPro会自动的通过ODBC 读取 SQL Server 上的有关数据,所以连接本地的Orders表与远程视图 order_details_sql 就等于直接连接异构数据表。这一点在其他语言中是很难实现的,它们也可以读取不同的数据源的数据,但它们无法支持异构数据在本地的SQL连接,它们只能用“循环+条件判断”的方式实现“异构数据”的连接。

编译并发布 Web Service

编译 Web Service

这个过程大家应该是非常熟悉了,其实就是编译成通常的COM。通过下面的命令就可以实现:

BUILD MTDLL First_web_service FROM First_web_service

好了,就这样容易——COM组件做好了,我们可以调用一下,在Command窗口中:

*请务必保证 C 盘根目录中不存在FoxWebService.txt文件,如果有就删除它(我们的目的是证明COM组件是“有状态”的)
*建立COM对象
ox=CREATEOBJECT("first_web_service.FoxWebService")
*测试GetInvoice
XMLTOCURSOR(ox.GetInvoice(0),"test")
*测试GetSumSales
?ox.GetSumSales({^1997-01-01},{^1997-3-30})
*摧毁COM对象
rele ox

如果测试成功了,就请查看C 盘根目录中的 FoxWebService.txt 文件,我的文件中的内容是(根据试验时间,结果会有不同):

开启时间23:20:54关闭时间23:21:25

这是由FoxWebService对象的 Init 和 Destory 事件中的代码产生的:Init当类被实例化为对象时触发,Destory当对象被摧毁时触发。在COM 应用中,CreateObject()和rele 分别触发了这两个事件!

好了,记住这里的结果。我们继续……

时间: 2024-12-02 07:19:22

用vfp编写Web Service(一)的相关文章

用vfp编写Web Service(二)

发布Web Service 在IIS中建立虚拟目录 这个步骤很简单,建立一个虚拟目录.设定好以后的属性页是: 图一 这里我只设定了两个属性,其他保持默认状态.设名称为:First_web_service,设本地路径为DLL所在路径,这里是:D:\VFP7_Web_Service. 在Visual FoxPro 里发布 Web Service 工具-〉向导-〉Web Services 图二 弹出如下界面: 图三 这里,COM Server里,我们选择刚才编译的那个DLL. 为了获得更多信息,按"A

在.NET里使用Visual FoxPro资源-vfp编写的Web Service

第三部分:在.NET里使用vfp编写的Web Service .NET和JAVA都以能够跨越不同平台作为卖点,JAVA似乎注重代码本身的跨平台特性..NET则更关注数据的跨平台,于是 .NET高举着XML Web Service的大旗出现在我们面前,从某种意义上说 .NET 就是 XML Web Service. Visual FoxPro 对XML Web Service 的支持是建立在MS XML与SOAP组件基础上的,用Visual FoxPro 编写 Web Service的核心就是上文

Web Service——下一代的WWW[转]

web Web Service一词似乎一夜之间就热了起来.所谓的Web Service是指由企业发布的完成其特别商务需求的在线应用服务其他公司或应用软件能够通过Internet来访问并使用这项在线服务. Web Service是下一代的WWW它允许在Web站点上放置可编程的元素能进行基于Web的分布式计算和处理.Web Service的发展非常迅速这个新规范SOAP.WSDL 和 UDDI的构建模块仅仅才出现了几个月就已经对设计.开发和部署基于 Web 的应用产生了巨大的影响软件产业的巨头和In

Web Service——下一代的WWW

web Web Service一词似乎一夜之间就热了起来.所谓的Web Service是指由企业发布的完成其特别商务需求的在线应用服务其他公司或应用软件能够通过Internet来访问并使用这项在线服务. Web Service是下一代的WWW它允许在Web站点上放置可编程的元素能进行基于Web的分布式计算和处理.Web Service的发展非常迅速这个新规范SOAP.WSDL 和 UDDI的构建模块仅仅才出现了几个月就已经对设计.开发和部署基于 Web 的应用产生了巨大的影响软件产业的巨头和In

手把手教你学Web Service

Well,各位观众,现在开始我的手把手交Visual Studio.net的第一课―-手把手教你学Web Service.有没有下一课还得看诸位看官的反应了!我们知道,在MS新一代战略.net中,Web Service占了一个相当次大的份量,为什么这样说那?那是因为Web Service 是未来编程的新 思路,他将编程由本机扩大到了Internet上,他通过一个proxy.dll就可以访问在Internet上 提供的Service,并且就像在本机上操作一样方便,其实,Web Service也可以

用Web Service传送文件(二)

更多话题 今天是 2002年7月20日.一个星期前,我推出了本文,得到了一些朋友的相应.他们提出了一些问题,我希望通过续写此文一并作答. 实现文件上传 朋友们问我,你的示例代码里只有文件从服务器下载到客户端的介绍,是不是在暗示 Web Service 不能实现文件从客户机上传到服务器?不是,这是我的疏忽,本来应该提到 "文件上传" 的问题! 其实这里所谓 "文件上传" 是很简单的,只不过是 "文件下载" 的逆向思维!客户端把文件读起,并转换成为

用Web Service传送文件(一)

开篇 去年,第一次编写 Web Service 的时候,我就有个疑问:这玩艺儿能不能传送文件! 在实际开发中传写文件是经常性的需求,Visual FoxPro 程序员要在 Internet 上做这件事情,通常是用电子邮件或者是FTP的方式,那么 Web Service 能不能提供一种新方法呢? 当然可以用 Web Service 传送文件,这就是今天我们讨论的主题. 在开始之前,要感谢 将来是我.漫步者和 BOBY 在有关技术上对我的帮助,将这篇文章献给你们!!! 把文件转化为文本 Base64

通向架构师的道路(第十天)之Axis2 Web Service(一)

一.Axis2简介 1.1介绍Axis2 Axis框架来自 Apache 开放源代码组织,它是基于JAVA语言的最新的 SOAP 规范(SOAP 1.2)和 SOAP withAttachments 规范(来自 Apache Group )的开放源代码实现.有很多流行的开发工具都使用AXIS作为其实现支持Web服务的功能,例如JBuilder以及著名的Eclipse J2EE插件Lomboz.AXIS的最新版本可以从 http://ws.apache.org/axis/index.html下载.

简单的Web Service(自己试过MyEclipse XFire写过)

本Guide利用Eclipse以及Ant建立一个简单的Web Service,以演示Web Service的基本开发过程:   1.系统条件: Eclipse Java EE IDE for Web Developers Java SE 6 Windows XP 2.基本环境搭建: 1)Java SE6 JDK的安装:下载Java SE6 JDK,双击,安装默认选项进行安装即可. 2)Eclipse的安装与配置:     安装时直接解压.      配置处有两点,Window>Preferenc