背景是这样的,项目目前的用户session存储在redis中,使用了shiro-redis这个插件。最近有个需求,需要查看用户在线状态,就需要用到shiro-redis这个插件去读取在线的用户,但是却发现其代码久未更新,依然使用旧版本的jedis(2.9),但是项目中也使用了spring—data-redis,其中引用的jedis(3.7.1)和代码版本不匹配,导致无法使用,
scanResult.getStringCursor()
jedis中方法已变更为 getCursor(),现在解决办法有以下3种:
-
下载shiro-redis源码,修改依赖以及错误代码,手动编译
-
降低jedis版本至2.9。可能引发redis的其他问题,暂不可取。
-
重写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;
}
};
- 使用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。
本文由 转啊转 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2019/09/01 15:58