上篇博文介紹了在客戶端狀態管理的兩種方式:http://www.cnblogs.com/wolf-sun/p/3329773.html。除了在客戶端上保存狀態外,還可以在服務器上保存狀態。使用客戶端的狀態,其缺點在於增加了數據在網絡之間的傳送。使用服務器端狀態的缺點在於,服務器必須給客戶端分配資源,下面詳細討論服務器端的狀態管理技術。
服務器端的狀態管理
- Session
會話狀態與瀏覽器會話相關。客戶在服務器上第一次打開Asp.Net頁面時,會話就開始了。當客戶在20分鍾之內沒有訪問服務器,會話結束,銷毀session。
可以在Global Application類(即全局應用程序類)中定義自己的代碼,會話開始或結束時運行。會創建Global.asax文件。在這個文件中,定義了一些時間處理程序例程:

1 public class Global : System.Web.HttpApplication 2 { 3 4 protected void Application_Start(object sender, EventArgs e) 5 { 6 7 } 8 9 protected void Session_Start(object sender, EventArgs e) 10 { 11 12 } 13 14 protected void Application_BeginRequest(object sender, EventArgs e) 15 { 16 17 } 18 19 protected void Application_AuthenticateRequest(object sender, EventArgs e) 20 { 21 22 } 23 24 protected void Application_Error(object sender, EventArgs e) 25 { 26 27 } 28 29 protected void Session_End(object sender, EventArgs e) 30 { 31 32 } 33 34 protected void Application_End(object sender, EventArgs e) 35 { 36 37 } 38 }
會話狀態可以存儲在HttpSessionState對象中。與當前Http環境相關的會話狀態對象可以使用Page類的Session屬性來訪問。在Session_Start()事件處理程序中,可以初始化會話變量。在下面的實例中,名為mydata的會話狀態被初始化為0:
1 protected void Session_Start(object sender, EventArgs e) 2 { 3 Session["mydata"] = 0; 4 }
可以在頁面中通過使用會話狀態名讀取會話狀態。
1 protected void Unnamed2_Click(object sender, EventArgs e) 2 { 3 int val = (int)Session["mydata"]; 4 myLabel.Text = val.ToString(); 5 val += 5; 6 Session["mydata"] = val; 7 }
要把客戶端與其會話變量關聯起來,ASP.NET默認使用一個臨時cookie和一個會話標識符(SessionId)。Asp.Net也支持沒有cookie的會話,其中的URL標識符用於把Http請求映射到同一個會話。
Session的銷毀:
Session.Abandon();//銷毀服務器端的Session對象 Session.Clear();//清空服務端的Session對象里的鍵值對,Session對象並沒有從Session池里銷毀
Session常用屬性、方法
屬性 | 描述 |
SessionID | 唯一用戶會話標識符 |
TimeOut |
用戶超時(單位:分鍾),默認20分鍾 |
Count |
會話狀態集合中的項目數 |
方法 |
描述 |
Abandon方法 |
用於顯式結束會話。 |
Session的作用 就像你的銀行賬戶,錢(數據)都存在銀行里,你就拿一張銀行卡(包含SessionId)回家,你每次去銀行取錢,只需要帶着銀行卡(包含SessionId)就可以了。銀行就知道該將哪個賬戶的錢(數據)給你。而不是別人賬戶里的。每次取錢必須帶着卡才行,所以瀏覽器的每次請求,也必須帶着sessionid取數據。
Session總結
(之前筆記中摘錄別人的一段,很容易理解,作者如果看到望指出,我將鏈接添加到文章中。)
- Session提供了一種把信息保存在服務器內存中的一種方式。它能存儲任何數據類型包括自定義對象。所以像Session["user"]的返回類型是object類型。根據你想要的類型,需要進行類型轉換。
- 每個客戶端的Session是獨立存儲(sessionid唯一標識)。
- Session 對象用於存儲有關用戶的信息(比如在驗證用戶是否登錄,此時可以通過判斷Session[“user”]是否為null進行判斷)。
- 在整個用戶會話過程中都會保留此信息。(保存SessionId的cookie丟失之前)
- 當用戶在應用程序中從一個網頁瀏覽到另一個網頁時,存儲在 Session 對象中的變量不會被丟棄。(這里就感覺像全局變量了)
- Session只可由該會話的用戶訪問(因為SessionId以cookie的方式保存訪問者瀏覽器的緩存里,關閉瀏覽器就沒了)
- 用戶不能訪問或修改他人的Session(sessionid唯一標識)
- ASP.Net已經內置了Session機制。不要放太多的對象到Session(因為存儲在服務器端的一個輔助進程里,不穩定,數據多了容易丟失。),Session會有超時銷毀的機制。
-
Cookie是存在客戶端,Session是存在服務器端,目的是一樣的:保存和當前客戶端相關的數據(當前網站的任何一個頁面都能取到Session、Cookie)。
-
如果瀏覽器禁用了Cookie可以啟用Url來傳遞SessionID。
-
可以看到Session機制並不是Http協議規定的,是ASP.net實現的,現在PHP、JSP等大部分服務端技術都實現了Session,原理都差不多。
-
Session有 自動銷毀機制(設置失效時間,默認就是滑動過期機制),如果一段時間內瀏覽器沒有和服務器發生任何的交互,則Session會定時銷毀。
注意:當會話過期或終止時,服務器就會清除 Session 對象
關於Sesiion的存儲方式:http://www.cnblogs.com/zhangkai2237/archive/2012/03/22/2410890.html可以看這個文章寫的不錯。這里就不再贅述了。
2.Application
字面翻譯:應用程序狀態,如果數據應在多個客戶端共享,就可以使用應程序狀態來保存。應用程序狀態的使用方式跟Session非常相似。對於應用程序狀態,應使用HttpApplication類,通過Page類的Application屬性就可以訪問它。
Application可以用來統計訪問網站的人數,在啟動Web應用程序時,初始化應用程序變量userCount。Application_Start()是global.asax文件中的時間處理程序方法,在啟動網站的第一個Asp.Net頁面時調用該方法。
1 Void Application_Start(Object sender,EventArgs e) 2 { 3 Application["userCount"]=0; 4 }
在Session_Start()事件處理程序中,應用程序變量userCount的值會遞增。在改變應用程序變量之前,應用程序對象必須用Lock()方法鎖定,否則會出現線程問題,因為多個用戶可以同時訪問一個應用程序變量。在改變了應用程序變量的值后,還必須調用Unlock()方法。注意鎖定和解鎖時間的時間比較短,在此時間段內,不應讀文件或數據庫中的數據。否則,其他用戶就必須等到數據訪問完成之后才能操作。
還用取錢的例子打比方:Application的方式比較像去自動取款機取錢的模式,你進去取錢,需將門關上(Lock),你取完錢出來(Unlock),下一個人才能進去。這樣更容易理解。
protected void Session_Start(object sender, EventArgs e) { Application.Lock(); Application["userCount"] = (int)Application["userCount"] + 1; Application.UnLock(); }
讀取應用程序狀態中的數據與Session狀態中的數據一樣。
Label1.Text=Application["userCount"].ToString();
注意:不要在應用程序狀態中存儲太多的數據,因為應用程序狀態需要服務器資源,直到服務器停止或重啟之后,才會釋放這些資源。
3.Cache
高速緩存是服務端狀態,它類似於應用程序狀態,因為它在所有的客戶端上共享。高速緩存與應用程序狀態的區別是,高速緩存要靈活的多:定義狀態合適失效有很多方式。我們不是給每個請求讀取文件或數據庫,而是把數據存儲在高速緩存中。
對高速緩存,需要使用System.Web.Caching命名控件和Cache類。給高速緩存添加對象的過程如下:
Cache.Add("mycache",myobj,null,DateTime.MaxValue,TimeSpan.FromMinutes(10),CacheItemPriority.Normal,null);
Page類的Cache屬性返回一個Cache對象。使用Cache類的Add()方法,可以把任意對象賦予高速緩存。Add()的第一個參數定義了高速緩存項的名字。第二個參數是應被高速緩存的對象。第三個參數定義了依賴關系,例如高速緩存項可以依賴於一個文件:當文件改變時,高速緩存對象就會失效。在下面的示例中,沒有定義依賴關系,因為這個參數設置為null。
第4和5個參數用於設置高速緩存項的有效時間。第四個參數定義了高速緩存項失效的絕對時間,第五個參數定義了使高速緩存項失效的相對時間。在這個時間過后,就不能訪問高速緩存項了。下面的示例使用了相對時間,在高速緩存項試用了10分鍾之后失效。
第六個參數定義了高速緩存的優先級。CacheItemPriority是一個設置高速緩存優先級的枚舉。如果asp.net工作進程有很高的內存利用率,asp.net運行庫就根據優先級刪除高速緩存項。優先級較低的項先刪除。最后一個參數定義一個方法,在刪除高速緩存項時調用該方法。當高速緩存依賴於一個文件時,就可以使用最后一個參數:當文件改變時,就刪除高速緩存項,調用事件處理程序。通過這個事件處理程序,可以再次讀取文件,重新加載高速緩存。
使用前面介紹的索引符和會話狀態或應用程序狀態,就可以讀取高速緩存項。在使用從cache屬性返回的對象之前,必須檢查結果是否為null,當高速緩存失效時,結果就是null。如果從Cache索引符返回的值不是null,就可以對返回的對象進行類型轉換,用於存儲高速緩存項:
1 object o=Cache["mycahce"]; 2 if (o==null) 3 { 4 //緩存里沒數據 或者數據變化 重新獲取數據放入緩存 5 } 6 else 7 { 8 //從緩存中取數據 9 Myclass myobj=o as Myclass; 10 }
參考資料:
c#入門經典(第4版)及網絡資源
結語:
由於工作的原因,總是斷斷續續,今天終於將狀態保持的幾種方式整理完了。東西比較基礎,從之前筆記中摘抄了一部分(覺得能讓當時的自己理解的),LZ一直關注博客園,每天必看,看到的好東西總會記錄在本地筆記中,這么長時間了,很多不記得來源自哪篇文章了。實在對不起原文博主的辛勤勞動,但是從他們那里吸收了不少東西,也會慢慢的整理出來,也會加入一些自己的理解。這里真心感謝大牛們的分享,你們辛苦了。