打印本文 打印本文  关闭窗口 关闭窗口  
VFP与ASP相结合开发Web数据库应用
作者:佚名  文章来源:不详  点击数  更新时间:2008/10/22 21:40:38  文章录入:杜斌  责任编辑:杜斌

  1.VFP与Web数据库应用

  ----作为最成功的大众数据库,Foxpro简便易学,有广大的用户。随着VFP 5.0的推出,VFP已经成为一个强大的企业级开发工具。它不仅可以开发文件/服务器(F/S)数据库应用,也可以开发C/S应用,这时VFP作为一个前端工具,后端可以是SQL Server,Sybase等数据库Engine。通过Remote View和SQL Passthrough函数,VFP可以像操作本地数据一样,方便地处理服务器端数据。----在Internet/Intranet影响日益巨大的今天,开发Web数据库应用成为引人关注的技术。Web数据库应用有一个天然的多层C/S结构。在这个结构中,客户端(Client)仅由Browser组成,几乎没有软件维护和升级的问题。来自Client的请求发送到WebServer,我们只须开发WebServer端软件,处理请求,与数据库服务器交互、并把结果返回Client,系统维护和升级非常方便。只要允许,任意一个客户都可以通过Internet或Intranet访问我们的数据。

  ----VFP完全具备开发Web数据库应用的能力。不过有意思的是,这次VFP被推到了后台,在数据库服务器上专门处理数据存取和实现商业逻辑。数据库服务器和WebServer可以运行在同一个网络服务器上,或者运行在由高速通道连接的两台网络服务器上(如NT Server),这样网络传输瓶颈不再存在。并且借助NTServer的安全管理,客户并不能直接接触VFP数据库,而是通过WebServer存取数据,VFP数据库的安全特性得以大大提高,而此两项一般认为是VFP的重要弱点。

  2.ASP(Active Server Page)与VFP的组件技术

  ----Web数据库应用可以由CGI、ISAPI、IDC、ASP等实现。其中ASP的功能最为强大,在其中可以混用HTML、DHTML、ActiveX、VBSsript或JavaSript,特别是可以使用服务器端组件。此服务器端组件可以用VFP、VB、VC++、Delphi等任意支持COM技术的语言编写,以实现用户特定的商业逻辑。如果不出意外,ASP将成为主流技术。目前有Microsoft的IIS(Internet Information Server,NT Server)和PWS(Personel Web Server,Win95)支持ASP。----在传统的F/S或C/S应用中,组件作为面向对象的编程风格,你可以随自己的喜好,采用或不采用它。然而在ASP中使用VFP,组件(一个OLE Server DLL)是你唯一的选择。你的处理过程都应封装在一个或多个组件中。

  3.使用的环境和工具

  ----对于ASP,需要WinNT4.0(ServicePack3)、IIS3.0(WinNT自带)、Visual InterDev1.0。也可以是:Win95、PWS(Visual InterDev1.0中提供)、Visual InterDev1.0。----为了使IIS或PWS支持ASP,在安装Visual InterDev时必须首先在服务器上选择安装其中的Server Components:FrontPage Server Extensions和Active Server Pages,然后在开发服务器上安装Client Components:Visual InterDevClient。也可以把这些都安装在同一台机器上,这样可以在单机上方便地编程、调试。

  4.VFP组件的实现

  ----在VFP中开始一个Project,取名为Classes,然后在此Project中建立一个Program,取名Classdef.prg。它定义了一个OneRecord类,其功能是一条条显示一个数据库,具有向前、向后和定位能力。使用一个DBF文件d:\vfpweb\data\booksno.dbf,结构为:
  Field_name Field_type Field_len
  bookno C 16
  bookname C 50
  author C 12
  editor C 14
  pubdate D 8
  charnum N 4.0

  在Classdef.prg 中 键 入 代 码:
  Define class onerecord as custom olepublic
  mcDatapath=""

  function getdatapath
  return (this.mcdatapath)

  function getcurrentno
  return recno()

  function init
  set exclu off
  set century on
  set date to ansi
  return

  function setdatapath
  lparameter cpath
  if type("cpath")< >"C"
  return
  endif
  this.mcdatapath=cpath
  set defau to (cpath)
  if not used("booksno")
  select 0
  use booksno
  else
  select booksno
  endif
  return

  function movenext
  if .not.eof()
  skip
  endif
  return

  function moveprevious
  if .not.bof()
  skip -1
  endif
  return

  function destroy
  use
  *clear all &&clear all 将 挂 起 服 务 器
  return

  function iseof
  if eof()
  return .t.
  else
  return .f.
  endif

  function isbof
  if bof()
  return .t.
  else
  return .f.
  endif

  function getbookno
  return bookno

  function getpubdate
  if empty(pubdate)
  return ""
  else
  return pubdate
  endif

  function geteditor
  return editor

  function getbookname
  return bookname

  function goto
  lparameter recnum
  if type("recnum")< >"N" &&error data type

  return
  endif
  if recnum< 1 .or. recnum >reccount()
  return
  else
  goto (recnum)
  endif
  return
  EndDefine

  ----在菜单Project,选中SetMain,然后Build,在Build对话框中选BuildOLEDLL。好了,我们到此就完成了一个OLE Server,并且它已经自动注册在我们的机器上。我们可以在菜单Project|ProjectInfo弹出的Project Information对话框中看到这个组件的信息:
  Server Classes:onerecord
  Project Name:Classes
  OLE

  ---- Server 的 引 用 方 法 是createobject("ProjectName.ClassName"), 对 于 我 们 这 个 组 件, 就 是:createobject("classes.onerecord")。 可 以 直 接 在VFP 的Command 窗 口 中 交 互 式 地 测 试 之, 在Command 窗 口 中 键 入:
  ox=createobject("classes.onerecord")
  ox.setdatapath("d:\vfpweb\data")
  ?ox.bookname
  ?ox.getbookname
  ox.movenext
  ?ox.getbookname
  ox.goto(30)
  ?ox.getbookname

  ----可以直接看到执行结果,最后不要忘了释放该组件:
  release ox

  ----这个组件是针对特定数据库进行操作的,测试很方便。下面,我们再实现一个更为一般的类ClsQ2T,其功能是任意指定一条SQL查询语句(针对任意一个或多个数据库),将查询结果以表格的形式显示在Web页面上,其中使用了ASP的接口。它不仅封装了数据处理,而且通过ASP接口,也封装了数据显示。----仍在Classdef.prg之中,接着最后一行代码,键入:

  define class clsq2t as custom olepublic
  mcontext=.null.
  function onstartpage(ocontext)
  this.mcontext=ocontext &&对ASP接口的引用
  return
  function init
  set exclu off
  set safety off
  return
  function setdatapath(strpath)
  merrnum=0
  on error merrnum=error( )
  set default to (strpath)
  if merrnum< >0
  return "Error in setdatapath"+message()+chr(13)
  endif
  on error
  return "OK,setdatapath"+strpath+chr(13)

  *函数querytotable要求传入一个SQL Select串,如:
  * "select bookname,editor from booksno where charnum >500"

  function querytotable(querystring)
  merrnum=0
  on error merrnum=error( )
  oResp=this.mcontext.response &&引用ASP对象response
  tempname=SUBSTR(SYS(2015), 3, 10) &&产生唯一的文件名
  &querystring into cursor (tempname)
  if merrnum< >0
  return "Error in querytotable,create sql view"+message()
  +alltrim(str(lineno( )))+chr(13)
  endif
  outstring="< table border=1 >"+chr(13)+"< tr >"+chr(13)
  oresp.write(outstring)
  if merrnum< >0
  return "Error in querytotable,oresp.write"+message()
  +alltrim(str(lineno( )))+chr(13)
  endif
  outstring=""
  fc=fcount()
  for i=1 to fc
  if type("eval(field(i))")="G"
  loop
  endif
  outstring=outstring+"< td >"+field(i)+"< /td >"+chr(13)
  next
  outstring=outstring+"< /tr >"+chr(13)
  oresp.write(outstring)
  outstring=""
  if merrnum< >0
  return "error in oresp.write header"+message()
  +alltrim(str(lineno( )))+chr(13)
  endif
  scan
  outstring=outstring+"< tr >"+chr(13)
  for i=1 to fc
  if type("eval(field(i))")="G"
  loop
  endif
  mt=eval(field(i))
  do case
  case type("mt")="C"
  outstring=outstring+"< td >"+mt+"< /td >"
  case type("mt")="T"
  outstring=outstring+"< td >"+ttoc(mt)+"< /td >"
  case type("mt")="D"
  outstring=outstring+"< td >"+dtoc(mt)+"< /td >"
  case type("mt")$"NY"
  outstring=outstring+"< td >"+alltrim(str(mt,5))+"< /td >"
  endcase
  outstrin=outstring+chr(13)
  next
  outstring=outstring+"< /tr >"+chr(13)
  endscan
  oresp.write(outstring)
  outstring="< /table >"
  oresp.write(outstring)
  use
  on error
  return "OK of querytotable, ended"+chr(13)
  endfunc
  EndDefine

  ----键入代码后Build,在Build对话框中仍选Build OLE DLL,在确认覆盖时选择"Y",在Project Information对话框中看到这个组件的信息已有变化:
  Server Classes:onerecord clsq2t
  Project Name:Classes

  ----加上了新增的clsq2t。----这段代码中较特别的是onstartpage(ocontext),它在每次.asp页面启动时由IIS自动调用,并传入一个参数。该参数是对ASP的一个容器ScriptingContext的引用,通过它可以引用ASP的所有内在对象(Intrinsic Object),如response、reuqest。通过这些内在对象,VFP可以直接读取用户在Web页面上的输入,也可以把结果直接写回Web页面。

  ----组件clsq2t的调试要困难得多。可以在函数querytotable中注释掉与oResp有关的行以及define classclsq2tascustomolepublic和EndDefine两行,然后增加一些代码直接调用各个函数,以进行调试排错。确认无误后再恢复上述各行,并重新Build。

  5.在ASP中使用VFP组件

  ----下面将建立两个ASP页面:Onerecord.asp和Clsq2t.asp测试我们完成的这两个组件。启动Visual InterDev,开始一个新的工程:NewProjects,然后选取Web Project Wizard,在Project Name中输入VFP Classes,点击OK后,Visual InterDev产生一些辅助文件,为新的工程做好准备,然后打开该工程。我们在该工程中首先建立一个HTML页面index.htm,以调用上述两个ASP页面。点击菜单File|New,在New对话框中选Files|HTMLPage,并指定HTML页面的名字:index.htm。Visual InterDev将会为我们产生一个空的框架,在其中用手工加入代码,也可用Visual InterDev附带的FrontPage Editor等可视化工具编辑代码,完成后的HTML页面如下:
  < HTML >
  < HEAD >
  < /HEAD >
  < BODY >
  < p >< a href="Onerecord.asp" >To scan the records< /a >
  < /p >
  < p >To send a query:< br >
  < form action="Clsq2t.asp" method="post" name="input" >
  < input type="submit" name="Btoquery" value="Query" >
  < input type="text" size="40" name="qstring"
  value="Input a query here" >
  < /p >
  < /form >
  < /BODY >
  < /HTML >

  ----index.htm中包括一个到Onerecord.asp的超联接、一个Text用于输入查询语句、一个SubmitButton用于提交查询,点击该Button后将调用Clsq2t.asp。----点击菜单File|New,在New对话框中选Files|ActiveServerPage,新建Onerecord.asp,它使用onerecord组件在Web页面上浏览数据库,代码如下:

  < %@ LANGUAGE="VBSCRIPT" % >
  < html >
  < HEAD >
  < /HEAD >
  < BODY >
  < FORM ACTION="Onerecord.asp" METHOD="POST" ID="scanform" >
  < %set ox=server.createobject("classes.onerecord")
  ox.setdatapath("d:\vfpweb\data")
  if session("currentno")="" then
  session("currentno")=1'first time open the page
  currentno=1
  else
  if isnumeric(session("currentno")) then
  currentno=session("currentno")
  else
  currentno=1
  end if
  end if
  ox.goto(currentno)
  % >
  < %if request.form("cmdnext")< >"" then
  ox.movenext
  end if% >
  < %if request.form("cmdprev")< >"" then
  ox.moveprevious
  end if% >
  < %if isnumeric(request.form("txtgoto")) then
  temp=cint(request.form("txtgoto"))
  ox.goto(temp)
  end if% >
  < %session("currentno")=ox.getcurrentno% >
  < p >
  当前记录:< %=ox.getcurrentno% >< br >
  书 号:< %=ox.getbookno% >< br >
  书 名:< %=ox.getbookname% >< br >
  责 编:< %=ox.geteditor% >< br >
  出版时间:< %=ox.getpubdate% >< br >
  < /p >
  < p >
  < %if not ox.iseof then'如果不是文件未则显示按钮Next% >
  < INPUT TYPE=submit VALUE="Next" NAME="cmdnext" >
  < %end if% >
  < %if not ox.isbof then'如果不是文件头则显示按钮Prev% >
  < INPUT TYPE=submit VALUE="Prev" NAME="cmdprev" >
  < %end if% >
  < %set ox=nothing% >
  < INPUT LANGUAGE="VBScript" TYPE=submit
  VALUE="Goto"
  ONCLICK="if not isnumeric(scanform.txtgoto.value) then
  window.alert("Must input a number")
  window.event.cancelbubble=true
  end if"
  NAME="cmdgoto" >
  < INPUT TYPE=text SIZE=20 NAME="txtgoto" >< /p >
  < a href=index.htm > Return Index< /a >
  < /FORM >
  < /BODY >
  < /HTML >
  

  ----该页面显示数据库当前记录各字段的值,并在页面下方显示三个按钮Next(下一条),Prev(上一条)和Goto。其中使用了Server Side Code(符号<%和%>之间的代码,在服务器端执行),产生组件及对组件各方法和属性的调用;Client SideCode(在客户端执行),在ONCLICK的事件响应中检验用户输入的记录号(必须是一个数字)。由于WebBrowser基于的HTTP是一个无状态协议,它并不知道各客户的当前记录。为了在各个页面调用中记住当前记录号,使用了session对象。session对象在跟踪和保持客户的使用状态上很有用处,感兴趣者可以查阅Visual InterDev的联机帮助。----再新建Clsq2t.asp,它使用使用clsq2t组件在Web页面上显示任意查寻结果,代码如下:
  

  < %@ LANGUAGE="VBSCRIPT" % >
  < HTML >
  < HEAD >
  < /HEAD >
  < BODY >
  < %qs=request.form("qstring")% >
  你输入的查询要求是: < br >< %=qs% >< hr >
  < a href=index.htm > Return Index< /a >< br >
  < %set ox=Server.CreateObject("classes.clsq2t")% >
  < %ox.SetDataPath("d:\vfpweb\data")% >
  < %ox.QueryToTable(qs)% >
  < %Set ox = Nothing% >
  < /BODY >
  < /HTML >

  ----由于输出操作都已封装在组件clsq2t之中,故该组件的使用相当简明。应该指出的是,该组件应该用于开发之中,而不应提供给最终用户,因为不能保证用户输入的SQL Select串的有效和合法。6.调试注意事项

  ----此处两个组件皆是进程内服务器,当有Bug时将会使系统挂起甚至崩溃。----当修改组件代码时,你会发现无法覆盖老的.dll文件。这是因为即使退出Visual InterDev,组件仍被WebServer锁定(这就是为什么VFP试图用clearall释放资源时会挂起服务器)。这时必须停止WebServer并再启动之,在开发过程中可能要如此反复多次。如果系统被挂起或崩溃,WebServer无法响应,这时只有使出最后一招:关机并重新启动。VFP5.0版本的RunTime Library只支持一个实例,就是说:如果上述两个组件在两个不同的prg文件中实现,则它们不能同时被使用。这一点在VFP6.0中已得到改进(但仍是单线程的)。

  7.评述

  ----Web数据库开发更专业化的方法似乎是ASP+VB+ADO(ActiveX Data Object)+SQLServer。其中ADO不仅可用于Web数据库开发,也可用在VB、VFP中替代DAO、RDO开发传统的C/S应用,功能更为强大。然而对于中小企业来说,VFP简便易用,对资源要求不高,而且我国很多高校学生都学习过Foxbase或Foxpro,他们可以很快掌握VisualFoxpro,故可以比较容易地找到编程和系统维护人才。VFP用于开发Internet/Intranet是一个较好的选择,国外已有许多大型应用的成功凡例。

  相关链接:

  2008年下半年全国计算机等级考试报名信息汇总

  更多信息请访问:计算机等级考试站 计算机等级考试在线题库 计算机等级考试论坛

打印本文 打印本文  关闭窗口 关闭窗口