|
深入研究Application和Session對(duì)象
邊緣孤星淚 ·yesky
用ASP編寫虛擬社區(qū)、網(wǎng)上購(gòu)物等程序時(shí),Application和Session對(duì)象具有舉足輕重的作用,能夠靈活合理地運(yùn)用這兩 個(gè)對(duì)象是提高程序質(zhì)量的關(guān)鍵。下面讓筆者根據(jù)自己在這方面的經(jīng)驗(yàn),向大家深入介紹一下ASP的這兩個(gè)內(nèi)建對(duì)象。
一、Application對(duì)象的成員概述
Application對(duì)象成員包括Application對(duì)象的集合、方法和事件。
、盇pplication對(duì)象的集合
Contents集合:沒有使用<OBJECT>元素定義的存儲(chǔ)于Applicaiton對(duì)象中的所有變量的集合
StaticObjects:使用<OBJECT>元素定義的存儲(chǔ)于Application對(duì)象中的所有變量 的集合
例:在default.asp中有如下賦值
application("a")="a"
application("b")=128
application("c")=false
則有contents集合
application.contents(1)="a" '也可寫為application.contents("a")="a"
application.contents(2)=128 '也可寫為application.contents("b")=128
application.contents(3)=false '也可寫為application.contents("c")=false
在此筆者推薦你在調(diào)用時(shí)使用類如application.contents("a")的方法,因?yàn)檫@樣更為直觀,如果用序號(hào)來(lái)表示的話則 要考慮賦值的先后順序。
、睞pplication對(duì)象的方法
Contents.Remove("變量名"):從Application.Contents集合中刪除指定的變量
Contents.RemoveAll() :把Application.Contents集合中的所有變量刪除
Lock() :鎖定Application對(duì)象,使得只有當(dāng)前的ASP頁(yè)對(duì)內(nèi)容能進(jìn)行訪問
Unlock() :解除對(duì)Application對(duì)象的鎖定
例:在default.asp中:
application("a")="a"
application("b")=128
application("c")=false
response.write application.contents(1)&"<br>"
response.write application.contents(2)&"<br>"
response.write application.contents(3)&"<br>"
response.write "After Remove b:"
application.contents.remove("b")
response.write application.contents(1)&"<br>"
response.write application.contents(2)&"<br>"
執(zhí)行結(jié)果:
a
128
False
After Remove b:
a
False
如果要?jiǎng)h除集合中所有變量用application.contents.removeall即可,至于Lock和Unlock方法在實(shí)際中經(jīng)常用到,讀 者也比較熟悉,在此就不在累贅。
、矨pplication對(duì)象事件
OnStart:第一個(gè)訪問服務(wù)器的用戶第一次訪問某一頁(yè)面時(shí)發(fā)生
OnEnd :當(dāng)最后一個(gè)用戶的會(huì)話已經(jīng)結(jié)束并且該會(huì)話的OnEnd事件所有代碼已經(jīng)執(zhí)行完畢后發(fā)生,或最后一個(gè)用戶訪問 服務(wù)器一段時(shí)間(一般為20分鐘)后仍然沒有人訪問該服務(wù)器產(chǎn)生。
想要定義application對(duì)象的OnStart和OnEnd事件里做什么需要將代碼寫在Global.asa這個(gè)文件里(下文有舉例),并 且將該文件放在站點(diǎn)的根目錄下(一般是Inetpub\wwwroot\)
二、Session對(duì)象的成員概述
Session對(duì)象的成員比Application對(duì)象多一項(xiàng)屬性,即:集合、屬性、方法、事件
、盨ession對(duì)象的集合
Contents :沒有使用<OBJECT>元素定義的存儲(chǔ)于特定Session對(duì)象的所有變量的集合。
StaticObject:使用<OBJECT>元素定義的、存儲(chǔ)于Session對(duì)象中的所有變量的集合。
例:在default.asp中有如下賦值
session("a")="a"
session("b")=128
session("c")=false
則有contents集合
session.contents(1)="a" '也可寫為session.contents("a")="a"
session.contents(2)=128 '也可寫為session.contents("b")=128
session.contents(3)=false '也可寫為session.contents("c")=false
、睸ession對(duì)象的屬性
CodePage: 可讀/可寫。整型。定義用于在瀏覽器中顯示頁(yè)內(nèi)容的代碼頁(yè)。代碼頁(yè)是字符集的數(shù)字值,不同的語(yǔ)言使用 不同的代碼頁(yè)。例如,ANSI代碼頁(yè)為1252,日文代碼頁(yè)為932,簡(jiǎn)體中文代碼頁(yè)為936。
LCID : 可讀/可寫。整型。定義發(fā)送給瀏覽器的頁(yè)面地區(qū)標(biāo)識(shí)。LCID是唯一地標(biāo)識(shí)地區(qū)的一個(gè)國(guó)際標(biāo)準(zhǔn)縮寫,例如, 2057定義當(dāng)前地區(qū)的貨幣符號(hào)是"£"。
SessionID: 只讀。長(zhǎng)整型。返回本會(huì)話的會(huì)話標(biāo)識(shí)符。每創(chuàng)建一個(gè)會(huì)話,由服務(wù)器自動(dòng)分配一個(gè)標(biāo)識(shí)符?梢愿鶕(jù)它 的值判斷兩個(gè)用戶是誰(shuí)先訪問服務(wù)器。
Timeout : 可讀/可寫。整型。為會(huì)話定義以分鐘為單位的超時(shí)限定。如果用戶在這個(gè)時(shí)間內(nèi)沒有刷新或請(qǐng)求任何一個(gè) 網(wǎng)頁(yè),則該用戶產(chǎn)生的會(huì)話自動(dòng)結(jié)束。缺省值是20。
以上屬性在實(shí)際應(yīng)用中作用不大,而且基本上不需要怎么修改,這幾個(gè)屬性也沒什么特殊的地方。
、砈ession對(duì)象的方法
Contents.Remove("變量名"): 從Session.contents集合中刪除指定的變量
Contents.Removeall() : 刪除Session.contents集合中的所有變量
Abandon() : 結(jié)束當(dāng)前用戶會(huì)話并且撤消當(dāng)前Session對(duì)象。
Session對(duì)象的Contents.Remove("變量名")和Contents.Removeall()方法與Application對(duì)象的基本上沒什么區(qū)別,為 幫助理解,大家可以參照上面的例子將Application改為Session。這里要說(shuō)明一下的是Contents.Removeall()和Abandon() 的區(qū)別,執(zhí)行這兩個(gè)方法都會(huì)釋放當(dāng)前
用戶會(huì)話的所有Session變量,不同的是Contents.Removeall()單純地釋放Session變量的值而不終止當(dāng)前的會(huì)話,而 Abandon()除了釋放Session變量外還會(huì)終止會(huì)話引發(fā)Session_OnEnd事件,希望大家注意兩者的區(qū)別。
、碨ession對(duì)象的事件
OnStart: 當(dāng)ASP用戶會(huì)話產(chǎn)生時(shí)觸發(fā),一旦有任一用戶對(duì)本服務(wù)器請(qǐng)求任一頁(yè)面即產(chǎn)生該事件。
OnEnd : 當(dāng)ASP用戶會(huì)話結(jié)束時(shí)觸發(fā),當(dāng)使用Abandon()方法或超時(shí)也會(huì)觸發(fā)該事件。
這兩個(gè)事件和Application的OnStart、OnEnd事件一樣,也是必須放在Global.asa文件里,下 面就重點(diǎn)和大家研究一下這四個(gè)事件的使用。
三、Global.asa
ASP的Application和Session對(duì)象體現(xiàn)了其他ASP內(nèi)置對(duì)象所沒有的特征--事件。每一個(gè)訪客訪問服務(wù)器時(shí)都會(huì)觸發(fā)一 個(gè)OnStart事件(第一個(gè)訪客會(huì)同時(shí)觸發(fā)Application和Session的OnStart事件,但Application先于Session),每個(gè)訪客 的會(huì)話結(jié)束時(shí)都會(huì)觸發(fā)一個(gè)OnEnd事件(最后一個(gè)訪客會(huì)話結(jié)束時(shí)會(huì)同時(shí)觸發(fā)Application和Session的OnEnd事件,但 Session先于Application)。
OnStart和OnEnd這兩個(gè)事件一般應(yīng)用在虛擬社區(qū)中統(tǒng)計(jì)在線人數(shù)、修改用戶的在線離線狀態(tài)等。要具體定義這兩個(gè)事 件,需要將代碼寫在Global.asa文件,并將該文件放在站點(diǎn)的根目錄下(缺省是\Inetpub\wwwroot\)。另外, Application和Session對(duì)象規(guī)定了在OnEnd事件里除了Application對(duì)象外其他ASP內(nèi)置對(duì)象(Response、Request、 Server、Session...)一概不能使用。以下舉一個(gè)虛擬社區(qū)統(tǒng)計(jì)在線人數(shù)的例子來(lái)說(shuō)明如何使用這兩個(gè)事件。
文件說(shuō)明:
global.asa 位于d:\Inetpub\wwwroot\目錄下
default.asp 位于d:\Inetpub\wwwroot\目錄下,虛擬社區(qū)登錄頁(yè)面
login.asp 位于d:\Inetpub\wwwroot\目錄下,用于檢測(cè)用戶輸入的用戶名及密碼
index.asp 位于d:\Inetpub\wwwroot\目錄下,虛擬社區(qū)首頁(yè)
bbs.mdb 位于d:\Inetpub\wwwroot\目錄下,存儲(chǔ)用戶信息的數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)(ACCESS)結(jié)構(gòu):
===bbs表===
id 用戶ID,長(zhǎng)整型
name 用戶名,文本型
code 密碼,文本型
online 在線狀態(tài),是/否
===global.asa===
。約cript LANGUAGE="VBScript" RUNAT="Server">
Sub Application_OnStart
application("online")=0
End Sub
sub Application_OnEnd
nd Sub
Sub Session_OnStart
End Sub
Sub Session_OnEnd
if session.contents("pass") then '判斷是否為登錄用戶的Session_OnEnd
application.lock
application("online")=application("online")-1
application.unlock
end if
End Sub
。/script>
==============
===login.asp===
......'密碼驗(yàn)證,連接數(shù)據(jù)庫(kù),檢測(cè)用戶輸入的用戶名及密碼是否正確
if 密碼驗(yàn)證通過(guò) then
session("name")=rs("name")
session("id")=rs("id")
session("pass")=true
else
rs.close
conn.close
response.write "密碼錯(cuò)誤!"
response.end
end if
application.lock
application("online")=application("online")+1
conn.Execute ("update bbs set online=1 where id="&session("id"))'將用戶的狀態(tài)設(shè)為在線
application.unlock
rs.close
conn.close
response.redirect "index.asp" '初始化數(shù)據(jù)后跳轉(zhuǎn)到社區(qū)首頁(yè)
===========
在本例中,用application("online")變量記錄已經(jīng)登錄社區(qū)的在線人數(shù),因?yàn)橐坏┯杏脩粼L問服務(wù)器而不管用戶是否 登錄,都會(huì)產(chǎn)生OnStart事件,所以不能在OnStart事件里使Applicaiton("online")加一。因?yàn)椴还苁欠袷堑卿浻脩舻臅?huì)話 結(jié)束都會(huì)產(chǎn)生OnEnd事件(假如有訪客訪問了服務(wù)器但并不登錄社區(qū),他的會(huì)話結(jié)束后也會(huì)產(chǎn)生OnEnd事件),所以在 Session_OnEnd事件里用了句if語(yǔ)句來(lái)判斷是否為已登錄用戶的OnEnd事件,如果是才將在線人數(shù)減一。
這只是一個(gè)統(tǒng)計(jì)在線人數(shù)的簡(jiǎn)單例子,對(duì)于一個(gè)完整的虛擬社區(qū)來(lái)說(shuō),僅僅統(tǒng)計(jì)有多少人在線是不夠的,在本例中數(shù) 據(jù)庫(kù)里有個(gè)online字段是用來(lái)記錄用戶的在線狀態(tài),用戶登錄的時(shí)候,在login.asp里將online設(shè)為1,但用戶離線時(shí)并沒 有將online設(shè)為0,要完善它,就要修改一下Session_OnEnd事件,在該事件里將online設(shè)為0。
===global.sas===
。約cript LANGUAGE="VBScript" RUNAT="Server">
Sub Application_OnStart
application("online")=0
set application("conn")=Server.CreateObject("ADODB.Connection")
application("db")=Server.MapPath("\bbs.mdb") '此處最好使用絕對(duì)路徑\bbs.mdb,下文有詳細(xì)介紹
End Sub
sub Application_OnEnd
set application("conn")=nothing
End Sub
Sub Session_OnStart
End Sub
Sub Session_OnEnd
if session.contents("pass") then '判斷是否為登錄用戶的Session_OnEnd
application("con").open ="driver={Microsoft Access Driver (*.mdb)};dbq="&application("db")
application.lock
application("online")=application("online")-1
application("con").Execute ("update friends set online=0 where id="&session.contents("id"))
application.unlock
application("con").close
end if
End Sub
。迹痵cript>
==============
至此,完整的代碼已經(jīng)完成了。因?yàn)樵贏pplication和Session的OnEnd事件里不能使用Server對(duì)象,所以要將數(shù)據(jù)庫(kù)的 連接及數(shù)據(jù)庫(kù)在服務(wù)器上的物理地址(d:\inetpub\wwwroot\bbs.mdb)存儲(chǔ)在application變量中,并在 Application_OnStart事件中預(yù)先處理。同理,在Session_OnEnd事件中不能用session("pass")來(lái)代替session.contents ("pass")(以下有詳盡說(shuō)明)。
四、本文實(shí)例中值得引起注意的兩點(diǎn)
、監(jiān)nEnd事件里的session.contents
剛開始接觸global.asa的朋友經(jīng)常會(huì)將上面Session_OnEnd事件里的
if session.contents("pass") then 寫成
if session("pass") then,
這樣的話系統(tǒng)不會(huì)提示錯(cuò)誤,但是永遠(yuǎn)也不會(huì)執(zhí)行then后面的內(nèi)容,這是因?yàn)樵贠nEnd事件里禁止使用Session對(duì)象, 但是可以用Session對(duì)象的集合來(lái)調(diào)用session變量。因?yàn)镮IS并沒提示任何錯(cuò)誤信息,所以筆者曾經(jīng)在這上面浪費(fèi)了很多時(shí) 間。在此希望大家引以為鑒!
、睞pplication_OnStart事件里用Server.MapPath獲取數(shù)據(jù)庫(kù)的物理地址時(shí)應(yīng)使用絕對(duì)地址為了說(shuō)明這個(gè)問題,大家可 以做個(gè)實(shí)驗(yàn):將上面Application_OnStart事件里的
application("db")=Server.MapPath("\bbs.mdb")改為:
application("db")=Server.MapPath("bbs.mdb")
然后在d:\inetpub\wwwroot\目錄下建立一個(gè)test子目錄,寫一個(gè)temp.asp在test目錄里。
====test.asp====
。迹esponse.write application("db")%>
================
再將temp.asp拷貝一份放在根目錄下(d:\inetpub\wwwroot\)。用記事本打開global.asa,再打開兩個(gè)瀏覽器,瀏覽器A 輸入地址http://localhost/temp.asp,按回車,將在瀏覽器上輸出:
d:\inetpub\wwwroot\bbs.mdb
然后,在記事本的窗口上點(diǎn)"文件"菜單,選"保存"(使global.asa的修改時(shí)間改變,從而使IIS重啟動(dòng)所有服務(wù)),再在瀏 覽器B輸入地址http://localhost/test/temp.asp,按回車,在瀏覽器上輸出的是:
d:\inetpub\wwwroot\test\bbs.mdb
global.asa文件雖然是放在站點(diǎn)根目錄下,但是如果在server.mappath中使用的是相對(duì)地址,而觸發(fā)Application_OnStart 事件的用戶第一次訪問的頁(yè)面又不是屬于根目錄的話,得到數(shù)據(jù)庫(kù)的物理地址將不會(huì)是期望的結(jié)果,希望大家要特別小 心。
|
溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!