管理系统必备技(1):递归生成树形结构菜单

微信公众号:潇雷
当努力到一定程度,幸运自与你不期而遇。

1、概述

后台管理系统是web开发必备的一个项目,因此有必要对系统的一些基本功能做个梳理,今天要看的内容是如何递归生成树形结构菜单,效果图如下:

菜单分为一级菜单、二级菜单、复杂的菜单甚至包含三级菜单和四级菜单,这些数据在表里面都是在一个菜单目录表里。

表的核心设计如下:

字段名称备注
idint主键id
parent_idint一级菜单为0 ,其他菜单指向父类的id
menu_pathvarchar资源路径
sortint排序
menu_buttontinyint是否作为目录展示,或者隐藏等需求

2、代码实现

思路比较统一:

1、首先找到菜单数据的所有数据

2、然后找到所有的一级菜单,将它的子树拼接上

3、子树也会有子菜单,需要递归拼接子树的子菜单。

首先对原先的实体类,我们需要增加一个字段存放子菜单的列表,加上注解表示该字段不在数据库中拥有。

2.1 基础版实现
  @Override
    public List<ChildMenuVO> listWithTree() {
        //1、查出所有菜单
        List<CategoryEntity> categoryEntities = categoryDao.selectList(null);
        //2、组装成父子的树形结构
        List<ChildMenuVO> childMenuVOS =treeMenu(categoryEntities);
        return childMenuVOS;
    }

    private List<ChildMenuVO> treeMenu(List<CategoryEntity> categoryEntities) {
        List<ChildMenuVO> childMenuVOS=new ArrayList<>();
        for (int i = 0; i < categoryEntities.size(); i++) {
            CategoryEntity categoryEntity=categoryEntities.get(i);
            //如果父id为0 的话,就不执行后续方法
            if(0!=categoryEntity.getParentCid().intValue()){
                continue;
            }
            ChildMenuVO childMenuVO = new ChildMenuVO();
            BeanUtils.copyProperties(categoryEntity,childMenuVO);
            //递归判断 当前menu 是否有子节点,如果有则set
            childMenuVO.setChild(subMenu(categoryEntity,categoryEntities));
            childMenuVOS.add(childMenuVO);
        }
        return childMenuVOS;
    }

    private List<ChildMenuVO> subMenu(CategoryEntity parentMenu, List<CategoryEntity> categoryEntities) {
        List<ChildMenuVO> childMenuVOS =new ArrayList<>();
        //遍历所有目录
        for (int i = 0; i < categoryEntities.size(); i++) {
            CategoryEntity subCategory=categoryEntities.get(i);
            if(subCategory.getParentCid().equals(parentMenu.getCatId())){
                ChildMenuVO childMenuVO = new ChildMenuVO();
                BeanUtils.copyProperties(subCategory,childMenuVO);
                childMenuVO.setChild(subMenu(subCategory,categoryEntities));
                childMenuVOS.add(childMenuVO);
            }
        }
        return childMenuVOS;
    }
2.2 进阶版实现
 public List<CategoryEntity> listWithTree() {
        //1、查出所有菜单
        List<CategoryEntity> categoryEntities = categoryDao.selectList(null);
        //2、组装成父子的树形结构
            //2.1 找到所有的一级分类
            List<CategoryEntity> level1Menus = categoryEntities.stream().filter(categoryEntity -> {
                return categoryEntity.getParentCid() == 0;
            }).map(menu->{
                menu.setChildren(getChildrens(menu,categoryEntities));
                return menu;
            }).sorted((menu1,menu2)->{
                return (menu1.getSort()==null?0:menu1.getSort())-(menu2.getSort()==null?0:menu2.getSort());
            })
              .collect(Collectors.toList());
            return level1Menus;
    }

    //递归找到当前菜单的子菜单
    private List<CategoryEntity> getChildrens(CategoryEntity  root,List<CategoryEntity> all){
        List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
            return categoryEntity.getParentCid().equals(root.getCatId());
        }).map(categoryEntity -> {
            categoryEntity.setChildren(getChildrens(categoryEntity,all));
            return categoryEntity;
        }).sorted((menu1,menu2)->{
            return (menu1.getSort()==null?0:menu1.getSort())-(menu2.getSort()==null?0:menu2.getSort());
        }).collect(Collectors.toList());
        return children;
    }

不得不说java8的stream流极大的简洁了代码,后续也会记录java8的文章,效果也达到了,stream流有点像sql,可以做出排序、过滤、判断等各种简洁的操作。

今天的分享就到这里,有兴趣可以关注,后续更多内容干货敬请期待。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值