HTTP 会话和 CometD 会话具有不同的生命周期:例如,如果临时连接失败,则 CometD 会话将失败,服务器会要求客户端重新握手,从而创建不同的 CometD 会话(代表相同的用户,但使用不同的 CometD clientId
)。在相同的情况下,HttpSession
将保持不变。
考虑到这一点,您需要在应用程序级别维护用户名、通讯者HttpSession
和通讯者之间的映射ServerSession
。我们称之为映射HttpCometDMapper
。每次新用户登录时,您都要注册其名称(或用户的另一个唯一标识符)、HttpSession
和当前ServerSession
. 可能您将需要一个两步过程,首先将用户名和 . 链接起来HttpSession
,然后将相同的用户名与ServerSession
.
如果执行 CometD 重新握手,则使用新的ServerSession
.
HttpSessionListener
您可以通过向 注册 an来链接这两个会话,HttpSession
这样当它被销毁时,您可以ServerSession
从映射器中检索当前的 CometD 并调用ServerSession.disconnect()
它。
反之亦然有点棘手,因为 CometD 没有像HttpSession
has 那样的非活动超时概念。它必须使用您自己的逻辑在应用程序中实现。
这样做的一部分是在 上注册 a RemoveListener
,ServerSession
如下所示:
serverSession.addListener(new ServerSession.RemoveListener()
{
public void removed(ServerSession session, boolean timeout);
{
if (!timeout)
{
// Explicitly disconnected, invalidate the HttpSession
httpCometDMapper.invalidate(session);
}
}
});
此侦听器监视与客户端(和服务器)的显式断开连接 - 谨防重入。
稍微困难的是为非显式断开实现相同的机制。在这种情况下,timeout
参数将为真,但可能由于临时网络故障而发生(与客户端永久消失相反),并且同一用户可能已经与新的ServerSession
.
我认为在这种情况下,应用程序超时可以解决问题:当您看到ServerSession
因超时而被删除时,您会注意到该用户并启动应用程序超时。如果同一个用户重新握手,取消应用超时;否则用户真的走了,应用程序超时到期,你也使之无效HttpSession
。
以上只是想法和建议;实际的实现很大程度上取决于应用程序的细节(这就是 CometD 不提供开箱即用的原因)。
关键点是映射器、HttpSessionListener
和RemoveListener
,以及了解这些组件的生命周期。一旦你做到了这一点,你就可以编写正确的代码来为你的应用程序做正确的事情。
最后,请注意 CometD 具有与HttpSession
通过BayeuxContext
实例交互的与传输无关的方式,您可以从BayeuxServer.getContext()
. 我建议你也看看它,看看它是否可以简化事情,尤其是检索存储在HttpSession
.