用asp创建互联网应用程序.doc_第1页
用asp创建互联网应用程序.doc_第2页
用asp创建互联网应用程序.doc_第3页
用asp创建互联网应用程序.doc_第4页
用asp创建互联网应用程序.doc_第5页
已阅读5页,还剩8页未读, 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

用asp创建互联网应用程序使用单机版应用软件的时代很快就要过去了,现在大部分的应用程序都开发出网络版或大都需要共享网络上丰富的数据资源。我们编写了很长时间基于客户端/服务器(C/S)的应用程序(比如pb),但是这些程序大部分只是运行在小型的局域网内部。然而,有很多客观的原因要求我们要修改这些程序以使它们能够运行在一个企业的内部网甚至是国际互联网。需要开发这类程序的原因在于:首先,随着一个企业的规模逐渐扩大,公司可能会跨地区甚至跨国经营,每个分公司的员工的数量也会逐年增多,这些在外地的员工肯定需要频繁地访问总公司的数据库资源;其次,集中应用程序的数据资源,能够使你更好的监控数据库的访问和使用情况;第三,你可以通过从一个集中的位置获取全局应用程序设置,从而维护和更新它们,最终达到缓减应用程序更新的目的;第四,尽量从Web服务器上访问数据库而不是从客户端上访问数据库,这样可以避免通过网络传送登录信息和客户密码,从而避免安全隐患;而且,使用浏览器从后台获取数据,这样能够避免刷新整个页面;最后,浏览器/服务器(B/S)结构的程序在客户端不必安装特殊的程序,只要使用一般的浏览器就可以了。这就要求我们创建一个运行于互联网上的应用程序,而假如想创建一个运行在HTTP协议上的VB程序,那么关键就是使用XML和XMLHTTPRequest对象。这个对象是Microsoft XML分析器(msxml.dll)的一部分,XMLHTTPRequest对象可以通过HTTP向远程服务器发送GET和POST请求,运行在远程服务器上的程序接收这个请求,翻译出它的内容,返回数据或者一个错误页面到调用它的应用程序。想要修改一个完全独立的客户端单机版程序从而达到以上目的是不现实的,但即使如此,从一个集中的服务器上下载应用程序设置也比使用本地的INI文件或Windows注册标有更大的独立性和灵活性。举例来说,假设你有一支手机销售队伍,他们需要访问集中化的信息来更有效的销售手机,每天,总公司集中收集数据,然后用电子邮件的形式发送给销售人员。然而,市场的压力和迅速变化的销售形式势必使销售人员要访问最新的数据信息。但是,网络管理员却坚持拒绝让在远程客户端的销售人员访问总公司数据库服务器,因为他们不想通过公用的网络发送用户名和登录密码。因此势必要使用一种新的技术代替基于客户端/服务器的技术。在一个标准的客户端/服务器应用程序中,在应用程序开始时,你能够初始化数据库连接字符串,这就意味着,客户有使用数据库连接字符串的权利,这包括用户名和口令。但是客观情况如果不允许你在网络上发送这些信息的话,你就必需在不联接数据库的情况下直接从客户端取得数据发送给客户。那么解决方案之一就是在服务器上创建一个ASP页(在本例中称为getData.asp)接收特定格式的POST数据,它要求一个包含XML字符串,用来创建ADO对象并运行存储过程或动态SQL语句命令。如果信息有效的话,getData.asp执行存储过程,并返回一个XML格式的数据集、返回值列表或错误页面信息的XML字符串。对于返回数据的命令,客户端要么重新实例化要么返回值或使用XML DOM(Document Object Model文档对象模型)格式的错误页面。这个页面的实现方法如下:getData.asp页面首先使用一个DOMDocument对象来保存客户端发送的数据:创建DOMDocument对象Set xml = Server.CreateObject (msxml2.DOMDocument) xml.async = False然后,它装载POST数据装载POST数据 xml.Load Request If xml.parseError.errorCode 0 Then Call responseError (不能装载XML信息。 & Description: & xml.parseError.reason & brLine: & xml.parseError.Line) End If它能够返回commandtext元素值和returndata或returnvalue元素值。下面只给出返回commandtext元素值的代码,其余代码请参看所附的源程序。Set N = xml.selectSingleNode(command/commandtext) If N Is Nothing Then Call responseError (缺少 sp_name 参数。) Else sp_name = N.Text End If接着,应该让页面创建一个Command对象,读入所有param元素,并且为request中的每一个元素创建一个参数。最后,让页面打开一个连接使用存储过程adExecuteNoRecords选项来执行request。set conn = Server.CreateObject(ADODB.Connection) conn.Mode=adModeReadWrite conn.open Application(ConnectionString) set cm.ActiveConnection=conn 返回数据if not returnsData then cm.Execute else set R = server.CreateObject(ADODB.Recordset) R.CursorLocation = adUseClient R.Open cm, ,adOpenStatic, adLockReadOnly end if如果能够返回数据的话,那么returnData变量就为真值,并且把结果数据集返回到客户端,仍然是一个XML文档。if returnsData then R.Save Response, adPersistXML if err.number 0 then call responseError (数据集发生存储错误 & 在命令 & CommandText & : & Err.Description)Response.end end if end if如果输出参数返回值,那么这个页面将返回一个包含这些值的XML字符串。文档的根元素是一个values标记,每一个返回值都有其相应的子元素,如果发生任何错误,页面都会格式化并返回一个包含错误信息的XML字符串:Sub responseError(sDescription) Response.Write responsedata错误: & sDescription & /data/response Response.endEnd Sub如果在上面的例子中,要应用程序中显示区域的左半边显示客户的姓名列表,再在每个客户姓名后面加上两个链接:购买历史和新近购买。当用户点击其中的一个链接,客户程序就会运行一个存储过程并在右边区域显示出结果。 为了显示这个想法的灵活性,我想让用于返回数据的三个操作单元执行不同的工作过程,它们都调用getData.asp。首先,通过调用CustOrderHist来运行一个存储过程,返回客户的购买历史,它搜索Northwind数据库(为了方便起见我使用MS SQL中自带的数据库)并返回一个数据集。用于返回购买历史的查询语句运行一个叫RecentPurchaseByCustomerID的存储过程,来接收输入的CustomerID参数并通过ProductName参数返回最近顾客购买的商品名。定义其处理过程相应SQL语句如下:CREATE PROCEDURE RecentPurchaseByCustomerID CustomerID nchar(5), ProductName nchar(40) output AS SELECT ProductName = (SELECT top 1 ProductName FROM Products INNER JOIN (Order Details INNER JOIN Orders ON Orders.OrderID=Order Details.OrderID) ON Products.ProductID = Order Details.ProductID WHERE Orders.OrderDate = (SELECT MAX(orders.orderdate) FROM Orders where CustomerID=CustomerID) AND Orders.CustomerID=CustomerID) GO不管你的查询语句中含有动态SQL语句还是含有返回记录集的存储过程或是输出一个返回值,其处理POST消息的方法是一样的:set xhttp = createObject (msxml2.XMLHTTP) xhttp.open POST, http:/localhost/myWeb/ getData.asp, False xhttp.send s发送和接收数据:客户端的XML信息是由一个command元素和一些子元素组成:commandtext元素包含了存储过程的名称,returnsdata元素告诉服务器,客户端是否要求接收返回数据,param元素包含参数信息。如果不使用参数的话,那么最简单的发送字符串查询就象下面这样:command commandtext存储过程或动态SQL语句/commandtextreturnsvaluesTrue/returnsvalues/command可以为每一个参数使用一个param元素,来添加参数。每个param元素有五个子元素:name,type,direction,size和value。子元素的顺序可以随意调换,但是所有的元素都应当有不能缺少,我通常按照定义一个ADO对象的值的顺序来定义它们。例如,CustOrderHist存储过程需要一个CustomID参数,所以用来创建发送到getData.asp的XML字符串的代码为:dim s s = ?xml version=1.0? & vbcrlf s = s & commandcommandtext s = s & CustOrderHist s = s & /commandtext s = s & returnsdata &True/returnsdata s = s & param s = s & nameCustomerID/name s = s & type%=adVarChar%/type s = s & direction & %=adParamInput%/direction s = s & size & len(CustomerID)& /size s = s & value & CustomerID &/value s = s & /param s = s & /command注意,前面的代码都是客户端代码,ADO常量是不在客户端定义的。服务器在发送响应之前使用正确的值取代它们。getData.asp页有一个Response.ContentType,它的属性为text/xml,这样,就可以使用ResponseXML属性来返回结果了。当请求返回纪录,你就可以创建一个Recordset对象并且使用XMLHTTP来打开它:Dim Rset R = createObject(ADODB.Recordset)R.open xhttp.responseXML当查询语句返回数据时,通过设置XMLHTTPRequest对象的responseXML属性来创建一个DOMDocument:Dim xmlset xml = xhttp.responseXML输出参数的XML字符串的每个返回值都包含一个元素,它们都是根元素values的直接子元素,例如:?xml version=1.0 encoding=gb2312?values paramnamevalue/paramname paramnamevalue/paramname/values如果数据使用别的国家的文字,可能需要把编码属性用相应的编码替换,例如对于大部分欧洲语言,可以使用ISO-8859-1客户端页面使用返回的数据来格式化一个HTML字符串用于显示,如:document.all(details).innerHTML = 一些格式化的HTML字符串 前面介绍了使用ASP和XML混合编程,那是因为ASP页面能够很容易让我们看清应用程序正在做什么,但是你如果你不想使用ASP的话,你也可以使用任何你熟悉的技术去创建一个客户端程序。下面,提供了一段VB代码,它的功能和ASP页面一样,也可以显示相同的数据,但是这个VB程序不会创建发送到服务器的XML字符串。它通过运行一个名叫Initialize的存储过程,从服务器取回XML字符串,来查询ClientCommands表的内容。ClientCommands表包括两个域:command_name域和command_xml域。客户端程序需要三个特定的command_name域:getCustomerList,CustOrderHist和RecentPurchaseByCustomerID。每一个命令的command_xml域包括程序发送到getData.asp页面的XML字符串,这样,就可以集中控制XML字符串了,就象存储过程名字所表现的意思一样,在发送XML字符串到getData.asp之前,客户端程序使用XML DOM来设置存储过程的参数值。下边的代码,包含了用于定义Initialize过程和用于创建ClientCommands表的SQL语句。下边的例程中还说明了如何使用XHTTPRequest对象实现我在本文一开始时许下的承诺:任何远程的机器上的应用程序都可以访问getData.asp;当然,你也可以通过设置IIS和NTFS权限来限制访问ASP页面;你可以在服务器上而不是客户机上存储全局应用程序设置;你可以避免通过网络发送数据库用户名和密码所带来的隐患性。还有,在IE中,应用程序可以只显示需要的数据而不用刷新整个页面。在实际的编程过程中,应当使用一些方法使应用程序更加有高效性。可以把ASP中的关于取得数据的代码端搬到一个COM应用程序中去然后创建一个XSLT变换来显示返回的数据。例程:Option ExplicitPrivate RCommands As RecordsetPrivate RCustomers As RecordsetPrivate RCust As RecordsetPrivate sCustListCommand As StringPrivate Const dataURL = http:/localhost/XHTTPRequest/getData.asp Private arrCustomerIDs() As StringPrivate Enum ActionEnumVIEW_HISTORY = 0VIEW_RECENT_PRODUCT = 1End EnumPrivate Sub dgCustomers_Click() Dim CustomerID As String CustomerID = RCustomers(CustomerID).Value If CustomerID Then If optAction(VIEW_HISTORY).Value Then Call getCustomerDetail(CustomerID)Else Call getRecentProduct(CustomerID)End If End IfEnd SubPrivate Sub Form_Load() Call initializeCall getCustomerListEnd SubSub initialize() 从数据库返回命令名和相应的值 Dim sXML As StringDim vRet As VariantDim F As FieldsXML = ?xml version=1.0?sXML = sXML & commandcommandtextInitialize/commandtextsXML = sXML & returnsdataTrue/returnsdatasXML = sXML & /commandSet RCommands = getRecordset(sXML)Do While Not RCommands.EOF For Each F In RCommands.Fields Debug.Print F.Name & = & F.ValueNext RCommands.MoveNextLoopEnd SubFunction getCommandXML(command_name As String) As StringRCommands.MoveFirstRCommands.Find command_name= & command_name & , , adSearchForward, 1If RCommands.EOF Then MsgBox Cannot find any command associated with the name & command_name & . Exit FunctionElse getCommandXML = RCommands(command_xml)End IfEnd FunctionSub getRecentProduct(CustomerID As String)Dim sXML As StringDim xml As DOMDocumentDim N As IXMLDOMNodeDim productName As StringsXML = getCommandXML(RecentPurchaseByCustomerID)Set xml = New DOMDocumentxml.loadXML sXMLSet N = xml.selectSingleNode(command/paramname=CustomerID/value)N.Text = CustomerIDSet xml = executeSPWithReturn(xml.xml)productName = xml.selectSingleNode(values/ProductName).Text 显示text域txtResult.Text = Me.txtResult.Visible = TruedgResult.Visible = False 显示product名txtResult.Text = 最近的产品是: & productNameEnd SubSub getCustomerList()Dim sXML As StringDim i As IntegerDim s As StringsXML = getCommandXML(getCustomerList)Set RCustomers = getRecordset(sXML)Set dgCustomers.DataSource = RCustomersEnd SubSub getCustomerDetail(CustomerID As String) 找出列表中相关联的ID号Dim sXML As StringDim R As RecordsetDim F As FieldDim s As StringDim N As IXMLDOMNodeDim xml As DOMDocumentsXML = getCommandXML(CustOrderHist)Set xml = New DOMDocumentxml.loadXML sXMLSet N = xml.selectSingleNode(command/paramname=CustomerID/value)N.Text = CustomerIDSet R = getRecordset(xml.xml) 隐藏 text , 因为它是一个记录集txtResult.Visible = FalsedgResult.Visible = TrueSet dgResult.DataSource = REnd SubFunction getRecordset(sXML As String) As RecordsetDim R As RecordsetDim xml As DOMDocumentSet xml = getData(sXML)Debug.Print TypeName(xml)On Error Resume NextSet R = New RecordsetR.Open xmlIf Err.Number 0 Then MsgBox Err.Description Exit FunctionElse Set getRecordset = REnd IfEnd FunctionFunction executeSPWithReturn(sXML As String) As DOMDocumentDim d As New DictionaryDim xml As DOMDocumentDim nodes As IXMLDOMNodeListDim N As IXMLDOMNodeSet xml = getData(sXML)If xml.documentElement.nodeName = values Then Set executeSPWithReturn = xmlElse 发生错误 Set N = xml.selectSingleNode(response/data) If Not N Is Nothing ThenMsgBox N.TextExit Function ElseMsgBox xml.xmlExit Function End IfEnd IfEnd FunctionFunction getData(sXML As String) As DOMDocumentDim xhttp As New XMLHTTP30xhttp.Open POST, dataURL, Falsexhttp.send sXMLDebug.Print xhttp.responseTextSet getData = xhttp.responseXMLEnd FunctionPrivate Sub optAction_Click(Index As Integer)Call dgCustomers_ClickEnd Sub代码二、getData.asp% Language=VBScript % option explicit %Sub responseError(sDescription) Response.Write responsedataError: & sDescription & /data/response Response.endEnd SubResponse.ContentType=text/xmldim xmldim commandTextdim returnsDatadim returnsValuesdim recordsAffecteddim paramdim paramNamedim paramTypedim paramDirectiondim paramSizedim paramValuedim Ndim nodeNamedim nodesdim conndim sXMLdim Rdim cm创建DOMDocument对象Set xml = Server.CreateObject(msxml2.DOMDocument)xml.async = False 装载POST数据xml.Load RequestIf xml.parseError.errorCode 0 ThenCall responseError(不能装载 XML信息。 描述: & xml.parseError.reason & br行数: & xml.parseError.Line)End If 客户端必须发送一个commandText元素Set N = xml.selectSingleNode(command/commandtext)If N Is Nothing ThenCall responseError(Missing commandText parameter.)ElsecommandText = N.TextEnd If 客户端必须发送一个returnsdata或者returnsvalue元素set N = xml.selectSingleNode(command/returnsdata)if N is nothing thenset N = xml.selectSingleNode(command/returnsvalues)if N is nothing then call responseError(Missing returnsdata or returnsValues parameter.)else returnsValues = (lcase(N.Text)=true)end ifelsereturnsData=(lcase(N.Text)=true)end ifset cm = server.CreateObject(ADODB.Command)cm.CommandText = commandTextif instr(1, commandText, , vbBinaryCompare) 0 thencm.CommandType=adCmdTextelsecm.CommandType = adCmdStoredProcend if 创建参数set nodes = xml.selectNodes(command/param)if nodes is nothing then 如果没有参数 elseif nodes.length = 0 then 如果没有参数 elsefor each param in nodes Response.Write server.HTMLEncode(param.xml) & bron error resume nextparamName = param.selectSingleNode(name).textif err.number 0 thencall responseError(创建参数: 不能发现名称标签。)end ifparamType = param.selectSingleNode(type).textparamDirection = param.selectSingleNode(direction).textparamSize = param.selectSingleNode(size).textparamValue = param.selectSingleNode(value).textif err.number 0 thencall responseError(参数名为 & paramName & 的参数缺少必要的域)end ifcm.Parameters.Append cm.CreateParameter(paramName,paramType,paramDirection,p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论