赞
踩
原版若依使用到了迭代器进行递归等,由于迭代器比较早了。我几乎没怎么用过。而且uoyi-vue-plus版本当中使用增强for与stream流简化过代码。因此在这里讲plus版本的递归生成树。原理是一样的。
值得注意的是在ruoyi-vue-plus版本当中使用了Hutool当中的TreeUtil来构建树形菜单,十分的简便。
public List<Tree<Long>> buildMenuTreeSelect(List<SysMenu> menus) {
if (CollUtil.isEmpty(menus)) {
return CollUtil.newArrayList();
}
return TreeBuildUtils.build(menus, (menu, tree) ->
tree.setId(menu.getMenuId())
.setParentId(menu.getParentId())
.setName(menu.getMenuName())
.setWeight(menu.getOrderNum()));
}
原版使用buildMenuTree方法进行一顿操作。。。
@Override
public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus)
{
List<SysMenu> menuTrees = buildMenuTree(menus);
return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
}
不过在路由接口获取菜单时依旧按照原版若依的思路来(这是因为需要将菜单组装为router,使用Hutool当中的TreeUtil返回的为Tree列表类型,不方便。而原版单纯返回menu列表方便router组装),只是简化了以下代码。
主要有以下几个方法
/** * 根据父节点的ID获取所有子节点 * * @param list 分类表 * @param parentId 传入的父节点ID * @return String */ public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) { List<SysMenu> returnList = new ArrayList<>(); for (SysMenu t : list) { // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 if (t.getParentId() == parentId) { recursionFn(list, t); returnList.add(t); } } return returnList; } /** * 递归列表 * * @param list * @param t */ private void recursionFn(List<SysMenu> list, SysMenu t) { // 得到子节点列表 List<SysMenu> childList = getChildList(list, t); t.setChildren(childList); for (SysMenu tChild : childList) { if (hasChild(list, tChild)) { recursionFn(list, tChild); } } } /** * 得到子节点列表 */ private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) { return StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId())); } /** * 判断是否有子节点 */ private boolean hasChild(List<SysMenu> list, SysMenu t) { return CollUtil.isNotEmpty(getChildList(list, t)); }
其中第一个方法getChildPerms(),寻找到最顶层(pid=0)的几个菜单,然后将每一个顶层菜单进行递归,看有没有子菜单,最后将这几个递归完成的顶层菜单(此时已经将子菜单递归出来了)add到returnList里面。
recursionFn()方法比较简单了获取当前菜单的子菜单,存入父亲菜单。然后看看子菜单里面有没有子菜单的子菜单,如果有的化,递归调用recursionFn()方法就行了。递归出口在最后一个子菜单没有自己的子菜单的化,那么其childList的size=0,那么下面的增加for循环就无法进行。自然无法继续调用recursionFn()方法,就会直接运行结束。
这里还有一种使用stream流更加简化的方案,原理是一样的
private List<Menu> builderMenuTree(List<Menu> menus, Long parentId) { List<Menu> menuTree = menus.stream() .filter(menu -> menu.getParentId().equals(parentId)) .map(menu -> menu.setChildren(getChildren(menu, menus))) .collect(Collectors.toList()); return menuTree; } /** * 获取存入参数的 子Menu集合 * @param menu * @param menus * @return */ private List<Menu> getChildren(Menu menu, List<Menu> menus) { List<Menu> childrenList = menus.stream() .filter(m -> m.getParentId().equals(menu.getId())) .map(m->m.setChildren(getChildren(m,menus))) .collect(Collectors.toList()); return childrenList; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。