本文主要讲解两方面内容:1.redis如何存储树结构数据。2.java操作redis时选取哪种序列化器。
1. redis如何存储树结构数据
先抛出结论,树结构数据在redis中的存储形式如下:
1.1 前置条件
- spring-boot-starter-data-redis(2.1.8)
- fastjson(1.2.61)
- redis可视化工具 Redis Desktop Manager
1.2 树结构数据在redis中的存储形式(数据结构)
假设有如上典型的组织机构数据,前端需要按层级展示,分层级查询指定节点的子集。
1.2.1 redis中Key的设计
redisKey={NAME_SPACE}:{level}:{parentId}
NAME_SPACE:该数据所在命名空间
level:当前层级
parentId:父节点id,可为空
1.2.2 查询
- 按层级查询:输入指定层级,返回该层级下的所有节点列表
入参:
{
"level":3
}
返回:
[
{
"nodeId": "010101",
"nodeName": "人事部"
},
{
"nodeId": "010102",
"nodeName": "技术部"
},
{
"nodeId": "010301",
"nodeName": "人事部"
},
{
"nodeId": "010202",
"nodeName": "技术部"
},
{
"nodeId": "010201",
"nodeName": "人事部"
}
]
- 查询指定节点的所有子节点:输入该节点id和当前层级
入参:
{
"nodeId":"0102",
"level":2
}
返回:
[
{
"nodeId": "010202",
"nodeName": "技术部"
},
{
"nodeId": "010201",
"nodeName": "人事部"
}
]
1.2.3 后台实现
主要代码:
/**
* 查询 指定层级下某个父节点的所有子节点
*
* @param level 层级
* @param parentId 父节点id,为空时查询该层级下所有节点
* @return 指定层级下某个父节点的所有子节点
*/
@SuppressWarnings("unchecked")
public List<OrgBean> getSubTree(int level, @Nullable String parentId) {
List<OrgBean> beanList;
if (StringUtils.isBlank(parentId) && level != 1) {
//parentId 为空,模糊匹配查询
beanList = patternSearch(level);
} else {
//parentId 不为空,精确匹配查询
beanList = exactlySearch(level, parentId);
}
return beanList;
}
@SuppressWarnings("unchecked")
private List<OrgBean> patternSearch(int level) {
//SCAN 0 MATCH {NAME_SPACE}:{level}:* COUNT 10000
String pattern = getRedisKey("*", level);
logger.info("redisKey:{}", pattern);
List<String> keys = (List<String>) redisTemplate.execute(connection -> {
List<String> keyStrList = new ArrayList<>();
RedisKeyCommands keysCmd = connection.keyCommands();
//采用 SCAN 命令,迭代遍历所有key
Cursor<byte[]> cursor = keysCmd.scan(ScanOptions.scanOptions().match(pattern).count(10000L).build());
while (cursor