我正在开发一个基于Spring-MVC的网络应用程序,它使用Cometd进行聊天。为了实时管理哪个用户在线,我们在用户上线时发送通知。因此,当窗口关闭时,通知不会出现,并且在30秒后确定用户离线或无法访问。
现在当用户在多个浏览器上时会出现问题。让我们现在保持2。因此,在10分钟后,我们将用户状态设置为“远离键盘”(AFK)。但是如果用户在一个浏览器中联机,那么我们将获得一个闪烁的状态,因为浏览器处于“空闲模式”状态几秒钟,我们得到一个AFK,并且从活动机器我们得到一个& #39;可用'状态。
我们如何解决这个问题?任何想法,建议。我想过使用一个布尔标志,并与IP地址结合,在覆盖通知之前将对其进行检查,但它存在过时通知的问题。
这是我向所有听众(用户之友)发送在线通知的代码。
代码:
@Listener(value = "/service/online")
public void OnlineNotifications(ServerSession remote, ServerMessage.Mutable message) {
Person sender = this.personService.getCurrentlyAuthenticatedUser();
Map<String, Object> input = message.getDataAsMap();
String onlineStatus = (String) input.get("status");
Map<String, Object> output = new HashMap<>();
output.put("status", onlineStatus);
output.put("id", sender.getId());
ServerChannel serverChannel = bayeux.createChannelIfAbsent("/online/" + sender.getId()).getReference();
serverChannel.setPersistent(true);
serverChannel.publish(serverSession, output);
}
欢迎任何想法。非常感谢。 : - )
答案 0 :(得分:1)
您的应用可以轻松地将多个设备与同一userName
相关联。
您可以使用SecurityPolicy
执行此操作,只需将userName
字符串与List<ServerSession>
或任何适合您情况的数据结构相关联。
因此,特定userName
的在线状态是此特定ServerSession
的所有userName
的函数。
因此,它是从userName
到在线状态列表的映射。
如果您想象用户bob
从两个浏览器登录,其在线状态的映射可以是:
"bob" -> ["afk", "online"]
要计算bob
的在线状态,您只需浏览每个ServerSession
的所有在线状态,如果至少有一个online
,那么它就在线,如果全部是{{} 1}}然后它远离键盘,依此类推。
您可以通过多种方式实现此逻辑(例如,将在线状态存储为afk
属性,使用不同的数据结构,缓存每个用户的在线状态等),但您明白了。
每当您从一个ServerSession
获得在线状态更改时,您将更新服务器端数据结构,然后从该用户的所有ServerSession
重新计算在线状态,这就是您的意思发送给其他用户。