?? 210.htm
字號:
<p>用VB和XML建立集中式應用程序</p>
<p></p>
<p> 很長一段時間以來,Visual Basic程序員都是在編寫客戶機/服務器程序,這些程序工作在私有網絡上。但是這種在一臺PC機上安裝一個獨立應用程序的時代正在很快地結束,客戶機/服務器結構不再能滿足需要,現在的大多數商用程序需要共享數據。 </p>
<p></p>
<p>為什么要建立基于Intranet和Internet的應用程序 </p>
<p> 編寫基于Intranet和Internet的應用程序或修改C/S結構的程序為工作于Intranet和Internet上的程序的原因至少有以下幾點: </p>
<p></p>
<p> 首先,每天都在增加的遠程雇員需要訪問公司的數據。 </p>
<p></p>
<p> 其次,通過集中應用程序里的數據能監控對它們的訪問和使用。 </p>
<p></p>
<p> 第三,使用本文談及的技術,在應用程序啟動時從一個中心位置查找全局設置信息,就能方便地維護和更新這些設置,有助于最大程度地降低對桌面應用程序的更新。 </p>
<p></p>
<p> 第四,通過Web服務器而不是從遠程客戶端來進行數據庫操作,可以避免通過網絡傳遞數據庫的登錄口令。 </p>
<p></p>
<p> 最后,如果使用Internet Explorer,通過后臺查詢數據,就能避免在修改部分內容時重畫整個頁面。 </p>
<p></p>
<p>右圖是在Internet Explorer中看到的一個應用程序實例。圖中,應用程序顯示了Northwind數據庫中的信息。左邊是客戶名列表和兩個鏈接:購買歷史情況和最近的購買情況。當用戶點擊鏈接時,數據在右邊的Details欄里顯示出來。這個應用程序使用DHTML顯示Details中的數據而不用刷新整個頁面,而且沒有使用框架。 </p>
<p>實現思路 </p>
<p> 創建基于HTTP的VB應用程序的關鍵是XML和XMLHTTPRequest對象,XMLHTTPRequest對象是Microsoft的XML語法分析器 (msxml.dll)的一部分,它讓你能通過HTTP向遠端服務器發送GET和POST請求。運行在遠端服務器上的程序(我們將要使用的是 ASP頁面,但應用程序可以使用任何服務器端腳本機制)接受請求、解釋內容,并向調用它的應用程序返回數據或錯誤消息。你可能會覺得這和對SOAP的描述差不多,實際上也是如此,但這里我們不使用SOAP,因為它會使代碼變得復雜。無論如何,重要的是:要理解這里所用的技術背后的思想,它和SOAP的思想是一樣的,但不像SOAP那樣復雜。 </p>
<p></p>
<p> 將不停改變的客戶端應用程序完全隔離起來是不可能的,但通過從中心服務器而不是從本地INI文件或Windows注冊表中來加載應用程序設置,就能在很高程度上建立應用程序的獨立性。例如,假定有一個流動的銷售團隊,他們需要訪問集中管理的數據以便進行有效的電話推銷。過去,這些數據是集中采集的,每天通過電子郵件提供給銷售人員。然而,市場的壓力和快速變化的銷售情況迫使銷售人員必須能訪問需要的最新數據。不幸的是,IT經理們堅決拒絕允許遠程用戶訪問數據庫服務器,因為他們不希望通過公用的Internet發送用戶名和口令。不過不要擔心,我們將采取方法使大家都滿意。 </p>
<p></p>
<p> 在標準的客戶機/服務器程序中,你可能需要在應用程序啟動時初始化數據庫連接串,這意味著客戶機必須能訪問連接串信息,包括用戶名和口令。但是,當不允許通過網絡傳送那些信息時,就需要在客戶端和數據庫之間不建立直接連接的情況下獲取數據。 </p>
<p></p>
<p> 解決辦法是在服務器上建立一個ASP頁面,在示例代碼中它的名字是getData.asp,它接受特定形式的POST數據,它等待一個 XML字符串,這個字符串里包含著建立ADO Command對象并運行存儲過程或動態SQL語句所需的命令信息。如果信息充分,getData.asp執行存儲過程并返回一個XML字符串,這個字符串里包含以XML格式表述的Recordset、一系列返回值或一個錯誤消息。對于返回數據的命令,客戶端或者將返回的Recordset對象重新表述,或者使用XML文檔對象模型(DOM)來查找返回值或錯誤消息。 </p>
<p></p>
<p>ASP代碼和所需接收的數據 </p>
<p> getData.asp頁面的動作有特定的次序。首先,它創建一個DOMDocument對象以保存從客戶端傳來的數據: </p>
<p></p>
<p> 注釋: 創建 DOMDocument 對象 </p>
<p></p>
<p> Set xml = Server.CreateObject _ </p>
<p></p>
<p> ("msxml2.DOMDocument") </p>
<p></p>
<p> xml.async = False </p>
<p></p>
<p> 然后,它加載POST數據,并檢測格式錯誤的請求: </p>
<p></p>
<p> 注釋: 加載 POST 數據 </p>
<p></p>
<p> xml.Load Request </p>
<p></p>
<p> If xml.parseError.errorCode <> 0 Then </p>
<p></p>
<p> Call responseError _ </p>
<p></p>
<p> ("Could not load XML message." & _ </p>
<p></p>
<p> "Description: " & _ </p>
<p></p>
<p> xml.parseError.reason & _ </p>
<p></p>
<p> "<br>Line: " & xml.parseError.Line) </p>
<p></p>
<p> End If </p>
<p></p>
<p> 它查找元素commandtext的取值或元素returnsdata、returnsvalues的取值。因為查找這些元素取值的代碼是相似的,因此這里只給出查找元素commandtext取值的代碼: </p>
<p></p>
<p> Set N = xml.selectSingleNode _ </p>
<p></p>
<p> ("command/commandtext") </p>
<p></p>
<p> If N Is Nothing Then </p>
<p></p>
<p> Call responseError _ </p>
<p></p>
<p> ("Missing <sp_name> parameter.") </p>
<p></p>
<p> Else </p>
<p></p>
<p> sp_name = N.Text </p>
<p></p>
<p> End If </p>
<p></p>
<p> 然后,頁面創建一個Command對象,讀取所有<param>元素,并為請求中存在的每一個元素創建一個參數,代碼如下: </p>
<p></p>
<p> 注釋: create parameters, if any </p>
<p></p>
<p> set nodes = xml.selectNodes("command/param") </p>
<p></p>
<p> if nodes is nothing then </p>
<p></p>
<p> 注釋: no parameters </p>
<p></p>
<p> elseif nodes.length = 0 then </p>
<p></p>
<p> 注釋: no parameters </p>
<p></p>
<p> else </p>
<p></p>
<p> for each param in nodes </p>
<p></p>
<p> 注釋: Response.Write server.HTMLEncode(param.xml) & "<br>" </p>
<p></p>
<p> on error resume next </p>
<p></p>
<p> paramName = param.selectSingleNode("name").text </p>
<p></p>
<p> if err.number <> 0 then </p>
<p></p>
<p> call responseError("Parameter creation: " & _ </p>
<p></p>
<p> "Unable to find the name " & "tag.") </p>
<p></p>
<p> end if </p>
<p></p>
<p> paramType = param.selectSingleNode("type").text </p>
<p></p>
<p> paramDirection = param.selectSingleNode("direction").text </p>
<p></p>
<p> paramSize = param.selectSingleNode("size").text </p>
<p></p>
<p> paramValue = param.selectSingleNode("value").text </p>
<p></p>
<p> if err.number <> 0 then </p>
<p></p>
<p> call responseError("The parameter named 注釋:" & _ </p>
<p></p>
<p> paramName & "注釋: was " & "missing one or more " & "required fields.") </p>
<p></p>
<p> end if </p>
<p></p>
<p> cm.Parameters.Append cm.CreateParameter(paramName,paramType, _ </p>
<p></p>
<p> paramDirection,paramSize,paramValue) </p>
<p></p>
<p> if err.number <> 0 then </p>
<p></p>
<p> call responseError("Unable to create or " & "append the parameter " & _ </p>
<p></p>
<p> "named 注釋:" & paramName & ".注釋: " & err.description) </p>
<p></p>
<p> Response.end </p>
<p></p>
<p> end if </p>
<p></p>
<p> next </p>
<p></p>
<p> on error goto 0 </p>
<p></p>
<p> end if </p>
<p></p>
<p> 最后,頁面打開一個鏈接并執行請求,對于存儲過程,它使用不返回數據的adExecuteNoRecords選項。 </p>
<p></p>
<p> set conn = </p>
<p></p>
<p> Server.CreateObject_ </p>
<p></p>
<p> ("ADODB.Connection") </p>
<p></p>
<p> conn.Mode=adModeReadWrite </p>
<p></p>
<p> conn.open _ </p>
<p></p>
<p> Application("ConnectionString") </p>
<p></p>
<p> set cm.ActiveConnection=conn </p>
<p></p>
<p> 注釋: retrieve the data </p>
<p></p>
<p> if not returnsData then </p>
<p></p>
<p> cm.Execute </p>
<p></p>
<p> else </p>
<p></p>
<p> set R = server.CreateObject _ </p>
<p></p>
<p> ("ADODB.Recordset") </p>
<p></p>
<p> R.CursorLocation = adUseClient </p>
<p></p>
<p> R.Open cm, ,adOpenStatic, _ </p>
<p></p>
<p> adLockReadOnly </p>
<p></p>
<p> end if </p>
<p></p>
<p> 如果命令返回數據,變量returnsData的值將為True,頁面以XML文檔方式將recordset的結果返回給客戶機: </p>
<p></p>
<p> 注釋: return the data, if required </p>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -