WeChat パブリック プラットフォームの開発: ユーザー コンテキスト (セッション) の問題の解決

高洛峰
リリース: 2017-02-27 13:08:18
オリジナル
3018 人が閲覧しました

概要

WeChatパブリックプラットフォームの特別なメカニズムにより、すべての情報はWeChatサーバーによって転送されるため、サーバーはセッションを使用してユーザーセッションのコンテキストを管理できません。

この目的のために、Senparc.WeiXin.MP SDK はコンテキスト モジュールを追加し、それを MessageHandler に統合します。

WeixinContext

WeixinContext は、すべての単一ユーザー コンテキスト (MessageContext) エンティティ (暫定的にグローバル コンテキストと呼ばれます) のコンテナーです。 WeixinContext 自体は静的クラスではないため、同じアプリケーション内に複数のコンテキスト エンティティを作成できます。

同時に、静的な WeixinContext インスタンスが MessageHandler に配置されるため、すべてのプロジェクトの MessageHandler から派生したすべてのサブクラスの WeixinContext は一意でグローバルになります (注: TM は、 IMessageContext を実装するクラスです。 SDK ですでに提供されている MessageContext)。

したがって、MessageHandler を実装するインスタンス (MyMessageHandler など) では、WeixinContext というタイプと名前のオブジェクトにアクセスできます。

WeixinContext はユーザーのコンテキスト (MessageContext) を保存するために使用され、一連のメソッドを提供します:


// /


/// MessageContext を取得します。存在しない場合は、null を返します
/// このメソッドのより重要な意味は、TM キューを操作し、期限切れの情報を削除することです。 、最新のアクティブなオブジェクトを最後に移動します
/ // & lt;/summary & gt; //// & lt; param name = "username" & gt; gt; //< null</param>
///< summary>リクエスト メッセージ メッセージを使用します ‐ use using requestMessage ' to use MessageContext ' ‐ MessageContext(IRequestMessageBase requestMessage) を取得します
t;
// /
パブリック TM GetMessageContext(IResponseMessageBase 応答メッセージ)
{
/// 記録リクエスト情報
///
gt ;
;summary>
// / 回答情報を記録します, ...
} T /// & lt;
///最新のリクエストデータを取得します
/// & lt;/summary & gt; /// & lt; Param name = "username" & gt;パラメータ>
/// <まとめ>
/// /最新の応答データを取得します。存在しない場合は Null を返します
///
/// ユーザー名 (OpenId)
/// /
Public IResponseMessageBase GetLastResponseMessage(string userName)

WeixinContext には、ユーザー コンテキストを保存するために使用される 2 つのオブジェクト、MessageCollection と MessageQueue があります。

これら 2 つのオブジェクトの要素のセットは重複していますが、MessageQueue は要素を並べ替えて、先頭の期限切れのコンテキストを時間内に処理できるようにします。

ExpireMinutes はコンテキスト時間の有効期間を定義するために使用され、デフォルトは 90 分です。プログラム内のどこにでもパラメータを設定でき、それはすぐに有効になります。

追記: 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 には、そのコンテンツへの参照がありません (ユーザーが実行したステップや重要な内容など)。位置情報など)、セッションの役割と同様です。

上記の MessageContext クラスは、比較的完全な一般的なメッセージ処理メソッドを提供しており、直接使用できます。さらに特別なニーズがあり、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() などのメソッドをオーバーライドしたり、他の属性やメソッドを追加したりすることもできます。

WeChat パブリック プラットフォームの開発: ユーザー コンテキスト (セッション) の問題の解決に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!