shiro-redis下管理员怎么查看用户是否在线

/ 编程记录 / 没有评论 / 381浏览

背景是这样的,项目目前的用户session存储在redis中,使用了shiro-redis这个插件。最近有个需求,需要查看用户在线状态,就需要用到shiro-redis这个插件去读取在线的用户,但是却发现其代码久未更新,依然使用旧版本的jedis(2.9),但是项目中也使用了spring—data-redis,其中引用的jedis(3.7.1)和代码版本不匹配,导致无法使用,

scanResult.getStringCursor()

jedis中方法已变更为 getCursor(),现在解决办法有以下3种:

  1. 下载shiro-redis源码,修改依赖以及错误代码,手动编译

  2. 降低jedis版本至2.9。可能引发redis的其他问题,暂不可取。

  3. 重写redisConfiguration中创建RedisManager的方法

RedisManager redisManager = new RedisManager(){
            //重写方法解决shiro-redis未更新jedis版本导致的异常
            @Override
            public Set<byte[]> keys(byte[] pattern) {
                Set<byte[]> keys = new HashSet<byte[]>();
                Jedis jedis = getJedis();
                try {
                    ScanParams params = new ScanParams();
                    params.count(super.getCount());
                    params.match(pattern);
                    byte[] cursor = ScanParams.SCAN_POINTER_START_BINARY;
                    ScanResult<byte[]> scanResult;
                    do {
                        scanResult = jedis.scan(cursor, params);
                        keys.addAll(scanResult.getResult());
                        cursor = scanResult.getCursorAsBytes();
                    } while (scanResult.getCursor().compareTo(ScanParams.SCAN_POINTER_START) > 0);
                } finally {
                    jedis.close();
                }
                return keys;
            }
        };
  1. 使用spring-data-redis的lettuce连接池获取
 public Set<Integer> getOnlineUserIds() {
        Object cached = redisService.get(RedisConstant.onlineUserIds);
        if(null!=cached){
            return (Set<Integer>) cached;
        }
        //获取全部登陆的用户缓存key
        Set<String> keys = redisService.keys(RedisConstant.shiroSessionKey+"*");
        //读取redis已登陆的用户并且收集其ID
        Set<Integer> onlineUserIds = keys.stream().map(key -> {
            //直接从LettuceConnectionFactory读取
            byte[] bytes = lettuceConnectionFactory.getConnection().get(key.getBytes());
            //反序列化对象
            SimpleSession session =  ObjectUtil.deserialize(bytes);
            //从session中取到登陆的用户信息
            SimplePrincipalCollection attribute = (SimplePrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
            User cu = (User) attribute.getPrimaryPrincipal();
            return cu.getId();
        }).collect(Collectors.toSet());
        //手动缓存
        redisService.set(RedisConstant.onlineUserIds,onlineUserIds,60);
        return onlineUserIds;
    }

当然笔者最终选择采用的是第四种方法,也可以比较方便的获取在线用户,并且对数据实现缓存以减少io。