第5章 腳本運行期庫對象 前面章節(jié)已經(jīng)介紹了ASP如何使用在服務器上定義的對象的實例,充分利用所提供的方法和屬性擴展ASP的性能。有一系列的對象可供使用,包括腳本對象和標準IIS/ASP安裝的組件,以及自己創(chuàng)建的或者從其他供應商處購買的對象。也可以在互聯(lián)網(wǎng)上各種網(wǎng)站免費下載對象,并在自己的頁面上使用。 這一章將討論由ASP腳本環(huán)境提供的一般稱為“腳本運行期庫”(Scripting Runtime Library)的對象。這些對象通過正在使用的腳本引擎提供給代碼,與ASP腳本程序一起完成多種實用任務。 還有一種組件是“活動服務器組件”(Active Server Component),通過單獨的ActiveX DLL文件或者其他文件來實現(xiàn)。后面章節(jié)將討論相關(guān)內(nèi)容。 當然,需要研究如何在頁面上使用這些對象。在前一章中,我們已經(jīng)了解了服務器如何提供一個方法來實例化對象,本章將深入討論這個內(nèi)容。 本章將介紹以下內(nèi)容: · 腳本引擎以腳本對象方式提供了什么。 · 如何創(chuàng)建腳本對象及其他組件實例。 · 腳本對象的成員和屬性概要。 · 如何在代碼中使用腳本對象。 下面開始研究腳本對象的定義。
5.1 腳本對象的定義 前面章節(jié)研究了ASP對象模型。 對象模型是用來理解系統(tǒng)的各個部分相互關(guān)系的一種基本手段。 ASP對象模型提供了一種結(jié)構(gòu),用來作為一個整體操縱HTTP請求、響應及ASP環(huán)境中的不同元素。例如,我們已經(jīng)看到,如何通過查看ASP請求對象的cookie集合,得到來自瀏覽器的任何cookie值。 我們使用的腳本語言也有對象模型。然而,腳本語言提供的這一對象模型,不同于由ASP DLL直接提供的對象模型,腳本對象是由Microsoft腳本運行期庫(scrrun.dll)提供的,安裝缺省的Active Scripting腳本引擎時,也安裝了Microsoft腳本運行期庫。
5.1.1 不同類型的對象和組件 不要對“對象”和“組件”這兩個名詞感到困惑,在一定范圍內(nèi)它們都可以作為ASP的一部分,同樣可以通過COM對其進行訪問。從概念上可以將它們分為四類: · ASP內(nèi)置對象,如ObjectContext、Request、Response、Application、Session、Server和ASPError。本書的第2章到第4章已經(jīng)研究了這些內(nèi)容。 · 腳本對象。通過腳本運行期庫使用,如Dictionary、FileSystem和TextStream。這是本章要討論的對象。 · 可安裝的組件。由Microsoft在IIS 5.0和ASP 3.0標準安裝時提供。這將在下一章討論。 · 其他組件。從其他獨立廠商購買的、在網(wǎng)站上發(fā)現(xiàn)的或者自己創(chuàng)建的組件。還有一些其他的由Windows服務或產(chǎn)品提供的組件,如Windows Scripting Host。在本書的附錄中提供了相應的列表,本書專門有一部分章節(jié)講述如何構(gòu)建自己的組件。
5.1.2 VBScript和Jscript腳本對象 作為腳本運行期庫的一部分,Microsoft提供三個主要的對象: · Dictionary對象提供一個極為有用的存儲對象,它用來存儲值,通過對象的名字而不是其索引進行訪問和引用。例如,對于存儲從ASP Request對象中檢索到的名稱/值對,這是非常合適的。 · FileSystemObject對象提供了對服務器底層文件系統(tǒng)的訪問(在客戶端上使用IE 5.0,與名為“Hypertext Application(HTA)”的特殊類型的頁面協(xié)同使用)。可用FileSystemObject對象遍歷計算機的本地及網(wǎng)絡(luò)的驅(qū)動器、文件夾和文件。 · TextStream對象提供對存儲在磁盤上文件的訪問,用于同F(xiàn)ileSystemObject對象協(xié)同使用。TextStream對象能夠讀出或?qū)懭胛谋荆樞虻模┪募H能通過FileSystemObject對象進行實例化,所以人們常常認為TextStream對象是FileSystemObject對象的子對象。 FileSystemObject對象是其他一系列用來與文件系統(tǒng)交互的對象和集合的“父代”。該對象提供了對象的三個集合:Drives、Folders和Files集合,每個集合分別是相應的Drive、Folder和File對象的集合。它們用來進行磁盤上的驅(qū)動器、文件夾(目錄)和文件的遍歷和定位。對象間的關(guān)系如圖5-1所示: [img]http://dave_lu.myetang.com/asppic/asp79.jpg[/img] 圖5-1 腳本運行期庫中對象間的關(guān)系 下面,將依次介紹這些對象和集合,以及如何使用它們。然而,首先要理解對象實例與組件的創(chuàng)建或?qū)嵗绞街g的差異。這是下一節(jié)的主要內(nèi)容。
5.2 創(chuàng)建對象生組件實例 創(chuàng)建腳本運行期庫對象的實例與創(chuàng)建任何其他對象和組件的實例化方式完全相同。可使用ASP Server對象提供的CreateObject方法(確保對象創(chuàng)建在當前頁面的環(huán)境內(nèi)),或者使用一個<OBJECT>元素。我們將研究這兩種方法,究竟采用那種方法依賴于頁面的需要。
5.2.1 使用Server.CreateObject方法 正如在研究Server對象的時候看到的,組件或其他對象實例可根據(jù)它們的ProgID來創(chuàng)建: <% Dim objThis Set objThis = Server.CreateObject(“ADODB.Connection”) %> ProgID字符串“正式的”格式是“供應商.組件.版本”,供應商的名字和版本是可選的。通常ProgID只包含前兩部分(如上例)。少數(shù)供應商在ProgID中設(shè)置版本編號,這將避免向后兼容的新版本使用同樣的ProgID,這要求改變ASP頁面才能使用新版本。
5.2.2 使用<OBJECT>元素 可以使用標準的HTML<OBJECT>元素通過增加RUNAT參數(shù)并指定其值為“SERVER”來在服務器上創(chuàng)建一個組件實例。另外,通常是提供對象的ProgID字符串而不是數(shù)字的ClassID: <OBJECT ID=”objThis” RUNAT=”SERVER” PROGID=”This.Object”> <PARAM NAME=”param1” VALUE=”value1”> <PARAM NAME=”param2” VALUE=”value2”> </OBJECT> 如果上面腳本的對象有相應的屬性可在腳本中使用,在<OBJECT>元素內(nèi)可通過<PARAM>元素進行設(shè)置,就像通常在HTML頁面中所做的一樣。在ASP中使用<OBJECT>元素時不要求CODEBASE屬性,當其不可用時,服務器不會試圖下載以及安裝對象或組件。 1. 指定一個ClassID 另外,可以指定想要創(chuàng)建的對象或組件的ClassID。在不知道目標機安裝了什么其他組件的情況下,這是非常有用的。例如在客戶端上的瀏覽器的頁面上實例化組件時。 在理論上,組件的ProgID(文本“供應商.組件”)不應該相互沖突,應該是唯一的。然而,這不是無懈可擊的。有可能美國北方的一個供應商與希臘小島上的一個供應商同名。但是,使用ClassID識別訪問時,因為ClassID是唯一的,同名情況就不會發(fā)生。 如果決定使用對象或組件的ClassID,應將其放入CLASSID屬性中,而不是PROGID屬性。如: <OBJECT ID=”objThis” RUNAT=”SERVER” CLASSID=”clsid:892D6DA7-E0F9-11D2-B2E9-00105A42AF30”> <PARAM NAME=”param1” VALUE=”value1”> <PARAM NAME=”param2” VALUE=”value2”> </OBJECT> 但在自己的服務器上實例化對象時,應該知道對象和組件的安裝方式。這樣在ASP代碼中創(chuàng)建對象實例時,可以安全地使用ProgID。這就是ClassID很少在ASP頁面內(nèi)使用的原因。然而,因為ProgID用于查找ClassID,如果愿意也可以用組件或?qū)ο蟮腃lassID代替ProgID。 2. 設(shè)置對象實例的作用域 缺省情況下,所有ASP頁面中創(chuàng)建的對象與組件實例(無論用Server.CreateObject方法或<OBJECT>元素)都有頁面內(nèi)的作用域(page scope)。這意味著,對象與組件只有該頁在ASP上運行時才存在,當頁面完成并且把結(jié)果發(fā)送到客戶端以后就自動地取消了。 然而,如果在global.asa文件(它存在于站點或虛擬應用程序的根目錄)中放置<OBJECT>聲明,可以將對象或組件的作用域指定為應用程序或會話作用域。 (1) 在應用程序?qū)幼饔糜騽?chuàng)建對象 通過設(shè)置SCOPE屬性為“APPLICATION”,創(chuàng)建應用程序?qū)幼饔糜驅(qū)ο螅?br><OBJECT ID=”objThis” RUNAT=”SERVER” PROGID=”This.Object” SCOPE=”APPLICATION”> </OBJECT> 應用程序開始時創(chuàng)建了對象實例,即一旦用戶從虛擬應用程序的目錄請求一個頁面,就創(chuàng)建對象實例。對于缺省Web站點,這可以是站點上的任一目錄。直到應用程序結(jié)束(最后的用戶會話結(jié)束)前,對象實例一直存在,并且可以被虛擬應用程序或站點目錄內(nèi)任一頁面內(nèi)的任意用戶引用和使用。 (2) 在會話層作用域創(chuàng)建對象 如果想創(chuàng)建由單個用戶使用的對象實例,其作用域為他訪問的所有頁面,可創(chuàng)建會話層作用域?qū)ο蟆_@通過將SCOPE屬性設(shè)置為“SESSION”來實現(xiàn): <OBJECT ID=”objThis” RUNAT=”SERVER” PROGID=”This.Object” SCOPE=SESSION”> </OBJECT> 對象一旦被引用就被創(chuàng)建,引用是由用戶從虛擬應用程序或站點載入的頁面內(nèi)的程序代碼完成的(在global.asa文件中有<OBJECT>聲明)。當用戶會話生命周期結(jié)束并被取消時,它引用的對象實例也就取消了。 (3) 關(guān)于作用域和狀態(tài) 使對象實例的作用域為全局的或者為用戶會話全局環(huán)境看起來是一個好主意,但在實際使用時有些問題需要考慮,其中之一是在用戶的許多請求之間能夠有效地保護對象的狀態(tài)。換句話說,可以設(shè)定對象的一些屬性,它們對使用的所有頁面是共用的。因為不必每次都創(chuàng)建新的實例并設(shè)置其屬性,所以這看起來是個較好的辦法。 事實上,微軟建議一般情況下不要這樣做,這一思想是傳統(tǒng)程序設(shè)計思想的殘余。在Web上,要面對的最大問題是服務器以及Web應用程序及所提供的動態(tài)網(wǎng)頁如何應付數(shù)以百萬計的網(wǎng)站訪問者。將組件實例駐留在內(nèi)存中等待一個特定用戶的頁面請求,對可能有幾百個用戶同時瀏覽的網(wǎng)站來說,這樣做不能有效地使用資源。 Windows 2000提供新的COM+運行期特性,它能夠處理組件的創(chuàng)建、緩存和使用,采用一種吞吐量最大化但所占服務器資源最小化的方式。對象實例存儲在哪里和存儲多久的問題,最好由操作系統(tǒng)自己完成,而不是由程序員決定。 也就是說,在頁面內(nèi)需要的地方創(chuàng)建對象實例,當頁面終止時讓其消失。COM+整理這些碎片,自動處理后臺的一些復雜工作。如果要了解有關(guān)這方面的內(nèi)容,第14章比較詳細地研究了組件的創(chuàng)建。 當然,在某種情況下,我們可能要求一個對象具有應用程序?qū)雍蜁拰拥淖饔糜颍绕涫窃陧撁嬲埱箝g保存狀態(tài)時。在后面討論Dictionary對象時,將有一個這方面的實例。
5.2.3 Server.CreateObject與<OBJECT>的區(qū)別 Server.CreateObject方法立即創(chuàng)建一個對象實例。在大多數(shù)情況下這也是我們所希望的。而<OBJECT>元素只有首次引用一個對象時才創(chuàng)建指定的對象實例。因此如果在代碼中停止使用該對象,則不創(chuàng)建該對象實例。 如果代碼只在某種情況下使用這個對象(可能依賴于請求參數(shù)的值),這也許是有用的。因為如果不需要這個對象,則可以節(jié)省服務器的資源。 然而,如果肯定需要創(chuàng)建某一對象,可使用Server.CreateObject方法完成。用<OBJECT>元素創(chuàng)建對象有助于防止在代碼中取消對對象的調(diào)用時,忘記取消程序中的Server.CreateObject行,當然這是一個粗心的程序設(shè)計。 最后需要記住的是,如果對象是使用Server.CreateObject方法創(chuàng)建的,就可以從會話或應用程序中去掉對象,但使用<OBJECT>元素創(chuàng)建的,則不行。
5.2.4 組件線程模型 在頁面內(nèi)使用對象或組件時,應該考慮的另一個問題是該對象涉及到的響應多個請求的行為方式。事實上在ASP里,這是所需要理解的最復雜的題目之一。一個組件的線程模型,結(jié)合其作用域,影響該組件和應用程序的性能和效率,也影響將它實例化的ASP頁面。 線程就是由處理器執(zhí)行的系統(tǒng)對象,用于完成由組件代碼定義的任務。每一個線程都可以被認為是單個二進制指令集。在像Windows這樣的多線程環(huán)境中,多個線程可同時運行。 實際上有五個線程模型(包括在Windows 2000里引入的Neutral-threading模型): · Single-threaded(單線程):某一時刻只能有一個進程使用某組件。 · Apartment-threaded(單元線程):若干進程都可以使用某組件,但只有一個在指定的線程上。 · Neutral-threaded(中立線程):若干進程都能使用某組件,并且可以使用指定的一組線程中的任何一個。 · Multiple-threaded或Free-threaded(多線程或自由線程):若干進程都能使用某組件,并且這些進程可以運行在不同的線程上。 · Both-threaded(雙線程):對象既可以是單元線程的又可以作為自由線程的。 在這里不解釋線程模型的技術(shù)細節(jié),本書后面有相應的內(nèi)容。 單元線程的組件(例如使用Visual Basic創(chuàng)建的或作為XML腳本的組件)可在頁面層作用域內(nèi)很好地運行,在會話層作用域內(nèi)也是可以接受的。事實上,在頁面層,由于較低的數(shù)據(jù)處理開銷,也能很好地運行雙線程的組件。 Winodws 2000中的中立線程的模型甚至提供了更好的性能,盡管到目前為止只有很少的這樣的組件和與之相適應的開發(fā)工具。 如果需要會話層組件,使用可用的雙線程的組件。并且如果需要應用程序?qū)幼饔糜颍梢恢笔褂秒p線程的組件。 然而,微軟建議避免使用會話層作用域的組件,甚至不使用應用程序?qū)幼饔糜虻慕M件,除非這些組件是絕對需要的。使組件的活動時間超過作用域為頁面級的組件所要求的時間,對于由COM+提供代理特性的對象是沒有益處的。
|