研究方法:
1)Session。 ASP.NET提供Session讓我們可對工作狀態進行管理,可以讓我們跨越多個要求儲存與瀏覽器工作階段關連的訊息,Session提供Key-value pairs的方式來存取這些資料。雖然我們很常拿Session來儲存使用者的資訊,像是使用者的帳號或是一些其他資訊,不過Session是每個使用者各自有的,這裡面的資訊並不會共享,因此利用Session來達成需求顯然是不行。我們需要的應用系統的全域變數,或是資料結構來對整個系統的使用者進行管理。這樣的需求我想全域應用程式類別(預設檔名為Global.asax)就是我這邊提出的解答!
2)簡述關於Global.asax的運作。
當ASP.NET應用程式收到第一個要求的時候會先使用ApplicationManager建立應用程式定義域(應用程式定義域可以隔離應用程式間的全域變數,而且能夠允許每個應用程式個別進行卸載。)。在所有核心物件初始化後會藉由建立System.Web.HttpApplication類別的實體來執行應用程式。若應用程式中有Global.asax(繼承自HttpApplication)則會改用衍生自HttpApplication的Global.asax來建立執行應用程式的實體。而當處理要求的時候則會執行下述事件:(注意!這邊僅列達成需求出最主要的兩個)
///當要求ASP.NET應用程式中的第一個資源(如:網頁)時呼叫, ///這個方法在應用程式生命週期中只會被呼叫一次。 ///我們讓全域變數在這邊進行宣告。 Application_Start(object sender, EventArgs e) { } ///這個方法在MSDN裡面的解釋有點怪,不過在應用程式生命週期中該事件發生也是只有一次, ///就是當IIS重啟或是應用程式正常關閉時就會發起該事件。 ///我們讓全域變數所用到的資源在這裡釋放。 Application_End(object sender, EventArgs e) { }開始撰寫時我們要先準備一下這個管理使用者的容器類別:
/// 系統中記錄目前線上全部使用者的識別號的容器。 public sealed class SystemUserPool { private static ConcurrentDictionary<string, string> _UserPool = new ConcurrentDictionary<string, string>(); /// 記錄系統中新登入的使用者。 /// userNumber = 登入者的帳號。 /// userIp = 登入者的 IP 位址。 /// 使用者登入成功與否。 public Boolean AddUser(String userNumber, String userIp) { return _UserPool.TryAdd(userNumber, userIp); } /// 剔除系統中指定的使用者。 /// userNumber = 使用者的帳號。 /// 剔除成功與否。 public Boolean DeleteUser(String userNumber) { string str = String.Empty; return _UserPool.TryRemove(userNumber, out str); } /// 列出目前系統中在線上的使用者。 /// 使用者列表。 public List<string> ListAllUser() { return _UserPool.Keys.ToList<string>(); } /// 判斷使用者是否仍在線上。 /// userNumber = 欲查明的使用者。 /// 若在線上則為 true,反之則為 false。 public Boolean IsOnLine(String userNumber) { return _UserPool.Keys.Contains(userNumber); } /// 判斷使用者是否從同一個地方登入。 /// userNumber = 使用者帳號。 /// userIp = 使用者目前 IP 位址。 /// 若 userIp 與系統中使用者的 IP 位址一致表示從同一個地方登入。 public Boolean IsTheSameIP(String userNumber, String userIp) { String orignalIP = String.Empty; if (_UserPool.TryGetValue(userNumber, out orignalIP)) { if (orignalIP == userIp) return true; return false; } return false;//若沒能取得,表示使用者已經離線。 } /// 更新使用者的 IP 位址。 /// userNumber = 使用者帳號。 /// userIP = 使用者新的 IP 位址。 public void UpdateUserIP(String userNumber, String userIP) { if (!IsOnLine(userNumber)) return; _UserPool[userNumber] = userIP; } /// 把系統使用者儲蓄池清空。 public void ClearUserPool() { _UserPool.Clear(); } }
在Application_Start中就這樣寫:
void Application_Start(object sender, EventArgs e) { Application["UserPool"] = new SystemUserPool(); } void Application_End(object sender, EventArgs e) { var pool = Application["UserPool"] as SystemUserPool; if (pool != null) pool.ClearUserPool(); }
以上就是我這次所提出來的解決方案!不過其實最常加在這邊的應該是記錄系統狀態的Log啦~只是Log並不在這次範圍內,以後有機會再說囉~
參考文獻:
1) HttpSessionState
2) ASP.NET應用程式生命週期 IIS 5.0/IIS6.0 IIS7.0
3) ApplicationManager
4) HttpApplication
5) ASP.NET生命週期概觀 --> 強烈推薦寫 ASP.NET Web Form的人可以去看看「網頁生命週期的其他考量」裡面的事件圖
沒有留言:
張貼留言