自定义会话状态存储提供程序
自定義會(huì)話狀態(tài)存儲(chǔ)提供程序
?
?此版本程序只是說(shuō)明 ?自定義會(huì)話 ?可以放在不同的地方, 可以改造成 把會(huì)話分布式存儲(chǔ) 等。
?
一、Web.config?
<sessionState mode="Custom" customProvider="JinshuaiCustomSessionStateProvider">
? <providers>
? ? ? ?<add name="JinshuaiCustomSessionStateProvider" type="SessionStateWebApplication.Sessions.JinshuaiCustomSessionStateProvider" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
?
二、?JinshuaiCustomSessionStateProvider 提供程序
?
1 using System; 2 using System.Collections.Generic; 3 using System.Collections.Specialized; 4 using System.IO; 5 using System.Linq; 6 using System.Web; 7 using System.Web.SessionState; 8 9 namespace SessionStateWebApplication.Sessions 10 { 11 public class JinshuaiCustomSessionStateProvider : SessionStateStoreProviderBase 12 { 13 private static Dictionary<string, CustomSession> _dic = new Dictionary<string, CustomSession>(); 14 15 public string AppName 16 { 17 get { return "jinshuaiTest"; } 18 } 19 20 public int TimeOut { get; set; } 21 22 23 public override void Initialize(string name, NameValueCollection config) 24 { 25 TimeOut = 20; 26 27 base.Initialize(name, config); 28 } 29 30 31 public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout) 32 { 33 TimeOut = timeout; 34 return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout); 35 } 36 37 public override void CreateUninitializedItem(HttpContext context, string id, int timeout) 38 { 39 var newSession = new CustomSession 40 { 41 SessionId = id, 42 LockDate = DateTime.Now, 43 Locked = false, 44 LockId = 0, 45 SessionItems = string.Empty, 46 Timeout = timeout, 47 Expires = DateTime.Now.AddMinutes(timeout), 48 Created = DateTime.Now, 49 ApplicationName = AppName 50 }; 51 _dic.Add(id, newSession); 52 53 } 54 55 public override void Dispose() 56 { 57 58 } 59 60 public override void EndRequest(HttpContext context) 61 { 62 63 } 64 65 public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) 66 { 67 68 return GetItemByExclusive(false, context, id, out locked, out lockAge, out lockId, out actions); 69 } 70 71 public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) 72 { 73 return GetItemByExclusive(true, context, id, out locked, out lockAge, out lockId, out actions); 74 } 75 76 77 78 public SessionStateStoreData GetItemByExclusive(bool isExclusive, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) 79 { 80 locked = false; 81 lockAge = TimeSpan.Zero; 82 lockId = null; 83 actions = SessionStateActions.None; 84 85 CustomSession tempSession = null; 86 87 88 if (_dic.ContainsKey(id)) 89 { 90 tempSession = _dic[id]; 91 } 92 else 93 { 94 //沒(méi)找到相應(yīng)的會(huì)話 95 return null; 96 } 97 98 //如果過(guò)期 99 if (tempSession.Expires <= DateTime.Now) 100 { 101 _dic.Remove(id); 102 return null; 103 } 104 105 106 //是否獨(dú)占訪問(wèn) 107 if (isExclusive) 108 { 109 if (tempSession.Locked) 110 { 111 locked = true; 112 lockAge = (DateTime.Now - tempSession.LockDate); 113 lockId = tempSession.LockId; 114 actions = (SessionStateActions)tempSession.Flags; 115 return null; 116 } 117 } 118 119 return Deserialize(context, tempSession.SessionItems, tempSession.Timeout); 120 121 } 122 123 124 125 126 127 public override void InitializeRequest(HttpContext context) 128 { 129 130 } 131 132 public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) 133 { 134 if (!_dic.ContainsKey(id)) return; 135 136 var tempSession = _dic[id]; 137 tempSession.LockId = (int)(lockId??0); 138 tempSession.Locked = false; 139 tempSession.Expires = DateTime.Now.AddMinutes(tempSession.Timeout); 140 } 141 142 public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item) 143 { 144 145 if (!_dic.ContainsKey(id)) return; 146 147 _dic.Remove(id); 148 149 } 150 151 public override void ResetItemTimeout(HttpContext context, string id) 152 { 153 154 if (!_dic.ContainsKey(id)) return; 155 156 var tempSession = _dic[id]; 157 tempSession.Expires = DateTime.Now.AddMinutes(tempSession.Timeout); 158 159 } 160 161 public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) 162 { 163 164 string sessItems = Serialize((SessionStateItemCollection)item.Items); 165 166 if (newItem) 167 { 168 var newSession = new CustomSession 169 { 170 SessionId = id, 171 LockDate = DateTime.Now, 172 Locked = false, 173 LockId = 0, 174 SessionItems = sessItems, 175 Timeout = TimeOut, 176 Expires = DateTime.Now.AddMinutes(TimeOut), 177 Created = DateTime.Now, 178 ApplicationName = AppName 179 }; 180 _dic.Add(id, newSession); 181 182 } 183 else 184 { 185 186 if (!_dic.ContainsKey(id)) 187 { 188 var newSession = new CustomSession 189 { 190 SessionId = id, 191 LockDate = DateTime.Now, 192 Locked = false, 193 LockId = 0, 194 SessionItems = sessItems, 195 Timeout = TimeOut, 196 Expires = DateTime.Now.AddMinutes(TimeOut), 197 Created = DateTime.Now, 198 ApplicationName = AppName 199 }; 200 _dic.Add(id, newSession); 201 202 } 203 204 var tempSession = _dic[id]; 205 tempSession.Expires = DateTime.Now.AddMinutes(TimeOut); 206 tempSession.SessionItems = sessItems; 207 tempSession.LockId =(int)(lockId??0); 208 tempSession.LockDate = DateTime.Now; 209 210 } 211 212 213 } 214 215 public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) 216 { 217 218 return false; 219 } 220 221 222 223 224 225 226 227 private string Serialize(SessionStateItemCollection items) 228 { 229 MemoryStream ms = new MemoryStream(); 230 BinaryWriter writer = new BinaryWriter(ms); 231 232 if (items != null) 233 items.Serialize(writer); 234 235 writer.Close(); 236 237 return Convert.ToBase64String(ms.ToArray()); 238 } 239 240 private SessionStateStoreData Deserialize(HttpContext context, 241 string serializedItems, int timeout) 242 { 243 MemoryStream ms = 244 new MemoryStream(Convert.FromBase64String(serializedItems)); 245 246 SessionStateItemCollection sessionItems = 247 new SessionStateItemCollection(); 248 249 if (ms.Length > 0) 250 { 251 BinaryReader reader = new BinaryReader(ms); 252 sessionItems = SessionStateItemCollection.Deserialize(reader); 253 } 254 255 return new SessionStateStoreData(sessionItems, 256 SessionStateUtility.GetSessionStaticObjects(context), 257 timeout); 258 } 259 260 261 } 262 263 264 [Serializable] 265 public class CustomSession 266 { 267 268 public string SessionId 269 { 270 get; 271 set; 272 } 273 274 public string ApplicationName 275 { 276 get; 277 set; 278 } 279 public DateTime Created 280 { 281 get; 282 set; 283 } 284 public DateTime Expires 285 { 286 get; 287 set; 288 } 289 public DateTime LockDate 290 { 291 get; 292 set; 293 } 294 public int LockId 295 { 296 get; 297 set; 298 } 299 public int Timeout 300 { 301 get; 302 set; 303 } 304 public bool Locked 305 { 306 get; 307 set; 308 } 309 public string SessionItems 310 { 311 get; 312 set; 313 } 314 public int Flags 315 { 316 get; 317 set; 318 } 319 320 321 } 322 }?
?
三 、 使用??
protected void Button1_Click(object sender, EventArgs e)
{
? ?Session["jinshuai"] = "你好:" + DateTime.Now.ToString();
}
protected void Button2_Click(object sender, EventArgs e)
{
? ? this.Label1.Text = (Session["jinshuai"]?? "沒(méi)找到值").ToString();
}
?
附:
https://msdn.microsoft.com/zh-cn/library/system.web.sessionstate.sessionstatestoreproviderbase(VS.80).aspx
?
ASP.NET 會(huì)話狀態(tài)使用會(huì)話狀態(tài)存儲(chǔ)提供程序?qū)?huì)話數(shù)據(jù)寫(xiě)入數(shù)據(jù)存儲(chǔ)區(qū),并從中讀取會(huì)話數(shù)據(jù)。會(huì)話狀態(tài)存儲(chǔ)提供程序是一個(gè)類,它繼承SessionStateStoreProviderBase?抽象類并使用特定于數(shù)據(jù)存儲(chǔ)區(qū)的實(shí)現(xiàn)重寫(xiě)其成員。在處理 ASP.NET 頁(yè)的過(guò)程中,SessionStateModule?類會(huì)調(diào)用會(huì)話狀態(tài)存儲(chǔ)提供程序以便與數(shù)據(jù)存儲(chǔ)區(qū)進(jìn)行通信,從而存儲(chǔ)和檢索會(huì)話變量和相關(guān)的會(huì)話信息,如超時(shí)值。
對(duì)于每個(gè)?SessionID?屬性,每個(gè) ASP.NET 應(yīng)用程序內(nèi)的會(huì)話數(shù)據(jù)都將單獨(dú)存儲(chǔ)。ASP.NET 應(yīng)用程序不共享會(huì)話數(shù)據(jù)。
如本主題中的示例所示,可以為 ASP.NET 應(yīng)用程序指定一個(gè)自定義?SessionStateStoreProviderBase?實(shí)現(xiàn),方法是將?sessionState?配置元素的mode?屬性設(shè)置為?Custom,并將?customProvider?屬性設(shè)置為自定義提供程序的名稱。
鎖定會(huì)話存儲(chǔ)區(qū)數(shù)據(jù)
由于 ASP.NET 應(yīng)用程序是多線程的,支持對(duì)并發(fā)請(qǐng)求的響應(yīng),因此并發(fā)請(qǐng)求可能會(huì)嘗試訪問(wèn)同一會(huì)話信息。考慮下面一種情況,其中一個(gè)框架集中的多個(gè)框架都訪問(wèn)同一應(yīng)用程序。框架集內(nèi)每個(gè)框架的單獨(dú)請(qǐng)求可能會(huì)在 Web 服務(wù)器中的不同線程上并發(fā)執(zhí)行。如果每個(gè)框架源代碼的 ASP.NET 頁(yè)都訪問(wèn)會(huì)話狀態(tài)變量,則可能會(huì)出現(xiàn)多個(gè)線程并發(fā)訪問(wèn)會(huì)話存儲(chǔ)區(qū)。
為避免在會(huì)話存儲(chǔ)區(qū)發(fā)生數(shù)據(jù)沖突以及意外的會(huì)話狀態(tài)行為,SessionStateModule?和?SessionStateStoreProviderBase?類包含了鎖定功能,可以在 ASP.NET 頁(yè)執(zhí)行期間,以獨(dú)占方式為特定的會(huì)話鎖定會(huì)話存儲(chǔ)項(xiàng)。請(qǐng)注意,即使?EnableSessionState?屬性標(biāo)記為?ReadOnly,同一應(yīng)用程序中的其他 ASP.NET 頁(yè)也可以向會(huì)話存儲(chǔ)區(qū)寫(xiě)入,因此對(duì)于存儲(chǔ)區(qū)中只讀會(huì)話數(shù)據(jù)的請(qǐng)求可能最終仍將等待鎖定數(shù)據(jù)的釋放。
在調(diào)用?GetItemExclusive?方法的過(guò)程中,在請(qǐng)求開(kāi)始時(shí)就會(huì)對(duì)會(huì)話存儲(chǔ)區(qū)數(shù)據(jù)設(shè)置鎖定。請(qǐng)求完成后,在調(diào)用?SetAndReleaseItemExclusive?方法期間釋放鎖定。
如果?SessionStateModule?對(duì)象在調(diào)用?GetItemExclusive?或?GetItem?方法期間遇到鎖定的會(huì)話數(shù)據(jù),它將以半秒為間隔重新請(qǐng)求會(huì)話數(shù)據(jù),直到鎖定被釋放或者會(huì)話數(shù)據(jù)的鎖定時(shí)間超過(guò)?ExecutionTimeout?屬性的值。如果超過(guò)了執(zhí)行超時(shí)時(shí)間,SessionStateModule?對(duì)象將調(diào)用ReleaseItemExclusive?方法以釋放會(huì)話存儲(chǔ)區(qū)數(shù)據(jù)并隨即請(qǐng)求會(huì)話存儲(chǔ)區(qū)數(shù)據(jù)。
在針對(duì)當(dāng)前的響應(yīng)調(diào)用?SetAndReleaseItemExclusive?方法前,由于鎖定的會(huì)話存儲(chǔ)區(qū)數(shù)據(jù)可能已經(jīng)通過(guò)調(diào)用單獨(dú)線程上的ReleaseItemExclusive?方法而釋放,因此可能會(huì)嘗試設(shè)置和釋放已被另一會(huì)話釋放并修改的會(huì)話狀態(tài)存儲(chǔ)區(qū)數(shù)據(jù)。為了避免這種情況,GetItem?和GetItemExclusive?方法返回一個(gè)鎖定標(biāo)識(shí)符。此鎖定標(biāo)識(shí)符必須包含在每個(gè)請(qǐng)求中以修改鎖定的會(huì)話存儲(chǔ)區(qū)數(shù)據(jù)。僅當(dāng)數(shù)據(jù)存儲(chǔ)區(qū)中的鎖定標(biāo)識(shí)符與?SessionStateModule?提供的鎖定標(biāo)識(shí)符匹配時(shí),才能修改會(huì)話存儲(chǔ)區(qū)數(shù)據(jù)。
刪除過(guò)期的會(huì)話存儲(chǔ)區(qū)數(shù)據(jù)
當(dāng)針對(duì)特定的會(huì)話調(diào)用?Abandon?方法時(shí),將使用?RemoveItem?方法從數(shù)據(jù)存儲(chǔ)區(qū)中刪除該會(huì)話的數(shù)據(jù);否則,數(shù)據(jù)將保留在會(huì)話數(shù)據(jù)存儲(chǔ)區(qū)供會(huì)話的以后請(qǐng)求使用。由?SessionStateStoreProviderBase?實(shí)現(xiàn)來(lái)刪除過(guò)期的會(huì)話數(shù)據(jù)。
?
總結(jié)
以上是生活随笔為你收集整理的自定义会话状态存储提供程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SQL连表修改
- 下一篇: 转://Oracle 复合压缩索引场景及