在 Asp.net Mvc 自定义Session (一) 中我们把数据缓存工具类写好了,今天在我们在这篇把 剩下的自定义Session写完
首先还请大家跟着我的思路一步步的来实现,既然我们要自定义Session肯定要继承和重写什么东东(因为在框架设计中肯定考虑这些东西,asp.net mvc 架构师不傻的),好吧 确实要继承 SessionStateStoreProviderBase 这个基类。下面我先把代码贴出来,在慢慢解释
/// <summary> /// 分布式session /// </summary> public class ClusterSessionStoreProvider : SessionStateStoreProviderBase { private CacheManager _Client = CacheManager.Instance; private static readonly int _DefaultSessionExpireMinute = 20; private int _timeout; /// <summary> /// 构造函数 /// </summary> public ClusterSessionStoreProvider() { } /// <summary> /// 请求初始化的时候 /// </summary> /// <param name="context"></param> public override void InitializeRequest(HttpContext context) { } public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { // string applicationVirtualPath = AppDomain.CurrentDomain.BaseDirectory; if (string.IsNullOrWhiteSpace(config["timeout"])) { this._timeout = _DefaultSessionExpireMinute; } else { this._timeout = Convert.ToInt32(config["timeout"]); } } public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout) { return new SessionStateStoreData(new SessionStateItemCollection() , SessionStateUtility.GetSessionStaticObjects(context), timeout); } /// <summary> ///将新的会话状态添加到数据区中 /// </summary> /// <param name="context"></param> /// <param name="id"></param> /// <param name="timeout"></param> public override void CreateUninitializedItem(HttpContext context, string id, int timeout) { SessionDataObject sessionObject = new SessionDataObject { Content = null, Locked = false, SetTime = DateTime.Now, LockId = 0, ActionFlag = 1 }; _Client.Put(id, sessionObject, timeout); } public override void Dispose() { //调用dispose 需要的操作 } public override void EndRequest(HttpContext context) { //请求结束时调用 } public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { SessionStateStoreData sessionStateStoreDate = null; SessionDataObject memcachedSessionObject = null; DateTime setTime = DateTime.Now; lockAge = TimeSpan.Zero; lockId = null; locked = false; actions = SessionStateActions.None; memcachedSessionObject = _Client.Get(id) as SessionDataObject; if (memcachedSessionObject != null) { //如果已经锁定 if (memcachedSessionObject.Locked) { lockAge = memcachedSessionObject.LockAge; lockId = memcachedSessionObject.LockId; locked = memcachedSessionObject.Locked; actions = (SessionStateActions)memcachedSessionObject.ActionFlag; return sessionStateStoreDate; } memcachedSessionObject.LockId++; memcachedSessionObject.SetTime = setTime; _Client.Put(id, memcachedSessionObject); actions = (SessionStateActions)memcachedSessionObject.ActionFlag; lockId = memcachedSessionObject.LockId; lockAge = memcachedSessionObject.LockAge; if (actions == SessionStateActions.InitializeItem) { sessionStateStoreDate = this.CreateNewStoreData(context, _timeout); } else { sessionStateStoreDate = this.Deserialize(context, memcachedSessionObject.Content, _timeout); } return sessionStateStoreDate; } return sessionStateStoreDate; } //从缓冲区中读取只读属性 public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { return GetItem(context, id, out locked, out lockAge, out lockId, out actions); } //释放锁定 public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) { SessionDataObject memcachedSessionObject = _Client.Get(id) as SessionDataObject; if (memcachedSessionObject != null) { memcachedSessionObject.Locked = false; memcachedSessionObject.LockId = (Int32)lockId; _Client.Put(id, memcachedSessionObject, _timeout); } } //删除缓存数据 public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item) { _Client.Delete(id); } public override void ResetItemTimeout(HttpContext context, string id) { object obj = _Client.Get(id); if (obj != null) { _Client.Put(id, obj, _timeout); } } //更新值 public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { DateTime setTime = DateTime.Now; byte[] bytes = this.Serialize((SessionStateItemCollection)item.Items); SessionDataObject memcachedSessionObject = new SessionDataObject() { LockId = 0, Locked = false, Content = bytes, ActionFlag = 0, SetTime = setTime }; _Client.Put(id, memcachedSessionObject, item.Timeout); } public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) { return false; } private SessionStateStoreData Deserialize(HttpContext context, byte[] bytes, int timeout) { MemoryStream stream = new MemoryStream(bytes); SessionStateItemCollection collection = new SessionStateItemCollection(); if (stream.Length > 0) { BinaryReader reader = new BinaryReader(stream); collection = SessionStateItemCollection.Deserialize(reader); } return new SessionStateStoreData(collection, SessionStateUtility.GetSessionStaticObjects(context), timeout); } private byte[] Serialize(SessionStateItemCollection items) { MemoryStream ms = new MemoryStream(); BinaryWriter writer = new BinaryWriter(ms); if (items != null) items.Serialize(writer); writer.Close(); return ms.ToArray(); } }
- 在代码中有一个SessionDataObject类,这个类是存储Session的一些基本信息,以保证访问时还能取得上次设置的值(这个类一定要序列还 不然嘻嘻。。)
这个类的代码如下:
[Serializable] public class SessionDataObject { public byte[] Content { get; set; } public bool Locked { get; set; } public DateTime SetTime { get; set; } public int LockId { get; set; } public int ActionFlag { get; set; } public TimeSpan LockAge { get; set; } }
2. 增删改查都要重写,如 GetItemExclusive 重写这个方法时,每次获取session(如:session['test'])都会调用这个方法,你根据sessionId往 缓存工具类中读取返回就行
3. 重写完了指定方法后,要在配置文件中加上,才能使用
/************************************************ * * <sessionState mode="Custom" customProvider="SessionProvider" > <providers> <add name="SessionProvider" type="NanHuaDDD.ClusterSession.ClusterSessionStoreProvider,NanHuaDDD" timeout="1" accessKey="你好" /> </providers> * * ******************************************************************/
到这里 我就不一 一列出每个方法的意思了,差不多大家一看方法名就知道,分布式用的是memcache,如果在后面系统升级,要求集群是不是很方便啊
如果有什么疑问可以联系我 QQ:209229923