近期因项目需要做一个在线用户信息收集,在网上搜索基本都是用redis  zset 实现 。觉得有点麻烦,希望有更简便的方式。

下面我用redis定时清理功能 + 客户端心跳 实现 

直接上代码,1.先实现登录成功后把用户登录信息保存到redis中

private void updOnlineUser(String userNameId,String userName,boolean isheartbeat){
        String json = stringRedisTemplate.opsForValue().get(ONLINE_USERS+userNameId);
        Map<String,Object> maps = new HashMap<>();
        String loginTime = "";
        if(!Strings.isBlank(json)) {
            maps = com.alibaba.fastjson.JSONObject.parseObject(json, Map.class);
            loginTime = maps.get("userLoginTime").toString();
        }
        maps.put("userName",userName);
        maps.put("userNameId",userNameId);
        maps.put("userLoginTime",com.misboot.system.utils.DateUtils.format(new Date(), com.misboot.system.utils.DateUtils.DATE_TIME_PATTERN));
        if(isheartbeat && !Strings.isBlank(loginTime)){     //如果是心跳,还用之前的登录时间
            maps.put("userLoginTime",loginTime);
        }
        stringRedisTemplate.opsForValue().set(ONLINE_USERS+userNameId, com.alibaba.fastjson.JSONObject.toJSONString(maps),5,TimeUnit.MINUTES);
    }

这里 设置当前值时效5分钟,如果过期自动删除当前key,所以需要心跳保活来保证一直存在。

stringRedisTemplate.opsForValue().set(ONLINE_USERS+userNameId, com.alibaba.fastjson.JSONObject.toJSONString(maps),5,TimeUnit.MINUTES);

2.实现心跳接口(客户端调用)

  @ApiOperation(value = "保活心跳")
    @RequestMapping("/heartbeat")
    @ResponseBody
    public boolean heartbeat() {
        updOnlineUser(this.getCurrentUserNameId(),this.getCurrentUserName(),true);
        return true;
    }

3. 获取在线用户信息

   @ApiOperation(value = "获取在线用户")
    @ResponseBody
    @PostMapping(value = "/getOnlineUsers")
    public Object getOnlineUsers(){
        Set<String> keys = stringRedisTemplate.keys(ONLINE_USERS+"*");
        List<Map<String,Object>> dataUsers = new ArrayList<>();
        for(String key : keys){
            String json = stringRedisTemplate.opsForValue().get(key);
            if(!Strings.isBlank(json)) {
                Map<String,Object> maps = com.alibaba.fastjson.JSONObject.parseObject(json, Map.class);
                dataUsers.add(maps);
            }
        }
        return dataUsers;
    }

4. 当然是客户端实现定时任务了。做个1分钟发一次心跳就可以了(5分钟内检查不到心跳redis自动删除失效的key)

效果来了 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐