要准确计算谁登录并访问该站点,您需要每个客户端每隔几秒钟或几分钟向服务器发送一次“心跳”.在每个心跳触发器上,您希望在未分配的时间范围内使所有未签入的用户失效.
心跳信号可能最好由用户名和时间戳组成,但可能包含您要跟踪的任何信息.
当客户端向服务器发送单个数据库时,它会检查该用户名的现有记录,并在记录已存在时覆盖时间戳信息,否则添加新记录. Afterwords删除任何未签入的用户条目.可能最好让信号比到期时更频繁地发生.像每30秒发出一次信号并每分钟清理一次.
(编辑,改变主意,最好以相同的顺序而不是单独完成)
然后从活动表返回当前登录的用户,这将像SELECT * FROM表一样简单,因为表将始终是干净的.
客户端:
下面是一个客户端库的示例,用于处理触发心跳功能和捕获结果.
//Client-side parent variable declaration (simulated namespacing) var Client = Client || {}; Client.Pulse = null; //Holds a pointer to the heartbeat timer (id) /* If you needed to cancel the heartbeat processes you could * pass this variable to clearTimeout(). Calling Client.Heartbeat() * again would start the cycle back up. */ //Initial event that will kick off the chain when the DOM is ready $(document).ready(function(){ Client.Heartbeat(); //Initial call to the Heartbeat function });//ready /// Sends the heartbeat signal and retrieves the currently active user list Client.Heartbeat = function(){ var sUsername = 'SomeUser'; /* Note: If you have an active session running on the server it would not be * necessary to send the username since you could pull it on the backend * script which would be more tamper-proof anyway. I'm just giving an * example of sending data to the server using the jQuery.ajax method * If you were storing the username to be sent from the client; this wouldn't * be a good place to do it anyway * * Remove the "data : {...}" line below to exclude sending information to the server * The "type : 'post'" line would not be necessary either */ $.ajax({ //Send the signal and recieve the information about active users back url : '/lib/server/Heartbeat.PHP',type : 'post',dataType : 'json',data : {Username : sUsername },success : function(jActiveUsers,sStatus,jqXHR){ /* This is the callback function of the request,jActiveUsers will be the * json object with the information you choose to send back to it */ Client.RenderActiveUsers(jActiveUsers); //Call the display function //Trigger the next delayed call to Client.Heartbeat Client.Pulse = setTimeout(function(){ Client.Heartbeat(); },30000); //30 second delay before next trigger }//success });//$.ajax }//Heartbeat /// Processes the results sent by the server and draws them to the UI Client.RenderActiveUsers = function(jActiveUsers){ /* This is where you would get a handle whatever element(s) on the page * will be displaying the information about currently active users * and filling it with the list of users how ever you would wish to display it. */ }//RenderActiveUsers
因为你将处理异步回调setTimeout()调用在一个完整周期结束时重新启动进程将是一个更简洁的处理间隔的方法,如果你使用setInterval()并且服务器花了比预期更长的时间回来你可以看到客户开始竞争自己.在成功回调中使用setTimeout()还可以在服务器端心跳处理器停止工作时正常失败;客户端也是如此,而不是继续尝试失败(如果你想让它继续尝试你只需要在失败的响应上添加一个重新触发).
服务器端:
I apologize I am not familiar with Java as a back-end service,I will
be making some assumptions based on how PHP works; so I cannot
guarantee it will map directly to your environment.
Database examples will assume MysqL.
code examples will be pseudo-cody PHP(ish)
在服务器端,您将需要一个新表来跟踪活动用户.您可能已经在数据库中登录时进行跟踪,但这将与该系统分开(尽管您当然可以链接到该系统以获取返回结构的额外用户详细信息)
该表至少会看到以下内容:
ActiveUsers ----------------------------------------- | Field | Type | NULL | Key | ----------------------------------------- | Id | int | | PRI | | Username | varchar(xx) | | | | LastPulse | datetime | | | | FirstPulse | datetime | | | -----------------------------------------
(推测)我假设像PHP一样,Java中有Sessions,您可以使用它来存储特定访问者的信息,例如他们当前的状态.在PHP中,这通过在客户端和服务器之间来回传递标识符来工作,允许服务器识别特定客户端,并在后端存储与该会话相关的变量(例如,具有当前登录状态的布尔值)用户或登录后用于保存用户名的字符串.)
如果您可以使用它,那么处理身份验证的方式要比在客户端存储此信息更安全,并允许客户端指示是否以及登录的人员.这里假设它是….
当客户端将心跳发送到服务器时,如果它们事实上已登录以开始该过程,则可以从会话变量访问其登录状态和用户名.
if($LoggedIn && ($Username != null)){ //Session information
如果他们没有登录,您将跳到列表检索部分,因为您不需要为它们添加或修改记录
检查它们是否在活动表中有记录
SELECT `Id` FROM `ActiveUsers` WHERE `Username` = '{$Username}' LIMIT 1
如果存在记录,则表示它们之前已经签入,并且您希望使用从第一个查询返回的Id值使用新时间戳更新记录
UPDATE `ActiveUsers` SET `LastPulse` = NOW() WHERE `Id` = {$Id}
如果不存在记录,则需要为此用户创建一个新记录
INSERT INTO `ActiveUsers` (`Username`,`LastPulse`,`FirstPulse`) VALUES ('{$Username}',NOW(),NOW())
接下来是该过程的维护阶段,您可以在该过程中清除未设置的任何条目,并将其设置为您要设置为限制的时间(本示例中为2分钟)
DELETE FROM `ActiveUsers` WHERE `LastPulse` < (NOW() - INTERVAL 2 MINUTE)
这将留下您的ActiveUsers表,以便只存在您可以查询以获取的活动用户的记录,以及您希望从此处以及您可以链接到的任何其他表中获得的任何其他信息
SELECT `Username`,UNIX_TIMESTAMP(`FirstPulse`) AS `FirstPulse` FROM `ActiveUsers` ORDER BY `FirstPulse` ASC
(在PHP中)然后,您需要遍历结果集并构建一个用户数组,通过调用json_encode()和print()以及“application / json”标头值将其转换为JSON,以便jQuery可以正确处理它.这当然会在实现中的Java之间有所不同,但“创建数组,将其转换为JSON字符串并使用指定的正确标头打印出来”的整个过程将是相同的.
理想情况下,您希望将客户端尽可能“愚蠢”地保留在任何类型的身份验证过程中.在此示例中,客户端盲目地检入服务器并仅通过询问活动用户的新列表来触发过期用户的清理.
如果100%准确的列表在高度利用的站点上是关键任务的,则可能需要在执行维护部分时锁定表.确保在另一个线程处于签入阶段时不会发生对用户列表的查询.
(哇,这变成了一个Wall-O-Text)