【Java树形菜单系统设计与实现】

发布于:2025-06-18 ⋅ 阅读:(18) ⋅ 点赞:(0)

ruoyi实现

根据用户 ID 查询菜单树

   public List<SysMenu> selectMenuTreeByUserId(String useNo) {
        List<SysMenu> menus = null;
        if (SecurityUtils.isAdmin(useNo))
        {
        	// 管理员查询所有权限
            menus = menuMapper.selectMenuTreeAll();
        }
        else
        {
            // 不是管理员,需要查询路由
            menus = menuMapper.selectMenuTreeByUseNo(useNo);
        }
        return getChildPerms(menus, 0);
    }

根据给定的父节点ID构建出树形结构的子菜单。

   // 根据给定的父节点ID从平面菜单列表中筛选并构建出树形结构的子菜单。
    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
        List<SysMenu> returnList = new ArrayList<SysMenu>();

        for (SysMenu t : list) {
            if (t.getParentId() == parentId) {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

递归地为当前菜单节点构建完整的子树结构

   // 递归地为当前菜单节点构建完整的子树结构,设置其所有子节点及其后代节点。
   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) {
        List<SysMenu> tlist = new ArrayList<SysMenu>();
        for (SysMenu n : list) {
            if (n.getParentId().longValue() == t.getMenuId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

判断是否有子节点

	// 判断是否有子节点
    private boolean hasChild(List<SysMenu> list, SysMenu t) {
        return getChildList(list, t).size() > 0;
    }

简化

 public List<SysMenu> selectMenuTreeByUserId(String useNo) {
        List<SysMenu> menus = null;
        if (useNo.equals("P059569")) {
            // 管理员查询所有权限
           return selectMenuTree() ;


        } else {
            // 不是管理员,需要查询路由
            return selectMenuTree() ;
        }
    }
    // 查询所有菜单并递归子菜单
    @Override
    public List<SysMenu> selectMenuTree() {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        // 设置查询条件
        wrapper.in(SysMenu::getMenuType, Arrays.asList("M", "C"))  // 菜单类型为目录(M)或菜单(C)
                .eq(SysMenu::getStatus, 0)                      // 状态为0(正常)
                .orderByAsc(SysMenu::getParentId, SysMenu::getOrderNum);// 设置排序(先按父ID排序,再按排序号排序)

        List<SysMenu> menus = menuMapper.selectList(wrapper);

        // 1. 创建菜单映射表并初始化children
        // 将菜单列表转换为一个Map,其中:
        // - 键(key)是菜单ID(Long类型)
        // - 值(value)是菜单对象(SysMenu)
        Map<Long, SysMenu> menuMap = menus.stream()

                // peek()是一个中间操作,用于对每个元素执行操作但不改变流内容
                // 这里对每个菜单对象执行初始化children列表的操作
                .peek(menu -> menu.setChildren(new ArrayList<>()))

                // 终止操作,将流转换为Map
                // Collectors.toMap()需要两个参数:
                // 1. SysMenu::getMenuId - 键提取函数,从菜单对象获取菜单ID作为Map的键
                // 2. Function.identity() - 值提取函数,直接使用菜单对象本身作为Map的值
                .collect(Collectors.toMap(SysMenu::getMenuId, Function.identity()));

        // 2. 构建父子关系
        menus.forEach(menu -> {
            if (menu.getParentId() != 0) {// 如果不是根菜单(parentId=0的是根菜单)
                SysMenu parent = menuMap.get(menu.getParentId());
                if (parent != null) {
                    parent.getChildren().add(menu);// 将当前菜单添加到父菜单的children列表中
                }
            }
        });

        // 3. 返回根节点并排序
        return menus.stream()
                // 1.筛选出所有根菜单(parentId == 0的菜单)
                .filter(menu -> menu.getParentId() == 0)
                // 2.对每个根菜单进行处理
                .peek(root ->
                        // 对当前根菜单的子菜单列表进行排序
                        // 使用Comparator.comparingInt根据orderNum字段进行升序排序
                        root.getChildren().sort(Comparator.comparingInt(SysMenu::getOrderNum)))
                // 3.对所有根菜单进行升序排序
                .sorted(Comparator.comparingInt(SysMenu::getOrderNum))
                // 4.将处理后的Stream收集为List
                .collect(Collectors.toList());
    }

网站公告

今日签到

点亮在社区的每一天
去签到