项目需求
我们需要向服务端发送请求,获取一个带有层级关系的菜单,有两种处理方式:一种为同步获取、另一种为异步获取。
表结构
pid:父文件夹的id
isparent:是否为文件夹
异步加载
什么是异步加载?
异步加载指的是并不一次性获得所有文件及它们的层级关系,而是需要什么获得什么
例子:当我们访问主页时,我们的客户端会向服务端发起其请求,获取顶级目录(成员管理、成员订单管理、内容管理、其它管理),而当我们打开成员管理时,会向服务端发送成员管理的mid,并查询成员管理的子目录(也就是所有pid=成员管理的mid 的菜单)
代码实现
@Select("select * from t_menu where mid in " +
"(select mid from t_role_menu where rid in" +
" (select rid from t_admin_role where aid=#{aid})) and pid=#{pid}")
List<Menu> selMenuMapper(@Param("aid") Integer aid,@Param("pid") Integer pid);
由于上述代码涉及到了权限管理,所以比我们上面说的复杂一些,不涉及权限管理的话:
select * from t_menu where pid=#{mid}
同步加载
很多时候,我们也需要同步加载来显示完整的层级,比如添加权限等
什么是同步加载?
和异步加载不同,同步加载是发送一次请求就获得目录的所有层级关系
如何实现?
一个复杂的项目中,菜单的层级往往是一层套着一层,十分复杂,但层级之间却又通过pid联系起来,这个业务场景非常适合用递归去解决。
我们首先将pid设为0,查找所有pid=0的目录,然后判断该目录是否为父级目录(看isparent是否为1),若为父级目录则设pid=该目录的mid,并重复上述操作
代码实现
public List<TreeResult> selMenuService(){
//查找t_menu的所有记录,避免递归一次查询一次数据库
List<Menu> menus = menuMapper.selAllMenuMapper();
//执行递归,首先设pid=0
List<TreeResult> childs = findChild(menus, 0);
return childs;
}
/**
* 同步查询关系列表
* @param menus
* @param pid
* @return
*/
private List<TreeResult> findChild(List<Menu> menus, int pid) {
List<TreeResult> list = new ArrayList<>();
for(Menu item:menus){
if(item.getPid()==pid) {
TreeResult result = new TreeResult();
result.setText(item.getMname());
result.setId(item.getMid());
result.setState("1".equals(item.getIsparent()) ? "closed" : "open");
Map<String, Object> map = new HashMap<>();
map.put("mdesc", item.getMdesc());
map.put("pid", item.getPid());
map.put("url", item.getUrl());
result.setAttributes(map);
List<TreeResult> childNodes = findChild(menus, item.getMid());
result.setChildren(childNodes);
list.add(result);
}
}
return list;
}