RuoYi动态路由

513 阅读2分钟

ry的侧边路由是后端动态生成的,并不是前端直接写死的,可以对路由进行新增修改,用户登录后会根据其角色权限去渲染路由。

image.png

其数据库设计了一张带父子结构的一张表

image.png

  • 顶级菜单的parent_id为0
  • 每个菜单独有perms权限字符,登录后通过前面的getInfo接口返回给前端用于资源展示

用户登录后会调用getRouters接口获取菜单路由信息

image.png

下面来看看getRouters接口

     /**
      * 获取路由信息
      * 
      * @return 路由信息
      */
     @GetMapping("getRouters")
     public AjaxResult getRouters()
     {
         Long userId = SecurityUtils.getUserId();
         List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
         return AjaxResult.success(menuService.buildMenus(menus));
     }
 /**
      * 根据用户ID查询菜单
      * 
      * @param userId 用户名称
      * @return 菜单列表
      */
     @Override
     public List<SysMenu> selectMenuTreeByUserId(Long userId)
     {
         List<SysMenu> menus = null;
         if (SecurityUtils.isAdmin(userId))
         {
             menus = menuMapper.selectMenuTreeAll();
         }
         else
         {
             menus = menuMapper.selectMenuTreeByUserId(userId);
         }
         return getChildPerms(menus, 0);
     }

selectMenuTreeByUserId方法比较清楚,区分admin和其他用户,根据sys_role_menu关联表查出该用户拥有的所有菜单资源(打平),再调用getChildPerms将其包装成树结构返回。再看一看这个树化方法。

 /**
      * 根据父节点的ID获取所有子节点
      * 
      * @param list 分类表
      * @param parentId 传入的父节点ID
      * @return String
      */
     public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
     {
         List<SysMenu> returnList = new ArrayList<SysMenu>();
         for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
         {
             SysMenu t = (SysMenu) iterator.next();
             // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
             if (t.getParentId() == parentId)//处理下一层
             {
                 recursionFn(list, t);
                 returnList.add(t);
             }
         }
         return returnList;
     }

调用recursionFn递归树化子节点

 /**
      * 递归列表
      * 
      * @param list 分类表
      * @param t 子节点
      */
     private void recursionFn(List<SysMenu> list, SysMenu t)
     {
         // 得到子节点列表
         List<SysMenu> childList = getChildList(list, t);//通过list.item.parentId == t.id得到
         t.setChildren(childList);
         for (SysMenu tChild : childList)
         {
             if (hasChild(list, tChild))//递归出口,调用getChildList.size() > 0得到
             {
                 recursionFn(list, tChild);//递归子节点
             }
         }
     }

总结层级结构思路:

  1. 获取当前userId所有目录菜单资源
  2. 将其中parent_id = 0的作为各自的根节点
  3. 查找1中parent_id = 2中的根节点id,加到2的子节点中去
  4. 递归3包装子节点,传入的根节id点为当前层id,直到没有子节点为止