1.若依后台提供了获取当前登录用户菜单路由的方法,在SysLoginController中
java方法代码如下:
@GetMapping("getRouters")public AjaxResult getRouters(){Long userId = SecurityUtils.getUserId();List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);return AjaxResult.success(menuService.buildMenus(menus));}
代码逻辑是得到当前登录用户userId,根据当前登录用户Id,到sys_menu表中递归遍历用户有权访问的所有菜单,并返回一个JSON结果。
2.我们查一下sys_menu表中的数据,parent_id为0的是第一级菜单,菜单是个树状设计,可以根据parent_id查找子菜单
3.下一步我们想先了解下getRouters接口生成的JSON数据格式,再确定怎么跟我们的菜单格式做匹配,这里有个问题就是getRouters接口是不能在浏览器中直接访问测试的,要先登录,拿到当前用户登录userId,然后按照JWT规范,在Header中加入Token才能正常访问到getRouters接口,我们没法在浏览器中直接调用getRouters接口的,这个问题如何解决呢,有两个方案,方案一是按swagger规范写接口,用swagger方式来做测试,具体可以参考https://doc.ruoyi.vip/ruoyi-cloud/cloud/swagger.html(这个版本是微服务版,仅供参考),方案二是使用postman之类的工具来做测试,方案一要改代码,繁琐一点,我们采用方案二
4.Postman的调用方式,我们用截图稍作说明,我们先实现登录,url地址里面填http://localhost:8080/login,
Headers Content-Type选application/json,

body中参数格式如下
{"username":"admin","password":"admin123"}
点发送时,正常登录的话会返回token值,我们要拿这个token只来测试/getRouters接口,这次测试登录我们拿到的token值是(每次调用的时候token值会不一样):eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImM1OGNjMTI5LWZjMzctNDc0YS04OTkyLTIyYmM2ZTEwZDI0ZiJ9.Jed5Kf6c-HiewxeJY44enCWJbuDkqOfXorAtq4oUCk-yDPQgHexd-OhK-rSRz3l4evAZ9zO_tLE2ELn8n_RQ
5.我们在postman中新建一个Tab栏,来测试/getRouters接口,请求方法改为Get,请求地址填写http://localhost:8080/getRouters,Headers Content-Type选application/json,
Header中新增一行,key中输入”Authorization”,value中输入Bearer+空格+刚才拿到的Token即eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImM1OGNjMTI5LWZjMzctNDc0YS04OTkyLTIyYmM2ZTEwZDI0ZiJ9.Jed5Kf6c-HiewxeJY44enCWJbuDkqOfXorAtq4oUCk-yDPQgHexd-OhK-rSRz3l4evAZ9zOtLE2ELn8n_RQ,完整的value值为:
Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImM1OGNjMTI5LWZjMzctNDc0YS04OTkyLTIyYmM2ZTEwZDI0ZiJ9.Jed5Kf6c-HiewxeJY44enCWJbuDkqOfXorAt_q4oUCk-yDPQgHexd-OhK-rSRz3l4evAZ9zO_tLE2ELn8n_RQ
然后点发送,如下图所示:
6.顺利的话应该可以拿到admin用户可以访问的所有菜单JSON数据,最终拿到的JSON数据如下:
{"msg":"操作成功","code":200,"data":[{"name":"System","path":"/system","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统管理","icon":"system","noCache":false,"link":null},"children":[{"name":"User","path":"user","hidden":false,"component":"system/user/index","meta":{"title":"用户管理","icon":"user","noCache":false,"link":null}},{"name":"Role","path":"role","hidden":false,"component":"system/role/index","meta":{"title":"角色管理","icon":"peoples","noCache":false,"link":null}},{"name":"Menu","path":"menu","hidden":false,"component":"system/menu/index","meta":{"title":"菜单管理","icon":"tree-table","noCache":false,"link":null}},{"name":"Dept","path":"dept","hidden":false,"component":"system/dept/index","meta":{"title":"部门管理","icon":"tree","noCache":false,"link":null}},{"name":"Post","path":"post","hidden":false,"component":"system/post/index","meta":{"title":"岗位管理","icon":"post","noCache":false,"link":null}},{"name":"Dict","path":"dict","hidden":false,"component":"system/dict/index","meta":{"title":"字典管理","icon":"dict","noCache":false,"link":null}},{"name":"Config","path":"config","hidden":false,"component":"system/config/index","meta":{"title":"参数设置","icon":"edit","noCache":false,"link":null}},{"name":"Notice","path":"notice","hidden":false,"component":"system/notice/index","meta":{"title":"通知公告","icon":"message","noCache":false,"link":null}},{"name":"Log","path":"log","hidden":false,"redirect":"noRedirect","component":"ParentView","alwaysShow":true,"meta":{"title":"日志管理","icon":"log","noCache":false,"link":null},"children":[{"name":"Operlog","path":"operlog","hidden":false,"component":"monitor/operlog/index","meta":{"title":"操作日志","icon":"form","noCache":false,"link":null}},{"name":"Logininfor","path":"logininfor","hidden":false,"component":"monitor/logininfor/index","meta":{"title":"登录日志","icon":"logininfor","noCache":false,"link":null}}]}]},{"name":"Monitor","path":"/monitor","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统监控","icon":"monitor","noCache":false,"link":null},"children":[{"name":"Online","path":"online","hidden":false,"component":"monitor/online/index","meta":{"title":"在线用户","icon":"online","noCache":false,"link":null}},{"name":"Job","path":"job","hidden":false,"component":"monitor/job/index","meta":{"title":"定时任务","icon":"job","noCache":false,"link":null}},{"name":"Druid","path":"druid","hidden":false,"component":"monitor/druid/index","meta":{"title":"数据监控","icon":"druid","noCache":false,"link":null}},{"name":"Server","path":"server","hidden":false,"component":"monitor/server/index","meta":{"title":"服务监控","icon":"server","noCache":false,"link":null}},{"name":"Cache","path":"cache","hidden":false,"component":"monitor/cache/index","meta":{"title":"缓存监控","icon":"redis","noCache":false,"link":null}}]},{"name":"Tool","path":"/tool","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统工具","icon":"tool","noCache":false,"link":null},"children":[{"name":"Build","path":"build","hidden":false,"component":"tool/build/index","meta":{"title":"表单构建","icon":"build","noCache":false,"link":null}},{"name":"Gen","path":"gen","hidden":false,"component":"tool/gen/index","meta":{"title":"代码生成","icon":"code","noCache":false,"link":null}},{"name":"Swagger","path":"swagger","hidden":false,"component":"tool/swagger/index","meta":{"title":"系统接口","icon":"swagger","noCache":false,"link":null}}]},{"name":"Http://ruoyi.vip","path":"http://ruoyi.vip","hidden":false,"component":"Layout","meta":{"title":"若依官网","icon":"guide","noCache":false,"link":"http://ruoyi.vip"}}]}
7.以一个菜单为例,我们稍微分析下拿到的JSON数据
"name":"System","path":"/system","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统管理","icon":"system","noCache":false,"link":null},"children":[...]
name菜单英文名, path 路由位置,hidden是否隐藏,redirect默认跳转路由,component使用组件,
meta.title菜单中文名称,meta.icon:菜单图标,children[]子菜单数组。
8.对比下我们现在从config/config.js中拿到的菜单格式
{name: 'table-list',icon: 'smile',path: '/list/table-list',component: './list/table-list',},
config.js中的菜单只有4个属性,name,icon,path,component,跟我们从数据库中拿到的菜单有部分不太一样,我们的icon在meta.icon中,我们的name要取中文显示,应该用meta.title,这个属性值的转换我们就不改后台的代码了,直接在前台做转换,不过由于是一个树状结构,要用到递归,有一点点麻烦,下一步我们先封装请求菜单的service方法。
