自定义session Provider随笔[由多个请求阻塞排队处理发现]
using IDH.Common.BaseInfoCacheManagement;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using System.Web.SessionState;
namespace IdhWebApplication.Extensions.SessionProvider
{
/// <summary>
/// 使用Redis实现SessionStateStoreProviderBase
/// </summary>
public class RedisSessionStateStore : SessionStateStoreProviderBase
{
/// <summary>
/// 创建新的Session执行
/// </summary>
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
return CreateLegitStoreData(context, null, null, timeout);
}
internal static SessionStateStoreData CreateLegitStoreData(HttpContext context, ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
{
if (sessionItems == null)
sessionItems = new SessionStateItemCollection();
if (staticObjects == null && context != null)
staticObjects = SessionStateUtility.GetSessionStaticObjects(context);
return new SessionStateStoreData(sessionItems, staticObjects, timeout);
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
RedisSessionState state = new RedisSessionState(null, null, timeout);
BaseInfoCache.redisSessionCache.SetItem(id, state.ToJson(), timeout);
}
/// <summary>
/// 从redis获取session数据
/// </summary>
/// <param name="context"></param>
/// <param name="id"></param>
/// <param name="exclusive"></param>
/// <param name="locked"></param>
/// <param name="lockAge"></param>
/// <param name="lockId"></param>
/// <param name="actionFlags"></param>
/// <returns></returns>
private SessionStateStoreData DoGet(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
locked = false;
lockId = null;
lockAge = TimeSpan.Zero;
actionFlags = SessionStateActions.None;
RedisSessionState state = RedisSessionState.FromJson(BaseInfoCache.redisSessionCache.GetItem(id));
if (state == null)
{
return null;
}
BaseInfoCache.redisSessionCache.SetItem(id, state.ToJson(), state._timeout);
return CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout);
}
/// <summary>
/// 取值的时候执行
/// </summary>
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
return this.DoGet(context, id, false, out locked, out lockAge, out lockId, out actionFlags);
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
return this.DoGet(context, id, true, out locked, out lockAge, out lockId, out actionFlags);
}
/// <summary>
/// 新增 修改 移除键值时执行
/// </summary>
/// <param name="item">item.Items为当前所有的键值对</param>
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
ISessionStateItemCollection sessionItems = null;
HttpStaticObjectsCollection staticObjects = null;
if (item.Items.Count > 0)
sessionItems = item.Items;
if (!item.StaticObjects.NeverAccessed)
staticObjects = item.StaticObjects;
RedisSessionState state2 = new RedisSessionState(sessionItems, staticObjects, item.Timeout);
BaseInfoCache.redisSessionCache.SetItem(id, state2.ToJson(), item.Timeout);
}
#region "未实现方法"
public override void Dispose()
{
}
public override void EndRequest(HttpContext context)
{
}
public override void InitializeRequest(HttpContext context)
{
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
BaseInfoCache.redisSessionCache.RemoveItem(id);
}
public override void ResetItemTimeout(HttpContext context, string id)
{
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return true;
}
#endregion
}
/// <summary>
/// 存储在redis的对象
/// </summary>
public class SessionStateItem
{
/// <summary>
/// session数据
/// </summary>
public Dictionary<string,object> Dict { get; set; }
/// <summary>
/// 超时时间(分钟)
/// </summary>
public int Timeout { get; set; }
}
/// <summary>
/// 将session对象数据格式处理
/// </summary>
internal sealed class RedisSessionState
{
internal ISessionStateItemCollection _sessionItems;
internal HttpStaticObjectsCollection _staticObjects;
internal int _timeout;
internal RedisSessionState(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
{
this.Copy(sessionItems, staticObjects, timeout);
}
internal void Copy(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout)
{
this._sessionItems = sessionItems;
this._staticObjects = staticObjects;
this._timeout = timeout;
}
/// <summary>
/// 序列化
/// </summary>
/// <returns></returns>
public string ToJson()
{
if (_sessionItems == null || _sessionItems.Count == 0)
{
return null;
}
var dict = new Dictionary<string, object>();
string key;
NameObjectCollectionBase.KeysCollection keys = _sessionItems.Keys;
for (int i = 0; i < keys.Count; i++)
{
key = keys[i];
dict.Add(key, _sessionItems[key]);
}
var item = new SessionStateItem { Dict = dict, Timeout = this._timeout };
return JsonConvert.SerializeObject(item);
}
/// <summary>
/// 反序列化
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public static RedisSessionState FromJson(string json)
{
if (string.IsNullOrEmpty(json))
{
return null;
}
try
{
SessionStateItem item = JsonConvert.DeserializeObject<SessionStateItem>(json);
SessionStateItemCollection collections = new SessionStateItemCollection();
foreach (var kvp in item.Dict)
{
//转换指定类型,要不然从session获取的对象无法强转为指定类型
if(kvp.Key == "CurrentUserPermissions")
{
var permissionJson = JsonConvert.SerializeObject(kvp.Value);
collections[kvp.Key] = JsonConvert.DeserializeObject<Dictionary<Guid,int>>(permissionJson);
}
else if(kvp.Key == "CurrentUser")
{
var userJson = JsonConvert.SerializeObject(kvp.Value);
collections[kvp.Key] = JsonConvert.DeserializeObject<UserIdentity>(userJson);
}
else
{
collections[kvp.Key] = kvp.Value;
}
}
return new RedisSessionState(collections, null, item.Timeout);
}
catch
{
return null;
}
}
}
}
再配置文件system.web节点下添加代码
<sessionState mode="Custom" customProvider="RedisSessionStateStore"> <providers> <add name="RedisSessionStateStore" type="IdhWebApplication.Extensions.SessionProvider.RedisSessionStateStore"/> </providers> </sessionState>

浙公网安备 33010602011771号