【Java】用户在线人数统计的简单实现

发布时间 2023-10-13 09:26:43作者: emdzz

一、需求效果:

就是进入首页时能查看在线人数,没有特定要求,那我就不刷这个接口了

就进入首页加载一次

 

二、实现思路:

思路参考博客:

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)
}