(1)SysLoginController.getRouters
@GetMapping("getRouters")
public AjaxResult getRouters()
{
// 从SecurityContextHolder中获取LoginUser,从LoginUser中获取userId
Long userId = SecurityUtils.getUserId();
// 根据userId获取菜单,并构造成树状结构
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
// 将树状菜单转换为前端所需的结构
List<RouterVo> routerVoList = menuService.buildMenus(menus);
return AjaxResult.success(routerVoList);
}
(2)SysMenuServiceImpl.selectMenuTreeByUserId
public List<SysMenu> selectMenuTreeByUserId(Long userId)
{
List<SysMenu> menus = null;
if (SecurityUtils.isAdmin(userId))
{
// 如果是管理员,则查询出所有菜单
menus = menuMapper.selectMenuTreeAll();
}
else
{
// 查询出该用户拥有的菜单(当该用户关联多个角色时,菜单取所有角色的并集)
menus = menuMapper.selectMenuTreeByUserId(userId);
}
// 将查询出的菜单构造成菜单树(注意这里传入的parentId为0)
return getChildPerms(menus, 0);
}
(3)SysMenuServiceImpl.getChildPerms
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();
// 遍历list,找出父id是parentId的菜单/目录(这里parentId为0)
if (t.getParentId() == parentId)
{
// 菜单t的父id是0,递归构造菜单t的子菜单
recursionFn(list, t);
// 将t添加到returnList中(有多少个一级菜单/目录,returnList最终就有多少个元素)
returnList.add(t);
}
}
return returnList;
}
(4)SysMenuServiceImpl.recursionFn
private void recursionFn(List<SysMenu> list, SysMenu t)
{
// 获取菜单t下的所有直接子菜单
List<SysMenu> childList = getChildList(list, t);
// 设置t的子菜单
t.setChildren(childList);
for (SysMenu tChild : childList)
{
// 判断菜单tChild是否也有子菜单
if (hasChild(list, tChild))
{
// 递归构造菜单tChild的子菜单
recursionFn(list, tChild);
}
}
}
(5)SysMenuServiceImpl.getChildList
private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t)
{
// 子菜单集合
List<SysMenu> tlist = new ArrayList<SysMenu>();
Iterator<SysMenu> it = list.iterator();
while (it.hasNext())
{
SysMenu n = (SysMenu) it.next();
// 遍历list,找到菜单t的所有直接子菜单
if (n.getParentId().longValue() == t.getMenuId().longValue())
{
tlist.add(n);
}
}
return tlist;
}
(6)SysMenuServiceImpl.hasChild
{
// 判断t下是否有子菜单
return getChildList(list, t).size() > 0;
}
(7)SysMenuServiceImpl.buildMenus
// RouterVo就是前端所需的菜单结构
public List<RouterVo> buildMenus(List<SysMenu> menus)
{
List<RouterVo> routers = new LinkedList<RouterVo>();
for (SysMenu menu : menus)
{
RouterVo router = new RouterVo();
// 1:隐藏 0:显示
router.setHidden("1".equals(menu.getVisible()));
// 设置路由名字(注意不是菜单名称)
router.setName(getRouteName(menu));
// 设置路由地址(逻辑地址:地址栏中显示的地址)
router.setPath(getRouterPath(menu));
// 设置组件地址(物理地址:index.vue文件所在的位置)
router.setComponent(getComponent(menu));
// 访问路由的默认传递参数,如 {"id": 1, "name": "ry"}
router.setQuery(menu.getQuery());
// 其他元素,如title(菜单/目录名称)、icon(目录/菜单图标)、noCache(是否缓存页面)等
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
List<SysMenu> cMenus = menu.getChildren();
if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
{
// true:总是显示
router.setAlwaysShow(true);
// 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
router.setRedirect("noRedirect");
// 递归处理子菜单
router.setChildren(buildMenus(cMenus));
}
// 略
routers.add(router);
}
return routers;
}