【Java】用户在线人数统计的简单实现
一、需求效果:
就是进入首页时能查看在线人数,没有特定要求,那我就不刷这个接口了
就进入首页加载一次

二、实现思路:
思路参考博客:
https://blog.csdn.net/GitLuckyd/article/details/124488063
如果是以前那种JSP的单体项目,可以用Servlet的监听器API来做
但是不管是Servlet还是现在微服务也好,没办法准确知道用户是否离开了应用
然后上面的思路是:
- 后台定时清空令牌容器
- 前端定时存入令牌,打一个时间差
- 只要存活的用户,不管是操作还是干嘛,只要没有关闭应用,就会持续存入令牌
三、代码实现:
后台接口直接做一个令牌容器
两个接口,一个查询容器令牌个数,一个存入令牌
package cn.ymcd.portal.user.controller;
import cn.ymcd.comm.log.LogFactory;
import cn.ymcd.comm.log.YmcdLogger;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashSet;
import java.util.Set;
/**
* @author OnCloud9
* @version 1.0
* @project portal-app
* @date 2023年10月10日 14:46
*/
@RestController
@RequestMapping("${api.path}/online")
public class UserOnlineCountController {
private YmcdLogger logger = LogFactory.getLogger(this.getClass());
private static final Set<String> TOKEN_SETS = new HashSet<>();
/**
* @author OnCloud9
* @date 2023/10/8 11:34
* @description 获取在线人员数量
* @params []
* @return java.lang.Integer
*/
@GetMapping("/counts")
public Integer getOnlineCounts() {
return TOKEN_SETS.size();
}
/**
* @author OnCloud9
* @date 2023/10/10 14:51
* @description 心跳接口, 前端调用接口定时添加令牌 3分钟一次
* @params [token]
* @return void
*/
@GetMapping("/heart-beat")
public void heartBeatTokenSet(@RequestParam("token") String token) {
TOKEN_SETS.add(token);
}
/**
* @author OnCloud9
* @date 2023/10/10 14:55
* @description 清除令牌 每30分钟执行一次
* @params []
* @return void
*/
@Scheduled(cron = "0 0/30 * * * ?")
public void scheduledTasks() {
logger.info("cn.ymcd.portal.user.controller.UserOnlineCountController 开始清理用户令牌... 当前令牌信息:" + TOKEN_SETS.toString());
TOKEN_SETS.clear();
}
}
前端API接口:
/**
* 获取用户在线人数
* @returns {*}
*/
export function getOnlineCounts() {
return requestPortal({
url: 'online/counts',
method: 'get'
})
}
/**
* 用户在线人数心跳接口
* @returns {*}
*/
export function onlineHeartBeats(token) {
return requestPortal({
url: 'online/heart-beat',
method: 'get',
params: { token }
})
}
首页的定时任务:
import { mapGetters } from 'vuex'
import { getOnlineCounts, onlineHeartBeats } from '../api/user'
computed: {
... mapGetters([
'name',
'roles',
'dept',
'userId',
'token'
])
},
created() {
getOnlineCounts().then(res => (this.onlineCounts = res.data))
/* 每三分钟心跳一次,刷新这个页面加载一次 */
onlineHeartBeats(this.token)
this.heartbeatInterval = setInterval(() => (onlineHeartBeats(this.token)), 1000 * 60 * 3)
},
beforeDestroy() {
clearInterval(this.heartbeatInterval)
}

浙公网安备 33010602011771号