HTTP 是 stateless 的 connection,換句話說,若無特殊設定,伺服器對每一個 request ,除了 log 記錄外,並不會留下其他特別的記錄,而是對每一個 request 一視同仁。因此,如果我們希望能在不同的 request 之間共享資訊,就必須靠一些特殊的方法來保存或傳送變數的方法,這些方法可以整理如下:
方法 溝通對象
Cookies 一個用戶端和各個網頁之間的資料共享
Form 經由表單來進行網頁間的資料傳遞和保存
Application 物件 一個 Web 應用程式和各個用戶端之間的資料共享
Session 物件 一個用戶端和各個 Web 應用程式之間的資料共享
在前面幾章的介紹中,我們已經說明了 Cookies 和 表單(Forms)的用法,本節及下節將著重於 Application 和 Session 物件如何用來存放與傳送變數。
對於 Web 伺服器的執行環境而言,一個虛擬目錄(即由用戶端看到 Web 伺服器的第一層目錄)之下的所有 ASP 程式,即構成了一個 Web 的應用程式(Application),來自世界各地的用戶端,都可以經由 Internet 來呼叫同一個應用程式,如果希望這些呼叫同一個應用程式的用戶端能夠「看到」一些共用的資訊,就必須靠 Application 物件。
Application 物件提供四種方法(Methods)、兩個事件(Events)與兩個集合(Collections),列表如下:
Application 物件提供的方法
方法 說明
Lock 鎖住 Application 物件,不讓其他使用者改變 Application 物件的任何資訊
Unlock 解除 Lock 狀態
Contents.Remove(item or index ) 從 Contents 集合中刪除一個項目
Contents.RemoveAll 從 Contents 集合中刪除所有項目
Application 物件提供的事件
事件 說明
OnStart 啟動一個 Application 物件時所觸發的函數,此函數必須放在 global.asa 檔案
OnEnd 結束一個 Application 物件時所觸發的函數,此函數必須放在 global.asa 檔案
Application 物件提供的集合
集合 說明
Contents 以程式碼加在 Application 物件的所有變數的集合
StaticObjects 以 Object 標籤加在 Application 物件的所有物件的集合
我們以訪客計數器來來說明 Application 物件的應用,可分兩部分說明:
在第一次啟動 Application 物件時,將 Application("Counter") 設定為零。
在被計數的網頁中,將 Application("Counter") 的值加一。換句話說,只要每次有使用者瀏覽此網頁,Application("Counter") 的值就會加一,其值即代表此網頁被點選的次數。
Hint Application("Counter") 是 Application.Contents("Counter") 的簡寫。
當伺服器啟動後,在 Web 應用程式(即虛擬目錄下的 ASP 檔案)中,若有任一網頁被點選,即代表相關 Application 物件的啟動,此時 ASP 解譯器會在虛擬目錄下尋找 global.asa 的檔案(其中副檔名 ASA 代表 Active Server Application),並執行此檔案中的 Application_OnStart() 函數。以訪客計數器而言,我們可在 global.asa 內的 Application_OnStart() 函數中,將變數 Application("Counter") 的值預設為零,之後若有計數網頁,就可以將此變數值加 1。此範例的 global.asa 可列出如下:
原始檔(application/global.asa ): (灰色區域按兩下即可拷貝) ' Application 物件啟動時該做的事
Sub Application_OnStart()
Application("Counter") = 0
End Sub
' Application 物件結束時該做的事
Sub Application_OnEnd()
' Nothing to do here
End Sub
請注意,上述 global.asa 中的程式碼是 VBScript。但事實上,若不使用 global.asa,也可以寫出一個簡單的計數網頁,請見下列範例:
Example(application/pagehit01.asp ):
上述範例的原始檔如下:
原始檔(application/pagehit01.asp ): (灰色區域按兩下即可拷貝) <%@language=JScript%>
<%title="使用 Application 物件的計數網頁的完整範例"%>
<!--#include file="../head.inc"-->
<hr>
<%
if (Application("Counter")==null) // 若 Application("Counter") 不存在,則設定其為 0
Application("Counter")=0;
function PageHitCounter(){
Application.Lock(); // 鎖住 Application 物件,不讓其他使用者改變 Application 物件的任何資訊
Application("Counter")++; // 計數變數加1
Application.UnLock(); // 解除 Application 物件的鎖定狀態
return(Application("Counter"));
}
%>
<h3 align=center>您是第 <font color=red><%=PageHitCounter()%></font> 位貴賓!</h3>
<hr>
<!--#include file="../foot.inc"-->
在上述範例中,Application.Lock 可以鎖住 Application 物件,不讓其他使用者改變 Application 物件的任何資訊,如此可避免兩個同時的 Requests 可能對 Application 造成錯誤動作。
事實上,由於計數器只是一個小程式,發生少許誤差也無所謂,因此上述範例可改寫成更簡單的形式,如下:
Example(application/pagehit02.asp ):
上述範例的原始檔如下:
原始檔(application/pagehit02.asp ): (灰色區域按兩下即可拷貝) <%@language=JScript%>
<%title="使用 Application 物件的計數網頁的精簡範例"%>
<!--#include file="../head.inc"-->
<hr>
<% if (Application("Counter")==null) // 若 Application("Counter") 不存在,則設定其為 0
Application("Counter") = 0; %>
<h3 align=center>您是第 <font color=red><%=++Application("Counter")%></font> 位貴賓!</h3>
<hr>
<!--#include file="../foot.inc"-->
若希望將上述程式碼反覆用在不同的網頁,而且每一個網頁都有獨立的計數功能,最簡單的方法,就是將 "Counter" 代換為隨網頁而不同的變數,例如網頁的網址 Request.ServerVariables("URL"),例如:
Example(application/pagehit03.asp ):
上述範例的原始檔如下:
原始檔(application/pagehit03.asp ): (灰色區域按兩下即可拷貝) <%@language=JScript%>
<%title="獨立功能的計數網頁:以 URL 為 Application 物件的變數名稱"%>
<!--#include file="../head.inc"-->
<hr>
<%
url = Request.ServerVariables("URL");
if (Application(url) == null)
Application(url) = 0; // 若 Application(url) 不存在,則設定其為 0
%>
<h3 align=center>您是第 <font color=red><%=++Application(url)%></font> 位貴賓!</h3>
<hr>
<!--#include file="../foot.inc"-->
如果要知道計數器的啟動時間,就可以在計數變數為 Null(用於 JScript)或 Empty(用於 VBScript)時,將時間以另外一個 Application 變數記錄下來,如下例:
Example(application/pagehit04.asp ):
上述範例的原始檔如下:
原始檔(application/pagehit04.asp ): (灰色區域按兩下即可拷貝) <%@language=JScript%>
<%title="顯示計數器啟動時間的範例"%>
<!--#include file="../head.inc"-->
<hr>
<%
url = Request.ServerVariables("URL");
theStartTime = "startTime: " + url;
if (Application(theStartTime) == null){ // 伺服器起動後,本網頁第一次被呼叫時的動作
Application(url) = 0;
now = new Date();
Application(theStartTime) = now.toLocaleString();
}
%>
<h3 align=center>從 <font color=green><%=Application(theStartTime)%></font> 以來,您是第 <font color=red><%=++Application(url)%></font> 位貴賓!</h3>
<hr>
<!--#include file="../foot.inc"-->
Hint 無論是使用 JScript 或 VBScript,都可以存取到相同的 Application 物件與變數。
上述範例是較簡單的網頁點選計數方法,但有下列缺點:
用戶端只要一再點選瀏覽器的「檢視/重新整理」(View/Reload)或是 F5 按鈕,計數器就會一直累加,所以不是很準。
伺服器重開機時,Application 物件會被清除,因此所有的計數資料就不見了,一切歸零。
要解決第一個問題,可用 Session 物件,將在下節介紹。要解決第二個問題,則要將計數資料寫入檔案,後面再詳細介紹。
Application.Contents 和 Application.StaticObjects 都是 Dictionary 變數,所以都可以直接用程式碼將其內容一一印出,例如:
Example(application/listAppVar01.asp ):
上述範例的原始檔如下:
原始檔(application/listAppVar01.asp ): (灰色區域按兩下即可拷貝) <%@language=JScript%>
<% title = "印出 Application.Contents 和 Application.StaticObjects 的內容" %>
<!--#include file="../head.inc"-->
<hr>
<!--#include file="../listdict.inc"-->
<p><% listdict(Application.Contents, "Application.Contents"); %>
<p><% listdict(Application.StaticObjects, "Application.StaticObjects"); %>
<hr>
<!--#include file="../foot.inc"-->
我們可以使用 Application.Contents.Remove() 或 Application.Contents.Removeall() 來刪除 Application 變數,範例如下:
Example(application/listAppVar02.asp ):
上述範例的原始檔如下:
原始檔(application/listAppVar02.asp ): (灰色區域按兩下即可拷貝) <%@language=JScript%>
<% title = "刪除所有 Application 變數後,再印出 Application.Contents 和 Application.StaticObjects 的內容" %>
<!--#include file="../head.inc"-->
<hr>
<% Application.Contents.Removeall()%>
<!--#include file="../listdict.inc"-->
刪除所有 Application 變數後,再進行列表:
<p><% listdict(Application.Contents, "Application.Contents"); %>
<p><% listdict(Application.StaticObjects, "Application.StaticObjects"); %>
<hr>
<!--#include file="../foot.inc"-->
和 Application 變數相關的常見應用如下:
網頁記數器。
線上投票區。
更新正確上線人數(如聊天室)。
JScript 程式設計與應用:用於伺服器端的 ASP 環境