大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > ASP.NET技巧 > 可灵活扩展的自定义Session状态存储驱动

可灵活扩展的自定义Session状态存储驱动(2)

关键词:灵活扩展自定义Session状态存储驱动  阅读(968) 赞(18)

[摘要]本文是对可灵活扩展的自定义Session状态存储驱动的讲解,对学习ASP.NET编程技术有所帮助,与大家分享。

创建一个ISessionStateStoreBehavior,将涉及Session存储的方法公开。

/// <summary>
    /// Session驱动行为工厂
    /// </summary>
    class SessionProviderBehaviorFactory
    {
        /// <summary>
        /// 当前Session状态存储行为实例
        /// </summary>
        static ISessionStateStoreBehavior currentSessionStateStoreBehavior;

        /// <summary>
        /// 创建Session状态存储行为实例
        /// </summary>
        /// <returns></returns>
        public static ISessionStateStoreBehavior CreateSessionStateStoreBehaviorInstance()
        {
            if (currentSessionStateStoreBehavior == null)
            {
                var types = Assembly.GetExecutingAssembly().GetTypes().Where(t => !t.IsAbstract && t.GetInterface(typeof(ISessionStateStoreBehavior).Name) != null);
                var currentType = types.FirstOrDefault(t => t.Name == string.Format("{0}SessionStateStoreBehavior", SessionProviderConfigurationSectionHandler.SessionProviderSettings.SessionStateStoreProviderBehaviorName));
                if (currentType != null)
                {
                    currentSessionStateStoreBehavior = (ISessionStateStoreBehavior)Activator.CreateInstance(currentType);
                }
            }

            return currentSessionStateStoreBehavior;
        }
    }

通过工厂得到当前应用程序域下的继承了ISessionStateStoreBehavior接口的所有实现类,并读取配置得到当前实例。

基于MongoDB的一个行为实现

/// <summary>
    /// 基于Mongo的Session状态存储行为
    /// </summary>
    public class MongoSessionStateStoreBehavior : SessionStateStoreBehaviorBase, ISessionStateStoreBehavior
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public MongoSessionStateStoreBehavior()
            : base()
        {
            if (collection == null)
            {
                collection = GetMongoDBCollection();
                var expiresKey = IndexKeys.Ascending("Expires");
                var options = IndexOptions.SetTimeToLive(base.SessionStateSection.Timeout);
                collection.EnsureIndex(expiresKey, options);
                collection.EnsureIndex("LockId", "Locked");
            }
        }

        static MongoCollection<MongoDBSessionDo> collection;

        /// <summary>
        /// 获取Mongo集合
        /// </summary>
        /// <returns></returns>
        static MongoCollection<MongoDBSessionDo> GetMongoDBCollection()
        {
            var url = new MongoUrl(SessionProviderConfigurationSectionHandler.SessionProviderSettings.StorageConnectionString);
            var client = new MongoClient(url);
            var database = client.GetServer().GetDatabase(url.DatabaseName, WriteConcern.Unacknowledged);
            return database.GetCollection<MongoDBSessionDo>(ConfigSection.SessionProviderConfigurationSectionHandler.SessionProviderSettings.SessionProfix);
        }

        /// <summary>
        /// 创建未初始化项
        /// </summary>
        /// <param name="context"></param>
        /// <param name="id"></param>
        /// <param name="timeout"></param>
        public void CreateUninitializedItem(System.Web.HttpContext context, string id, int timeout)
        {
            var session = new MongoDBSessionDo()
            {
                SessionId = id,
                Created = DateTime.Now,
                Expires = DateTime.Now.AddMinutes(base.SessionStateSection.Timeout.TotalMinutes),
                LockDate = DateTime.Now,
                LockId = 0,
                Timeout = timeout,
                Locked = false,
                Flags = (int)SessionStateActions.InitializeItem,
            };
            collection.Save(session);
            SetSessionIdCookieExpires(context, session.Expires);
        }

        /// <summary>
        /// 获取项
        /// </summary>
        /// <param name="lockRecord"></param>
        /// <param name="context"></param>
        /// <param name="id"></param>
        /// <param name="locked"></param>
        /// <param name="lockAge"></param>
        /// <param name="lockId"></param>
        /// <param name="actions"></param>
        /// <returns></returns>
        public System.Web.SessionState.SessionStateStoreData GetItem(bool lockRecord, System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out System.Web.SessionState.SessionStateActions actions)
        {
            var item = default(SessionStateStoreData);
            lockAge = TimeSpan.Zero;
            lockId = null;
            locked = false;
            actions = 0;

            bool foundRecord = false;
            bool deleteData = false;

            var session = collection.AsQueryable().FirstOrDefault(s => s.SessionId == id);

            if (lockRecord)
            {
                locked = session != null && !session.Locked && session.Expires > DateTime.Now;
            }

            if (session != null)
            {
                if (session.Expires < DateTime.Now)
                {
                    locked = false;
                    deleteData = true;
                }
                else
                {
                    foundRecord = true;
                }
            }

            if (deleteData)
            {
                collection.Remove(Query.EQ("_id", id));
            }

            if (!foundRecord)
                locked = false;

            if (foundRecord && !locked)
            {
                lockId = lockId == null ? 0 : (int)lockId + 1;
                collection.Update(Query.EQ("_id", id), Update.Set("LockId", (int)lockId).Set("Flags", (int)SessionStateActions.None));
                var timeout = actions == SessionStateActions.InitializeItem ? (int)base.SessionStateSection.Timeout.TotalMinutes : session.Timeout;
                var sessionStateItemCollection = actions == SessionStateActions.InitializeItem ? new SessionStateItemCollection() : Helper.Deserialize(session.SessionItems);
                item = new SessionStateStoreData(sessionStateItemCollection, SessionStateUtility.GetSessionStaticObjects(context), timeout);
            }

            return item;
        }

        /// <summary>
        /// 释放项
        /// </summary>
        /// <param name="context"></param>
        /// <param name="id"></param>
        /// <param name="lockId"></param>
        public void ReleaseItem(System.Web.HttpContext context, string id, object lockId)
        {
            var expires = DateTime.Now.AddMinutes(base.SessionStateSection.Timeout.TotalMinutes);
            collection.Update(Query.And(Query.EQ("LockId", int.Parse(lockId.ToString())), Query.EQ("_id", id)), Update.Set("Locked", false).Set("Expires", expires));
            SetSessionIdCookieExpires(context, expires);
        }

        /// <summary>
        /// 移除项
        /// </summary>
        /// <param name="context"></param>
        /// <param name="id"></param>
        /// <param name="lockId"></param>
        public void RemoveItem(System.Web.HttpContext context, string id, object lockId)
        {
            collection.Remove(Query.And(Query.EQ("LockId", int.Parse(lockId.ToString())), Query.EQ("_id", id)));
            SetSessionIdCookieExpires(context, DateTime.Now.AddDays(-1), true);
        }

        /// <summary>
        /// 重设项超时时间
        /// </summary>
        /// <param name="context"></param>
        /// <param name="id"></param>
        public void ResetItemTimeout(System.Web.HttpContext context, string id)
        {
            var expires = DateTime.Now.AddMinutes(base.SessionStateSection.Timeout.TotalMinutes);
            collection.Update(Query.And(Query.EQ("_id", id)), Update.Set("Expires", expires));
            SetSessionIdCookieExpires(context, expires);
        }

        /// <summary>
        /// 设置并释放项
        /// </summary>
        /// <param name="context"></param>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="lockId"></param>
        /// <param name="newItem"></param>
        public void SetAndReleaseItem(System.Web.HttpContext context, string id, System.Web.SessionState.SessionStateStoreData item, object lockId, bool newItem)
        {
            var session = default(MongoDBSessionDo);
            if (newItem)
            {
                session = new MongoDBSessionDo();
                session.SessionId = id;
                session.Created = DateTime.Now;
                session.Expires = DateTime.Now.AddMinutes(base.SessionStateSection.Timeout.TotalMinutes);
                session.LockDate = DateTime.Now;
                session.LockId = 0;
                session.Timeout = item.Timeout;
                session.Locked = false;
                session.Flags = (int)SessionStateActions.None;
                session.SessionItems = Helper.Serialize((SessionStateItemCollection)item.Items);
            }
            else
            {
                session = collection.FindOne(Query.And(Query.EQ("_id", id), Query.EQ("LockId", int.Parse(lockId.ToString()))));
                session.Expires = DateTime.Now.AddMinutes(item.Timeout);
                session.SessionItems = Helper.Serialize((SessionStateItemCollection)item.Items);
                session.Locked = false;
            }
            collection.Save(session);
            SetSessionIdCookieExpires(context, session.Expires);
        }
    }

配置相关

<configSections>
    <section name="SessionProviderSettings" type="CustomSessionDemo.SessionProviderConfigurationSectionHandler, CustomSessionDemo"/>
  </configSections>
  
  <SessionProviderSettings>
    <SessionProfix>Test</SessionProfix>
    <IsSynchronousSessionIdTimeout>true</IsSynchronousSessionIdTimeout>
    <SessionStateStoreProviderBehaviorName>Mongo</SessionStateStoreProviderBehaviorName>
    <StorageConnectionString>mongodb://192.168.1.43:27017/TestSessionDB</StorageConnectionString>
  </SessionProviderSettings>

  <system.web>
    <sessionState mode="Custom" customProvider="SessionProvider" sessionIDManagerType="CustomSessionDemo.CustomSessionIDManager" timeout="20">
      <providers>
        <add name="SessionProvider" type="CustomSessionDemo.CustomSessionStateStoreProvider, CustomSessionDemo"/>
      </providers>
    </sessionState>

执行效果

image

image

«上一页12下一页»


相关评论