您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關微信公眾平臺開發之如何解決用戶上下文Session的問題的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
概述
由于微信公眾平臺的特殊機制,所有的信息都由微信服務器轉發而來,因此服務器是無法使用Session對用戶會話的上下文進行管理的。
為此Senparc.WeiXin.MP SDK增加了上下文的模塊,并集成到了MessageHandler中。
WeixinContext
WeixinContext是所有單個用戶上下文(MessageContext)實體的容器(暫且稱為全局上下文)。WeixinContext本身不是靜態類,意味著您可以在同一個應用中創建多個上下文實體。
同時,一個靜態的WeixinContext實例被放入到MessageHandler<TM>中,因此所有項目中由MessageHandler<TM>派生的子類中的WeixinContext是唯一的、全局的(注:TM為實現IMessageContext的類,包括SDK中已經提供的MessageContext)。
因此我們在任何一個實現了MessageHandler<TM>的實例中(比如叫MyMessageHandler),都可以訪問到一個類型和名稱都叫WeixinContext的對象。
WeixinContext用于保存所用戶的上下文(MessageContext),并且提供了一系列的方法,主要方法包括:
/// <summary> /// 重置所有上下文參數,所有記錄將被清空 /// </summary> public void Restore() { ... } /// <summary> /// 獲取MessageContext,如果不存在,返回null /// 這個方法的更重要意義在于操作TM隊列,及時移除過期信息,并將最新活動的對象移到尾部 /// </summary> /// <param name="userName">用戶名(OpenId)</param> /// <returns></returns> private TM GetMessageContext(string userName) { ... } /// <summary> /// 獲取MessageContext /// </summary> /// <param name="userName">用戶名(OpenId)</param> /// <param name="createIfNotExists">True:如果用戶不存在,則創建一個實例,并返回這個最新的實例 /// False:用戶儲存在,則返回null</param> /// <returns></returns> private TM GetMessageContext(string userName, bool createIfNotExists) { ... } /// <summary> /// 獲取MessageContext,如果不存在,使用requestMessage信息初始化一個,并返回原始實例 /// </summary> /// <returns></returns> public TM GetMessageContext(IRequestMessageBase requestMessage) { ... } /// <summary> /// 獲取MessageContext,如果不存在,使用requestMessage信息初始化一個,并返回原始實例 /// </summary> /// <returns></returns> public TM GetMessageContext(IResponseMessageBase responseMessage) { ... } /// <summary> /// 記錄請求信息 /// </summary> /// <param name="requestMessage">請求信息</param> public void InsertMessage(IRequestMessageBase requestMessage) { ... } /// <summary> /// 記錄響應信息 /// </summary> /// <param name="responseMessage">響應信息</param> public void InsertMessage(IResponseMessageBase responseMessage) { ... } /// <summary> /// 獲取最新一條請求數據,如果不存在,則返回Null /// </summary> /// <param name="userName">用戶名(OpenId)</param> /// <returns></returns> public IRequestMessageBase GetLastRequestMessage(string userName) { ... } /// <summary> /// 獲取最新一條響應數據,如果不存在,則返回Null /// </summary> /// <param name="userName">用戶名(OpenId)</param> /// <returns></returns> public IResponseMessageBase GetLastResponseMessage(string userName) { ... }
WeixinContext中有兩個用于儲存用戶上下文的對象:MessageCollection及MessageQueue。
這兩個對象中的元素集合是重合的,但是MessageQueue對元素進行了排序,以便及時處理掉頂部過期的上下文。
ExpireMinutes用于定義上下文時間有效期,默認為90分鐘。可以在程序的任何地方設置設個參數,且立即生效。
PS:MessageQueue中刪除過期數據的邏輯以極高的效率運作,常規開發時無需考慮CPU占用及對象沖突的問題(額外校驗時間是否超時)。
MessageContext
MessageContext用于保存單個用戶的上下文信息,被儲存在WeixinContext的MessageCollection及MessageQueue對象中。 IMessageContext定義如下:
/// <summary> /// 微信消息上下文(單個用戶)接口 /// </summary> /// <typeparam name="TRequest">請求消息類型</typeparam> /// <typeparam name="TResponse">響應消息類型</typeparam> public interface IMessageContext<TRequest,TResponse> where TRequest : IRequestMessageBase where TResponse : IResponseMessageBase { /// <summary> /// 用戶名(OpenID) /// </summary> string UserName { get; set; } /// <summary> /// 最后一次活動時間(用戶主動發送Resquest請求的時間) /// </summary> DateTime LastActiveTime { get; set; } /// <summary> /// 接收消息記錄 /// </summary> MessageContainer<TRequest> RequestMessages { get; set; } /// <summary> /// 響應消息記錄 /// </summary> MessageContainer<TResponse> ResponseMessages { get; set; } /// <summary> /// 最大儲存容量(分別針對RequestMessages和ResponseMessages) /// </summary> int MaxRecordCount { get; set; } /// <summary> /// 臨時儲存數據,如用戶狀態等,出于保持.net 3.5版本,這里暫不使用dynamic /// </summary> object StorageData { get; set; } /// <summary> /// 用于覆蓋WeixinContext所設置的默認過期時間 /// </summary> Double? ExpireMinutes { get; set; } /// <summary> /// AppStore狀態,系統屬性,請勿操作 /// </summary> AppStoreState AppStoreState { get; set; } event EventHandler<WeixinContextRemovedEventArgs<TRequest, TResponse>> MessageContextRemoved; void OnRemoved(); }
您可以根據自己的需要創建自己的類,實現這個接口,并且被WeixinContext使用。當然如果你的要求不是那么特殊,而且你比較懶的話,SDK提供了一個默認的MessageContext實現:
/// <summary> /// 微信消息上下文(單個用戶) /// </summary> public class MessageContext<TRequest,TResponse>: IMessageContext<TRequest, TResponse> where TRequest : IRequestMessageBase where TResponse : IResponseMessageBase { private int _maxRecordCount; public string UserName { get; set; } public DateTime LastActiveTime { get; set; } public MessageContainer<TRequest> RequestMessages { get; set; } public MessageContainer<TResponse> ResponseMessages { get; set; } public int MaxRecordCount { get { return _maxRecordCount; } set { RequestMessages.MaxRecordCount = value; ResponseMessages.MaxRecordCount = value; _maxRecordCount = value; } } public object StorageData { get; set; } public Double? ExpireMinutes { get; set; } /// <summary> /// AppStore狀態,系統屬性,請勿操作 /// </summary> public AppStoreState AppStoreState { get; set; } public virtual event EventHandler<WeixinContextRemovedEventArgs<TRequest, TResponse>> MessageContextRemoved = null; /// <summary> /// 執行上下文被移除的事件 /// 注意:此事件不是實時觸發的,而是等過期后任意一個人發過來的下一條消息執行之前觸發。 /// </summary> /// <param name="e"></param> private void OnMessageContextRemoved(WeixinContextRemovedEventArgs<TRequest, TResponse> e) { EventHandler<WeixinContextRemovedEventArgs<TRequest, TResponse>> temp = MessageContextRemoved; if (temp != null) { temp(this, e); } } /// <summary> /// /// </summary> /// <param name="maxRecordCount">maxRecordCount如果小于等于0,則不限制</param> public MessageContext(/*MessageContainer<IRequestMessageBase> requestMessageContainer, MessageContainer<IResponseMessageBase> responseMessageContainer*/) { /* * 注意:即使使用其他類實現IMessageContext, * 也務必在這里進行下面的初始化,尤其是設置當前時間, * 這個時間關系到及時從緩存中移除過期的消息,節約內存使用 */ RequestMessages = new MessageContainer<TRequest>(MaxRecordCount); ResponseMessages = new MessageContainer<TResponse>(MaxRecordCount); LastActiveTime = DateTime.Now; } public virtual void OnRemoved() { var onRemovedArg = new WeixinContextRemovedEventArgs<TRequest, TResponse>(this); OnMessageContextRemoved(onRemovedArg); } }
上面的代碼根據注釋很好理解,需要說明一下的是StorageData。這是一個用于儲存任何和用戶上下文有關數據的容器,WeixinContext和IMessageContext沒有對它進行任何引用,完全由開發者決定里面的內容(比如用戶執行到哪一步、或某個比較重要的位置信息等等),類似于Session的作用。
上述MessageContext<TRequest,TResponse>類已經提供了比較完備的常用的消息處理的方法,可以直接使用。如果有更加特殊的需求,需要自定義MessageContext,推薦以這個類為基類進行必要的重寫,例如下面就是一個自定義的上下文類:
public class CustomMessageContext : MessageContext<IRequestMessageBase,IResponseMessageBase> { public CustomMessageContext() { base.MessageContextRemoved += CustomMessageContext_MessageContextRemoved; } /// <summary> /// 當上下文過期,被移除時觸發的時間 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void CustomMessageContext_MessageContextRemoved(object sender, Senparc.Weixin.Context.WeixinContextRemovedEventArgs<IRequestMessageBase,IResponseMessageBase> e) { /* 注意,這個事件不是實時觸發的(當然你也可以專門寫一個線程監控) * 為了提高效率,根據WeixinContext中的算法,這里的過期消息會在過期后下一條請求執行之前被清除 */ var messageContext = e.MessageContext as CustomMessageContext; if (messageContext == null) { return;//如果是正常的調用,messageContext不會為null } //TODO:這里根據需要執行消息過期時候的邏輯,下面的代碼僅供參考 //Log.InfoFormat("{0}的消息上下文已過期",e.OpenId); } }
上面的CustomMessageContext_MessageContextRemoved()方法會在某個用戶的上下文被清除的時候觸發,其中可以加入自己需要的代碼。除此以外,您也可以重寫積累中的OnRemoved()等方法,或者添加其他的屬性及方法。
感謝各位的閱讀!關于“微信公眾平臺開發之如何解決用戶上下文Session的問題”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。