Skip to content

路由格式化工具

工具剖析

路由列表格式化树结构

java
    /**
     * 路由列表格式化树结构
     * @param systemMenus 路由列表
     * @return 格式化后的路由信息
     */
    public static List<JSONObject> formatToTree (List<SystemMenu> systemMenus,String type) {
        // 将系统路由列表转换成路由数据转换对象列表
        List<MenuDTO> menuDTOS = systemMenus.stream().map(item -> {
            MenuDTO menuDTO = new MenuDTO();
            BeanUtils.copyProperties(item,menuDTO);
            return menuDTO;
        }).collect(Collectors.toList());

        // 把数据组合成树形结构
        List<MenuDTO> result = menuDTOS.stream()
                // 查找第一级菜单
                .filter(menu -> menu.getPmid() == 0)
                // 查找子菜单并放到第一级菜单中
                .peek(menu -> {
                    // 标记模块等级
                    menu.setMenuLevel(1)
                    menu.setChildren(getChildren(menu, menuDTOS));
                })
                // 根据排序字段排序
                .sorted(Comparator.comparingInt(menu -> (menu.getSortNum() == null ? 0 : menu.getSortNum())))
                .collect(Collectors.toList());
        if (type.equals("side")) {
            return formatSideMenu(result);
        } else {
            return formatAllMenu(result);
        }
    }

递归获取子路由

java
    /**
     * 递归获取子菜单
     * @param root 当前菜单
     * @param all 总的数据
     * @return 子菜单
     */
    private static List<MenuDTO> getChildren(MenuDTO root, List<MenuDTO> all) {
        List<MenuDTO> children = all.stream()
                // 根据 父菜单 ID 查找当前菜单 ID,以便于找到 当前菜单的子菜单
                .filter(menu -> Objects.equals(menu.getPmid(), root.getMid()))
                // 递归查找子菜单的子菜单
                .peek((menu) -> {
                    menu.setMenuLevel(root.getMenuLevel() + 1);
                    menu.setChildren(getChildren(menu, all));
                })
                // 根据排序字段排序
                .sorted(Comparator.comparingInt(menu -> (menu.getSortNum() == null ? 0 : menu.getSortNum())))
                // 把处理结果收集成一个 List 集合
                .collect(Collectors.toList());
        return children;
    }

格式化路由信息

java
/**
     * 根据要求格式化路由信息
     * @param menuDTOS 路由树列表
     * @return 格式化后的树结构路由信息
     */
    private static List<JSONObject> formatSideMenu (List<MenuDTO> menuDTOS) {
        List<JSONObject> menuJson = menuDTOS.stream().map(m -> {
            JSONObject menuItem = new JSONObject();
            menuItem.put("mid",m.getMid());
            menuItem.put("path", m.getPath());
            menuItem.put("name", m.getName());
            JSONObject meta = new JSONObject();
            meta.put("icon", m.getIcon());
            meta.put("title", m.getTitle());
            if ("1".equals(m.getIsLink())) {
                meta.put("isLink", m.getLinkUrl());
            }
            meta.put("isHide", m.getIsHide() == 1);
            meta.put("isKeepAlive", m.getIsKeepalive() == 1);
            menuItem.put("meta", meta);
            if (m.getMenuType().equals(MenuTypeEnum.ROUTER_BASIC.getTypeId())) {
                menuItem.put("component", m.getComponent());
            } else if (m.getMenuType().equals(MenuTypeEnum.ROUTER_REDIRECT.getTypeId())) {
                menuItem.put("redirect", m.getComponent());
            }
            List<MenuDTO> children = m.getChildren();
            if (children.size() > 0) {
                menuItem.put("children",formatSideMenu(children));
            }
            return menuItem;
        }).collect(Collectors.toList());
        return menuJson;
    }

格式化路由信息

| 路由信息根据实际情况有所变动

java

    /**
     * 根据要求格式化路由信息
     * @param menuDTOS 路由树列表
     * @return 格式化后的树结构路由信息
     */
    private static List<JSONObject> formatAllMenu (List<MenuDTO> menuDTOS) {
        List<JSONObject> menuJson = menuDTOS.stream().map(m -> {
            JSONObject menuItem = new JSONObject();
            menuItem.put("mid",m.getMid());
            menuItem.put("pmid",m.getPmid());
            menuItem.put("path", m.getPath());
            menuItem.put("name", m.getName());
            menuItem.put("status", m.getStatus());
            menuItem.put("title", m.getTitle());
            menuItem.put("apiPath",m.getApiPath());
            menuItem.put("menuType",m.getMenuType());
            menuItem.put("component",m.getComponent());
            menuItem.put("icon",m.getIcon());
            menuItem.put("isHide",m.getIsHide());
            menuItem.put("isLink",m.getLinkUrl());
            menuItem.put("isKeepalive",m.getIsKeepalive());
            menuItem.put("sortNum",m.getSortNum());
            List<MenuDTO> children = m.getChildren();
            if (children.size() > 0) {
                menuItem.put("children",formatAllMenu(children));
            }
            return menuItem;
        }).collect(Collectors.toList());
        return menuJson;
    }

完整工具类

java
package com.lh.utils;

import cn.hutool.json.JSONObject;
import com.lh.entity.SystemMenu;
import com.lh.dto.MenuDTO;
import com.lh.enums.MenuTypeEnum;
import com.lh.enums.StatusEnum;
import org.springframework.beans.BeanUtils;

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

/**
 * @ClassName MenuFormat
 * @Author liupengxiang
 * @Date 2023/6/19 17:43
 * @Description 菜单格式化
 */
public class MenuFormat<T> {
    /**
     * 路由列表格式化树结构
     * @param systemMenus 路由列表
     * @return 格式化后的路由信息
     */
        public static List<JSONObject> formatToTree (List<SystemMenu> systemMenus,String type) {
        // 将系统路由列表转换成路由数据转换对象列表
        List<MenuDTO> menuDTOS = systemMenus.stream().map(item -> {
            MenuDTO menuDTO = new MenuDTO();
            BeanUtils.copyProperties(item,menuDTO);
            return menuDTO;
        }).collect(Collectors.toList());

        // 把数据组合成树形结构
        List<MenuDTO> result = menuDTOS.stream()
                // 查找第一级菜单
                .filter(menu -> menu.getPmid() == 0)
                .peek(menu -> menu.setMenuLevel(1))
                // 查找子菜单并放到第一级菜单中
                .peek(menu -> {
                    menu.setChildren(getChildren(menu, menuDTOS));
                })
                // 根据排序字段排序
                .sorted(Comparator.comparingInt(menu -> (menu.getSortNum() == null ? 0 : menu.getSortNum())))
                .collect(Collectors.toList());
        if (type.equals("side")) {
            return formatSideMenu(result);
        } else {
            return formatAllMenu(result);
        }

    }
    /**
     * 递归获取子菜单
     * @param root 当前菜单
     * @param all 总的数据
     * @return 子菜单
     */
    private static List<MenuDTO> getChildren(MenuDTO root, List<MenuDTO> all) {
        List<MenuDTO> children = all.stream()
                // 根据 父菜单 ID 查找当前菜单 ID,以便于找到 当前菜单的子菜单
                .filter(menu -> Objects.equals(menu.getPmid(), root.getMid()))
                // 递归查找子菜单的子菜单
                .peek((menu) -> {
                    // 标记模块等级
                    menu.setMenuLevel(root.getMenuLevel() + 1);
                    menu.setChildren(getChildren(menu, all));
                })
                // 根据排序字段排序
                .sorted(Comparator.comparingInt(menu -> (menu.getSortNum() == null ? 0 : menu.getSortNum())))
                // 把处理结果收集成一个 List 集合
                .collect(Collectors.toList());
        return children;
    }

    /**
     * 根据要求格式化路由信息
     * @param menuDTOS 路由树列表
     * @return 格式化后的树结构路由信息
     */
    private static List<JSONObject> formatSideMenu (List<MenuDTO> menuDTOS) {
        List<JSONObject> menuJson = menuDTOS.stream().map(m -> {
            JSONObject menuItem = new JSONObject();
            menuItem.put("mid",m.getMid());
            menuItem.put("path", m.getPath());
            menuItem.put("name", m.getName());
            JSONObject meta = new JSONObject();
            meta.put("icon", m.getIcon());
            meta.put("title", m.getTitle());
            if ("1".equals(m.getIsLink())) {
                meta.put("isLink", m.getLinkUrl());
            }
            meta.put("isHide", m.getIsHide() == 1);
            meta.put("isKeepAlive", m.getIsKeepalive() == 1);
            menuItem.put("meta", meta);
            if (m.getMenuType().equals(MenuTypeEnum.ROUTER_BASIC.getTypeId())) {
                menuItem.put("component", m.getComponent());
            } else if (m.getMenuType().equals(MenuTypeEnum.ROUTER_REDIRECT.getTypeId())) {
                menuItem.put("redirect", m.getComponent());
            }
            List<MenuDTO> children = m.getChildren();
            if (children.size() > 0) {
                menuItem.put("children",formatSideMenu(children));
            }
            return menuItem;
        }).collect(Collectors.toList());
        return menuJson;
    }


    /**
     * 根据要求格式化路由信息
     * @param menuDTOS 路由树列表
     * @return 格式化后的树结构路由信息
     */
    private static List<JSONObject> formatAllMenu (List<MenuDTO> menuDTOS) {
        List<JSONObject> menuJson = menuDTOS.stream().map(m -> {
            JSONObject menuItem = new JSONObject();
            menuItem.put("mid",m.getMid());
            menuItem.put("pmid",m.getPmid());
            menuItem.put("path", m.getPath());
            menuItem.put("name", m.getName());
            menuItem.put("status", m.getStatus());
            menuItem.put("title", m.getTitle());
            menuItem.put("apiPath",m.getApiPath());
            menuItem.put("menuType",m.getMenuType());
            menuItem.put("component",m.getComponent());
            menuItem.put("icon",m.getIcon());
            menuItem.put("isHide",m.getIsHide());
            menuItem.put("isLink",m.getLinkUrl());
            menuItem.put("isKeepalive",m.getIsKeepalive());
            menuItem.put("sortNum",m.getSortNum());
            List<MenuDTO> children = m.getChildren();
            if (children.size() > 0) {
                menuItem.put("children",formatAllMenu(children));
            }
            return menuItem;
        }).collect(Collectors.toList());
        return menuJson;
    }
}

需要的实体类信息

系统菜单实体类

java
package com.lh.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * <p>
 * 系统菜单表
 * </p>
 *
 * @author lpx
 * @since 2023-06-19
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("system_menu")
public class SystemMenu implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 菜单id
     */
    @TableId(value = "MID", type = IdType.AUTO)
    private Integer mid;

    /**
     * 父菜单id
     */
    @TableField("PMID")
    private Integer pmid;

    /**
     * 组件名
     */
    @TableField("NAME")
    private String name;

    /**
     * 路由标题
     */
    @TableField("TITLE")
    private String title;

    /**
     * 菜单类型
     */
    @TableField("MENU_TYPE")
    private Integer menuType;

    /**
     * 路由组件地址
     */
    @TableField("COMPONENT")
    private String component;

    /**
     * 路由图标
     */
    @TableField("ICON")
    private String icon;

    /**
     * 前端路由地址
     */
    @TableField("PATH")
    private String path;

    /**
     * api路由
     */
    @TableField("API_PATH")
    private String apiPath;

    /**
     * 序号
     */
    @TableField("SORT_NUM")
    private Integer sortNum;

    /**
     * 是否隐藏 0(默认)不隐藏 1隐藏
     */
    @TableField("IS_HIDE")
    private Integer isHide;

    /**
     * 是否缓存 0(默认)是  1不是
     */
    @TableField("IS_KEEPALIVE")
    private Integer isKeepalive;

    /**
     * 是否链接
     */
    @TableField("IS_LINK")
    private String isLink;

    /**
     * 链接地址
     */
    @TableField("LINK_URL")
    private String linkUrl;

    /**
     * 创建者
     */
    @TableField("CREATED_BY")
    private Integer createdBy;

    /**
     * 创建时间
     */
    @TableField("CREATED_AT")
    private Date createdAt;
    /**
     * 修改人
     */
    @TableField("UPDATED_BY")
    private Integer updatedBy;

    /**
     * 修改时间
     */
    @TableField("UPDATED_AT")
    private Date updatedAt;
    /**
     * 路由状态
     */
    @TableField("STATUS")
    private String status;
    /**
     * 是否删除
     */
    @TableField("IS_DELETE")
    private String isDelete;
}

菜单传输对象

java
package com.lh.dto;

import lombok.Data;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName MenuDTO
 * @Author liupengxiang
 * @Date 2023/6/20 9:48
 * @Description menu传输对象
 */
@Data
public class MenuDTO {
    /**
     * 菜单id
     */
    private Integer mid;
    /**
     * 父菜单id
     */
    private Integer pmid;

    /**
     * 组件名
     */
    private String name;

    /**
     * 路由标题
     */
    private String title;

    /**
     * 菜单类型
     */
    private Integer menuType;

    /**
     * 路由组件地址
     */
    private String component;

    /**
     * 路由图标
     */
    private String icon;

    /**
     * 前端路由地址
     */
    private String path;

    /**
     * api路由
     */
    private String apiPath;

    /**
     * 序号
     */
    private Integer sortNum;

    /**
     * 是否隐藏 0(默认)不隐藏 1隐藏
     */
    private Integer isHide;

    /**
     * 是否缓存 0(默认)是  1不是
     */
    private Integer isKeepalive;

    /**
     * 是否链接
     */
    private String isLink;

    /**
     * 链接地址
     */
    private String linkUrl;

    /**
     * 创建者
     */
    private Integer createdBy;

    /**
     * 创建时间
     */
    private Date createdAt;

    /**
     * 路由状态
     */
    private String status;


    List<MenuDTO> children = new ArrayList<>();
}