Heim  >  Artikel  >  WeChat-Applet  >  Entwicklung der öffentlichen WeChat-Plattform: Lösung von Benutzerkontextproblemen (Sitzungsproblemen).

Entwicklung der öffentlichen WeChat-Plattform: Lösung von Benutzerkontextproblemen (Sitzungsproblemen).

高洛峰
高洛峰Original
2017-02-27 13:08:183019Durchsuche

Übersicht

Aufgrund des speziellen Mechanismus der öffentlichen WeChat-Plattform werden alle Informationen vom WeChat-Server weitergeleitet, sodass der Server die Sitzung nicht zum Verwalten des Kontexts der Benutzersitzung verwenden kann.

Zu diesem Zweck fügt das Senparc.WeiXin.MP SDK ein Kontextmodul hinzu und integriert es in den MessageHandler.

WeixinContext

WeixinContext ist ein Container für alle einzelnen Benutzerkontext-Entitäten (MessageContext) (vorläufig als globaler Kontext bezeichnet). WeixinContext selbst ist keine statische Klasse, was bedeutet, dass Sie mehrere Kontextentitäten in derselben Anwendung erstellen können.

Gleichzeitig wird eine statische WeixinContext-Instanz in MessageHandler68b68cd4f5c098c0c63d969fd4792098 eingefügt, sodass der WeixinContext in allen von MessageHandler68b68cd4f5c098c0c63d969fd4792098 abgeleiteten Unterklassen in allen Projekten eindeutig und global ist (Hinweis: TM sind Klassen, die implementieren IMessageContext, einschließlich MessageContext, der bereits im SDK bereitgestellt wird.

In jeder Instanz, die MessageHandler68b68cd4f5c098c0c63d969fd4792098 implementiert (z. B. MyMessageHandler), können wir auf ein Objekt zugreifen, dessen Typ und Name WeixinContext sind.

WeixinContext wird zum Speichern des Benutzerkontexts (MessageContext) verwendet und bietet eine Reihe von Methoden. Zu den Hauptmethoden gehören:

/// 631fb227578dfffda61e1fa4d04b7d25
/// Alle Kontextparameter zurücksetzen, alle Datensätze werden gelöscht
/// 039f3e95db2a684c7b74365531eb6044
public void Restore()
{
...
}

/// 631fb227578dfffda61e1fa4d04b7d25
/// Holen Sie sich den MessageContext. Wenn er nicht existiert, geben Sie null zurück
/// Die wichtigere Bedeutung dieser Methode Es dient dazu, die TM-Warteschlange zu betreiben, abgelaufene Informationen rechtzeitig zu entfernen und die neuesten aktiven Objekte an das Ende zu verschieben
/// 039f3e95db2a684c7b74365531eb6044
/// 3cd8c8873cd7fc29b8a558f7d5d8e013Benutzername (OpenId)8bb7487ae6a16a43571bc14c7fcf93c2
                                                                                                        >
/// 631fb227578dfffda61e1fa4d04b7d25
/// Get MessageContext
/// 039f3e95db2a684c7b74365531eb6044
; /param>
/// e63a580229b63ffa691b29f71803cad5True: Wenn der Benutzer nicht existiert, erstellen Sie eine Instanz und geben Sie die neueste Instanz zurück
/// False: Der Benutzer ist gespeichert in, Gibt null zurück8bb7487ae6a16a43571bc14c7fcf93c2
/// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
private TM GetMessageContext(string userName, bool createIfNotExists)
{
...
}


/// 631fb227578dfffda61e1fa4d04b7d25
/// Holen Sie sich den MessageContext. Wenn er nicht existiert, initialisieren Sie einen mit requestMessage-Informationen und geben Sie die ursprüngliche Instanz zurück
/// /// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3
public TM GetMessageContext(IRequestMessageBase requestMessage)
/// /// Den MessageContext abrufen, falls nicht vorhanden, initialisieren Sie eine mit requestMessage-Informationen und geben Sie die ursprüngliche Instanz zurück
/// 039f3e95db2a684c7b74365531eb6044
/// 2363942ed0d6cd3e85bae1dffa568116f7735d9f6a7af371769ab5c16d23b2f3 public TM GetMessageContext(IResponseMessageBase ResponseMessage)
                                                                                       Zusammenfassung>
/// c6f4d0252dbec5209f41377807ad0b73Antwortnachricht8bb7487ae6a16a43571bc14c7fcf93c2
public void InsertMessage(IResponseMessageBase ResponseMessage)
...
}

/// 631fb227578dfffda61e1fa4d04b7d25
/// Holen Sie sich die neuesten Anforderungsdaten. Wenn sie nicht vorhanden sind, geben Sie Null zurück
/// 039f3e95db2a684c7b74365531eb6044
/// eb7df87d0d2b61b9b9cf1f29a33fc08bBenutzername (OpenId)ea958c64f9fd88e22a02074fe798a5bc
                                                                                                                              🎜> // / 631fb227578dfffda61e1fa4d04b7d25
/// Holen Sie sich die neuesten Antwortdaten. Wenn sie nicht vorhanden sind, geben Sie Null zurück
// / 039f3e95db2a684c7b74365531eb6044
///                                                                                      , ,                              ;

WeixinContext verfügt über zwei Objekte, die zum Speichern des Benutzerkontexts verwendet werden: MessageCollection und MessageQueue.

Die Menge der Elemente in diesen beiden Objekten überschneidet sich, aber die MessageQueue sortiert die Elemente so, dass der oberste abgelaufene Kontext rechtzeitig verarbeitet wird.

ExpireMinutes wird verwendet, um den Gültigkeitszeitraum der Kontextzeit zu definieren. Der Standardwert beträgt 90 Minuten. Sie können einen Parameter an einer beliebigen Stelle im Programm festlegen und er wird sofort wirksam.

PS: Die Logik zum Löschen abgelaufener Daten in MessageQueue arbeitet mit extrem hoher Effizienz. Es besteht keine Notwendigkeit, die Probleme der CPU-Auslastung und Objektkonflikte (ob die zusätzliche Überprüfungszeit abläuft) während der regulären Entwicklung zu berücksichtigen.

MessageContext

MessageContext wird zum Speichern der Kontextinformationen eines einzelnen Benutzers verwendet und in den MessageCollection- und MessageQueue-Objekten von WeixinContext gespeichert. IMessageContext ist wie folgt definiert:

/// <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();
}

Sie können Ihre eigene Klasse entsprechend Ihren Anforderungen erstellen, diese Schnittstelle implementieren und von WeixinContext verwendet werden. Wenn Ihre Anforderungen nicht so speziell sind und Sie faul sind, bietet das SDK natürlich eine Standardimplementierung von 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);
    }
}

Der obige Code ist anhand der Kommentare leicht zu verstehen Speicherdaten. Dies ist ein Container, der zum Speichern aller Daten verwendet wird, die sich auf den Benutzerkontext beziehen, und IMessageContext hat keinen Verweis darauf. Es liegt ganz beim Entwickler, den Inhalt zu bestimmen (z. B. welchen Schritt der Benutzer ausgeführt hat oder welche wichtigen Informationen er enthält). Standortinformationen usw. usw.), ähnlich der Rolle der Sitzung.

Die obige MessageContext25193dfd7deff13abfdc5aafbe503ab2-Klasse bietet relativ vollständige allgemeine Nachrichtenverarbeitungsmethoden und kann direkt verwendet werden. Wenn Sie speziellere Anforderungen haben und MessageContext anpassen müssen, wird empfohlen, diese Klasse als Basisklasse zu verwenden, um erforderliche Umschreibungen vorzunehmen. Die folgende ist beispielsweise eine benutzerdefinierte Kontextklasse:

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(. ) Methode oben Es wird ausgelöst, wenn der Kontext eines Benutzers gelöscht wird, und Sie können den benötigten Code hinzufügen. Darüber hinaus können Sie bei der Akkumulation auch Methoden wie OnRemoved() überschreiben oder andere Attribute und Methoden hinzufügen.

Weitere Artikel zur Entwicklung der öffentlichen WeChat-Plattform: Lösung von Benutzerkontextproblemen (Sitzungen) finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn