本節將從程式設計的角度對Application和Session這兩個對象進行研究。
· 當載入ASP DLL並響應對一個ASP網頁的第一個請求時,建立Application對象。該對象提供一個儲存場所,用來儲存對於所有訪問者開啟的所有網頁都可用的變數和對象。
· 當訪問者首次從網站請求一個ASP頁面時,為他建立一個Session對象,並保持有效直到預設的逾時周期(或由指令碼確定的逾時周期)。該對象提供一個儲存場所,用來儲存僅僅對該訪問者在會話的活動期間開啟的網頁可用的變數和對象。
圖3-12(即圖1-20)給出了使用者的請求和伺服器的響應在會話中的分布情況。所有的會話都在ASP應用程式中。
3.3.1 ASP的Application對象成員概述
本節說明Application對象的集合、方法和事件(Application對象沒有屬性)。在下一節對Session對象(具有屬性)進行同樣的說明。然後將繼續探討使用這些對象所完成的任務,更詳細地說明每個對象的各成員如何進行工作。
1. Application對象的集合
Application對象提供了兩個集合,可以用來訪問儲存於全域應用程式空間中的變數和對象。集合及說明如表3-3所示:
表3-3 Application對象的集合及說明
集 合
說 明
Contents
沒有使用元素定義的儲存於Application對象中的所有變數(及它們的值)的一個集合。包括Variant數組和Variant類型對象執行個體的引用
StaticObjects
使用元素定義的儲存於Application對象中的所有變數(及它們的值)的一個集合
2. Application對象的方法
Application對象的方法允許刪除全域應用程式空間中的值,控制在該空間內對變數的並發訪問。方法及說明如表3-4所示:
表3-4 Application對象的方法及說明
方 法
說 明
Contents.Remove(“variable_name”)
從Application.Content集合中刪除一個名為variable_name的變數
Contents.RemoveAll()
從Application.Content集合中刪除所有變數
Lock()
鎖定Application對象,使得只有當前的ASP頁面對內容能夠進行訪問。用於確保通過允許兩個使用者同時地讀取和修改該值的方法而進行的並行作業不會破壞內容
Unlock()
解除對在Application對象上的ASP網頁的鎖定
注意,在運行期間不能從Application.StaticObjects集合中刪除變數。
3. Application對象的事件
Application對象提供了在它啟動和結束時觸發的兩個事件,如表3-5所示:
表3-5 Application對象的事件及說明
事 件
說 明
OnStart
當ASP啟動時觸發,在使用者請求的網頁執行之前和任何使用者建立Session對象之前。用於初始設定變數、建立對象或運行其他代碼
OnEnd
當ASP應用程式結束時觸發。在最後一個使用者會話已經結束並且該會話的OnEnd事件中的所有代碼已經執行之後發生。其結束時,應用程式中存在的所有變數被取消
3.3.2 ASP的Session對象成員概述
本節概述Session對象的所有成員。
1. Session對象的集合
Session對象提供了兩個集合,可以用來訪問儲存於使用者的局部會話空間中的變數和對象。這些集合及說明如表3-6所示:
表3-6 Session對象的集合及說明
集 合
說 明
Contents
儲存於這個特定Session對象中的所有變數和其值的一個集合,並且這些變數和值沒有使用元素進行定義。包括Variant數組和Variant類型對象執行個體的引用
StaticObjects
通過使用元素定義的、儲存於這個Session對象中的所有變數的一個集合
2. Session對象的特性
Session對象提供了四個屬性。這些屬性及說明如表3-7所示:
表3-7 Session對象的屬性及說明
屬 性
說 明
CodePage
讀/寫。整型。定義用於在瀏覽器中顯示頁內容的字碼頁(Code Page)。字碼頁是字元集的數字值,不同的語言和場所可能使用不同的字碼頁。例如,ANSI字碼頁1252用於美國英語和大多數歐洲語言。字碼頁932用於日文字
LCID
讀/寫。整型。定義發送給瀏覽器的頁面地區標識(LCID)。LCID是唯一地標識地區的一個國際標準縮寫,例如,2057定義當前地區的貨幣符號是'£'。LCID也可用於FormatCurrency等語句中,只要其中有一個可選的LCID參數。LCID也可在ASP處理指示中設定,並優先於會話的LCID屬性中的設定。本章後面提供一個ASP處理指示的列表
SessionID
唯讀。長整型。返回這個會話的工作階段識別項,建立會話時,該標識符由伺服器產生。只在父Application對象的生存期內是唯一的,因此當一個新的應用程式啟動時可重新使用
Timeout
讀/寫。整型。為這個會話定義以分鐘為單位的逾時周期。如果使用者在逾時周期內沒有進行重新整理或請求一個網頁,該會話結束。在各網頁中根據需要可以修改。預設值是10min。在使用率高的網站上該時間應更短
3. Session對象的方法
Session對象允許從使用者級的會話空間刪除指定值,並根據需要終止會話。Seesion對象的方法及說明如表3-8所示:
表3-8 Session對象的方法及說明
方 法
說 明
Contents.Remove(“variable_name”)
從Session.Content集合中刪除一個名為variable_name的變數
Contents.RemoveAll()
從Session.Content集合中刪除所有變數
Abandon()
當網頁的執行完成時,結束目前使用者會話並撤消當前Session對象。但即使在調用該方法以後,仍可訪問該頁中的當前會話的變數。當使用者請求下一個頁面時將啟動一個新的會話,並建立一個新的Session對象(如果存在的話)
注意,在運行期間不能從Session.StaticObjects集合中刪除變數。
4. Session對象的事件
Session對象提供了在啟動和結束時觸發的兩個事件,如表3-9所示:
表3-9 Session對象的事件及說明
事 件
說 明
OnStart
當ASP使用者會話啟動時觸發,在使用者請求的網頁執行之前。用於初始設定變數、建立對象或運行其他代碼。
OnEnd
當ASP使用者會話結束時觸發。從使用者對應用程式的最後一個頁面請求開始,如果已經超出預定的會話逾時周期則觸發該事件。當會話結束時,取消該會話中的所有變數。在代碼中使用Abandon方法結束ASP使用者會話時,也觸發該事件
3.3.3 使用Application和Session的事件
ASP的Application和Session對象體現了其他ASP內建對象所沒有的特徵——事件。然而,正像在前面的對象成員表中看到的那樣,這些都是ASP會話和應用程式的工作相聯絡的事件。
1. Application和Session的事件處理器
每當一個應用程式或會話啟動或結束時,ASP觸發一個事件。可以通過在一個特殊的檔案中編寫普通的指令碼代碼來檢測和應答這些事件,這個檔案名稱為global.asa,位於一個應用程式的根目錄中(對於預設的Web網站是InetPubWWWRoot目錄,或是作為一個實際應用程式定義的一個檔案夾)。這個檔案可以包含一個或多個HTML的元素,用於建立將在該應用程式或使用者會話內使用的組件執行個體。
在第4章中將詳細地介紹如何建立組件執行個體。下面的代碼是global.asa檔案的一個例子。我們只關注元素以及以Set關鍵字開始的那些程式碼:
PROGID=”MSWC.Counters”>
PROGID=”MSWC.NextLink”>
因為這個global.asa檔案用於本章中的樣本頁面,所以將需要將該檔案放到Web網站的根目錄中,或者放到已配置為一個虛擬應用程式的目錄中,並且在該目錄中包含有其他樣本檔案。
讀取和儲存值
注意上面的例子怎樣讀取Application和Session的變數,與在Request和Response對象的集合中所採取的方式相同。設定這些變數的值:
Application(“variable_name”) = variable_value
Application(“variable_name”) = variant_array_variable_name
Set Application(“variable_name”) = object_reference
擷取這些變數的值:
variable_value = Application(“variable_name”)
variant_array_variable = Application(“variable_name”)
Set object_reference = Application(“variable_name”)
當然,對於Session對象可採取同樣的方法。
可以看到,當從一個Session事件處理器訪問時,怎樣“鎖定”(Lock)和“解鎖”(unlock)該Application對象;當從一個ASP網頁訪問時,需要進行相同的處理。用Application事件內的代碼訪問Application對象中的值時,不要求這麼做。這是因為在任何應用程式中只有一個Application對象的執行個體,並且其事件處理器的代碼只在沒有活動的使用者會話時進行。
也可以看到一個基本的使用者會話計數器是如何?的。這裡使用一個應用程式級的變數Visit_count,當新的會話啟動時它就自動增加。 一般也不限制簡單地把值儲存到Application或Session對象中。例如,Web開發人員的Web網站在http://webdev.wrox.co.uk上,有相應的一個global.asa檔案,當一個新的會話啟動時該檔案就在伺服器上的資料庫中寫入相應的條目,資料細節從Request.ServerVariables集合中擷取。這提供了一個基本的方法統計訪問者的數量,並收集訪問者的一些基本資料。
2. 建立Variant數組
在Session和Application對象中建立和使用一個Variant數組來儲存值的方法目前尚未討論,在這裡作為一個非常有用的技術進行討論。正如已經看到的那樣,一個Variant資料類型可以包含一個數組,而不僅僅是一個值。
一個數組只是在記憶體的一個連續地區中以指定的次序儲存二進位值的一個長行。要安排Variant,需要指向首項,並給出有關大小和結構的資訊,指令碼引擎可以做餘下的事情。
可在一個Variant變數中建立一維、二維或多維陣列,然後把該數組分配給一個應用程式層或使用者會話層的變數,並保證整個數組可在相應的地方使用。下面代碼示範了一個簡單的一維數組的使用技術:
Dim varArray(3)
varArray(0) = “This is a”
varArray(1) = “Variant array”
varArray(2) = “stored in the”
varArray(3) = “Session object”
Session(“Variant_Array”) = varArray
3. 應用程式和會話在何時啟動和結束
在介紹ASP應用程式和會話如何進行工作時提到過這個內容。以最基本的術語概述如下:
· 當第一個使用者請求Application 領域內(即Web網站的預設根目錄內),或者在該網站的一個子目錄內的一個使用者定義的虛擬應用程式的一個ASP網頁時,啟動該應用程式。在任何使用者會話啟動之前發生。
· 當任意使用者第一次請求在預設應用程式或一個虛擬應用程式內的一個ASP網頁時,啟動一個會話(如果還沒一個活動的會話)。
· 當使用者在會話指定的逾時周期內沒有下載一個ASP網頁時,會話結束。逾時時間可以在指令碼代碼中使用Session.Timeout屬性進行設定,可在Properties對話方塊中對各個應用程式單獨設定,或者通過Active Directory的IIS:部分修改IIS中繼資料庫中的預設值進行設定。調用Session.Abandon方法的一個網頁完成執行以後,會話也會結束。
· 在一個應用程式中的最後一個活動會話結束以後,該應用程式立即結束。
4. ASP處理指示
正如在第1章中所看到的,可以把一條處理指示增加到一個ASP網頁。處理指示可以根據需要包含一個以上的條目。可以在語句中使用的關鍵字及其說明如表3-10所示:
表3-10 ASP指令關鍵字及說明
指令關鍵字
說 明
LANGUAGE=”language_name”
設定該網頁的預設的指令碼語言,如:
ENABLESESSIONSTATE=”True”|”Fasle”
當設定為“True”時,防止一個會話的cookie發送到瀏覽器,因此將不會建立新的Session對象,任何現有會話的內容將不再可用
CODEPAGE=”code_page”
設定該網頁的字碼頁,如
LCID=”locale_identifier”
設定該網頁的位置標識符,如
TRANSACTION=”transaction_type”
指明該網頁檔案在一個事務環境下運行。有效值是:
“Required”:如果已有可用的事務,指令碼將在其中運行;如果沒有可用的事務,啟動一個新的事務。
“Requires_New”:指令碼將初始化一個新的事務。
“Supported”:如果已有可用的事務,指令碼將在其中運行;而且不啟動一個新的事務。
“Not_Supported”:指令碼將不運行於任何已有的事務中,並且不初始化一個新的事務。
在第18章中詳細介紹事務。
在一個網頁上只能允許有一條處理指示,並且應該放在第一行。在處理指示中可以包含不止一個這樣的條目,但必須用空格進行分隔,等號兩端不能有空格,例如:
3.3.4 活動的ASP Application對象
我們提供一些簡單的網頁,這些網頁示範了使用過程中的ASP Application和Session對象。為了能夠正常使用,必須把它們放到伺服器上的一個虛擬應用程式內,並且把所提供的global.asa檔案放到該應用程式的根目錄中。最簡單的辦法是把global.asa檔案放到預設Web網站的根目錄(預設情況下是C:/InetPub/WWWRoot)中。
對任何已有的global.asa檔案重新命名是一個好辦法,可以在以後對該檔案進行恢複。
本書的所有例子檔案都可以從我們的Web網站上得到,在例子的Chapter03子目錄中還有本章的所有其餘樣本網頁。
在Chapter03子目錄中,Default.asp網頁是一個簡單的菜單,該菜單允許運行Application和Session樣本網頁,運行螢幕3-13所示:
1. 顯示Application集合的內容
單擊第一個連結,開啟名為show_application.asp的Application對象樣本頁面。它顯示了虛擬應用程式當前的Application對象的內容,3-14所示:
注意到ASPCounter對象是StaticObjects集合的一個成員(通過元素進行定義),但是其餘部份(由Server.CreateObject執行個體化)是Contents集合的成員。
可以看到使用global.asa例子網頁放到這些集合中的值,這在前面已經看到:
PROGID=”MSWC.Counters”>
...
...
(1) 遍曆Contents集合的代碼
為了遍曆Contents集合,可使用一個For Each ... Next結構。集合中的每一項可以是一個簡單的Variant類型變數、一個Variant數組或者一個對象的引用。因為需要對每種類型的值進行不同的處理,所以就不得不對每一個進行檢查來判別其類型。
在VBScript中可使用VarType函數完成這個工作。這裡使用IsObject和IsArray函數代替:
For Each objItem in Application.Contents
If IsObject(Application.Contents(objItem)) Then
Response.Write “Object reference: ‘” & objItem & “'
”
ElseIf IsArray(Application.Contents(objItem)) Then
Response.Write “Array: ‘” & objItem & “' contents are:
”
VarArray = Application.Contents(objItem)
‘Note: the following only works with a one-dimensional array
For intLoop = 0 To UBound(varArray)
Response.Write “ Index(“ & intLoop & “) = “ & _
VarArray(intLoop) & “
”
Next
Else
Response.Write “Variable: ‘” & objItem & “' = “ _
& Application.Contents(objItem) & “
”
End If
Next
注意程式如何從Application對象檢索該數組。將其分配給一個局部(Variant)變數,使用下面的語句:
varArray = Application.Contents(objItem)
使用UBound函數可以尋找出數組的大小(元素的數量),這個值可以作為遍曆的終止條件:
For intLoop = 0 UBound(varArray)
這個例子是一維數組,並將只顯示這樣的一個數組的內容。可根據需要編輯代碼以處理多維陣列,例如:
For intLoop = 0 To UBound(varArray)
IntNumberOfDimensions = UBound(varArray, 1)
For intDimension = 0 To intNumberOfDimensions
Response.Write “ Index(“ & intLoop & “) = “ _
& varArray(intLoop, intDimension)
Next
Response.Write “
”
Next
(2) 遍曆StaticObjects集合的代碼
StaticObjects集合包含了所有在global.asa中使用元素宣告的對象引用。因為每個條目都是一個物件變數,可用簡單些的代碼對這個數組進行遍曆。我們將輸出對象的名字(在ID屬性中原有的定義):
For Each objItem in Application.StaticObjects
If IsObject(Application.StaticObjects(objItem)) Then
Response.Write “element: ID='” & objItem & “'
”
End If
Next
(1) 遍曆Contents集合的代碼
為了遍曆Contents集合,可使用一個For Each ... Next結構。集合中的每一項可以是一個簡單的Variant類型變數、一個Variant數組或者一個對象的引用。因為需要對每種類型的值進行不同的處理,所以就不得不對每一個進行檢查來判別其類型。
在VBScript中可使用VarType函數完成這個工作。這裡使用IsObject和IsArray函數代替:
For Each objItem in Application.Contents
If IsObject(Application.Contents(objItem)) Then
Response.Write “Object reference: ‘” & objItem & “'
”
ElseIf IsArray(Application.Contents(objItem)) Then
Response.Write “Array: ‘” & objItem & “' contents are:
”
VarArray = Application.Contents(objItem)
‘Note: the following only works with a one-dimensional array
For intLoop = 0 To UBound(varArray)
Response.Write “ Index(“ & intLoop & “) = “ & _
VarArray(intLoop) & “
”
Next
Else
Response.Write “Variable: ‘” & objItem & “' = “ _
& Application.Contents(objItem) & “
”
End If
Next
注意程式如何從Application對象檢索該數組。將其分配給一個局部(Variant)變數,使用下面的語句:
varArray = Application.Contents(objItem)
使用UBound函數可以尋找出數組的大小(元素的數量),這個值可以作為遍曆的終止條件:
For intLoop = 0 UBound(varArray)
這個例子是一維數組,並將只顯示這樣的一個數組的內容。可根據需要編輯代碼以處理多維陣列,例如:
For intLoop = 0 To UBound(varArray)
IntNumberOfDimensions = UBound(varArray, 1)
For intDimension = 0 To intNumberOfDimensions
Response.Write “ Index(“ & intLoop & “) = “ _
& varArray(intLoop, intDimension)
Next
Response.Write “
”
Next
(2) 遍曆StaticObjects集合的代碼
StaticObjects集合包含了所有在global.asa中使用元素宣告的對象引用。因為每個條目都是一個物件變數,可用簡單些的代碼對這個數組進行遍曆。我們將輸出對象的名字(在ID屬性中原有的定義):
For Each objItem in Application.StaticObjects
If IsObject(Application.StaticObjects(objItem)) Then
Response.Write “element: ID='” & objItem & “'
”
End If
Next
1. 增加值到Contents集合
增加值到Contents集合的方法,與在global.asa網頁的指令碼代碼中使用過的方法相同。樣本網頁允許把一個新的Variant值增加到Application對象中,並已有建議的名字和值(可根據需要進行編輯),3-15所示:
單擊按鈕,重新載入這個網頁,把值增加到Application.Contents集合中,並且在列表中顯示,3-16所示:
增加新的Contents條目的代碼
所有的按鈕和其他HTML控制項放置在樣本網頁中的一個表單上。ACTION設定了當前網頁的路徑,提交該表單時,重新裝入。METHOD屬性為“POST”,所以控制項中的值出現在Request.Form集合中。在以前的章節中採用過這兩種技術:
" METHOD="POST">
Your Session Has Been Terminated
A new Session will be started when you load another
ASP page. It will contain any values that are defined in
the global.asa file for this application.
Return to the previous page
結果3-21所示。這時,當前的使用者會話已經被終止(放棄),並且該使用者不能引用原先的Session集合或屬性的內容:
然而,記住這一切是在調用Abandon方法的網頁執行時,甚至在對該方法的調用已經完成以後,仍能夠從Session對象中獲得使用者的會話內容。當此網頁結束時,會話才結束。
當然,當返回到顯示會話內容的Session對象樣本網頁時,將啟動一個新的ASP會話。它將有一個不同的Start_Time值和通過執行global.asa中的代碼建立的其他預設的會話值,3-22所示:
注意,Session.SessionID屬性值沒有改變。ASP試圖重新分配相同的會話ID,因此不能依靠該值來判定一個新的會話已經啟動。
3.4 小結
本章介紹了兩個ASP內建對象:Application和Session對象。這些對象引入了ASP的應用程式和使用者會話的概念(兩者都是特定的術語,並且不是通常談話時的意義)。ASP應用程式允許分配專門的屬性給頁面集,定義了IIS和ASP如何管理這些網頁及所使用的其他組件。
然而,使用ASP應用程式和會話的主要原因是需要自動地獲得狀態。換句話說,儲存資訊和變數引用的能力,要麼對使用者裝載的所有網頁是全域和可用的(即在一個應用程式中),要麼僅僅對一個指定的使用者的所有網頁是可用的(在一個會話中)。這使建立Web應用程式變得非常簡單(即應用程式在Web上工作,但能夠像傳統的編譯的應用程式一樣能完成指定的任務)。
本章通過一些樣本頁面,詳細介紹如何使用ASP的Application和Session對象。這些頁面示範了這兩個對象可用的所有技術。