Java 多级菜单实现,以及数据库表怎么设计?

一、引言

小编之前写过如何实现一二级菜单的文章,回顾了下之前所实现的逻辑方式,简直惨不忍睹~~

由于近期小编接触新的项目需要实现展示菜单功能,但这次的菜单是需要多级,并且级数不固定。

像这种需求,一般很简单的来说就是用递归实现了,可以从第一级一直往下查,一直查询到为空为止。

二、数据库表结构

这里小编之列出来几个基本的字段,但是够用了

CREATE TABLE `mall_category` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '类别Id',
  `parent_id` int(11) DEFAULT NULL COMMENT '父类别id当id=0时说明是根节点,一级类别',
  `name` varchar(50) DEFAULT NULL COMMENT '类别名称',
  `status` tinyint(1) DEFAULT '1' COMMENT '类别状态1-正常,2-已废弃',
  `sort_order` int(4) DEFAULT NULL COMMENT '排序编号,同类展示顺序,数值相等则自然排序',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100034 DEFAULT CHARSET=utf8;

三、代码实现

步骤一:一共有两个实体类,一个是对应数据库的实体类,还有一个是返回给前端的实体类

/**
 * @Auther: IT贱男
 * @Date: 2019/12/16 16:45
 * @Description: 商品类目
 */
@Data
public class Category {

    private Integer id;

    private Integer parentId;

    private String name;

    private Integer status;

    private Integer sortOrder;

    private Date createTime;

    private Date updateTime;
}
/**
 * @Auther: IT贱男
 * @Date: 2020/2/26 13:58
 * @Description: 返回前端对应实体类
 */
@Data
public class CategoryVo {

    private Integer id;

    private Integer parentId;

    private String name;

    private Integer sortOrder;

    /**
     * 存放类目子级目录
     */
    private List<CategoryVo> subCategories;
}

步骤二:具体实现逻辑,小编这是从项目里面直接截取出来的代码,但是能够实现多级菜单功能~~


import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Auther: IT贱男
 * @Date: 2020/2/26 13:47
 * @Description: 类目查询
 */
@Service
public class ICategoryServiceImpl implements ICategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    /**
     * 对象转换 将数据库实体类对象转还给前端实体
     *
     * @param category
     * @return
     */
    private CategoryVo categoryTOCategoryVo(Category category) {
        CategoryVo categoryVo = new CategoryVo();
        BeanUtils.copyProperties(category, categoryVo);
        return categoryVo;
    }

    @Override
    public ResponseVo selectCategoryAll() {

        // 先查询出全部类目
        List<Category> categories = categoryMapper.selectCategoryAll();

        // 获取一级菜单 , 0 代表一级目录
        List<CategoryVo> rootCategory = categories.stream()
                .filter(e -> e.getParentId().equals("0"))
                .map(this::categoryTOCategoryVo)
                .sorted(Comparator.comparing(CategoryVo::getSortOrder).reversed())
                .collect(Collectors.toList());

        // 查找子节点
        findSubCategory(categories, rootCategory);

        return ResponseVo.success(rootCategory);
    }
     /**
     * 根据一级递归调用子级
     *
     * @param categoryList
     * @param rootCategory
     * @return
     */
    private void findSubCategory(List<Category> categoryList, List<CategoryVo> rootCategory) {
        // 遍历一级
        for (CategoryVo categoryVo : rootCategory) {
            List<CategoryVo> subCategoryVoList = new ArrayList<>();
            // 查找子级
            for (Category category : categoryList) {
                // 判断当前目录是否是子父级关系
                if (categoryVo.getId().equals(category.getParentId())) {
                    subCategoryVoList.add(categoryTOCategoryVo(category));
                }
                // 递归调用,不管有几级菜单,都能够适用
                findSubCategory(categoryList, subCategoryVoList);
                // 类目显示排序,reversed 表示数字越大靠前
                subCategoryVoList.sort(Comparator.comparing(CategoryVo::getSortOrder).reversed());
            }
            // 最后把查到的子级保存到一级目录中
            categoryVo.setSubCategories(subCategoryVoList);
        }
    }

}

四、补充说明

一、小伙伴可能会有疑问,这样循环嵌套会不会影响效率

其实像这些循环操作来说,都是基于内存操作,内存操作是很快的,这点可以不用考虑。

二、需要避免的问题

其实对于这种数据的操作,最好一次性能够查询出来最好,商品目录最多也不过几千条。千万不要循环去查询数据库,这种是极度危险的行为。小编就在工作当中遇到有在循环一直去查询数据库的情况,如果不考虑效率可以这么操作。

 

好了,最后提醒大家,疫情期间,好好保护自己

不出门,就是对祖国做出最大的贡献哈哈哈  (老板要求去公司,俺也没办法,赚钱要紧,赚钱要紧) ~~~~

 

发布了152 篇原创文章 · 获赞 422 · 访问量 43万+

猜你喜欢

转载自blog.csdn.net/weixin_38111957/article/details/104524135