SpringBoot不同角色显示不同的菜单

最近准备把之前的博客重写,有时间还是要更新一些博客,防止权重下降,水一水。

通常我们后台有很多不同的角色登录,每个角色不同的权限,这个在 SpringBoot整合Shiro实现权限控制,验证码,记住我 中已经介绍了,这次我们介绍一下,如何根据不同的角色登录显示不同的菜单。

比如我目前只有两个角色,系统管理员和普通用户。

当用户登录后台的时候,通过 ajax 从后台获取菜单列表,redis 做缓存,然后初始化加载。

关于菜单绑定角色,其实也可以菜单绑定权限的。这里为了方便,我们使用使用角色来区分。

如下图,两种角色不同的菜单,至于不同菜单的请求链接,是通过 Shiro 控制权限访问的。

SpringBoot不同角色显示不同的菜单

 

一、数据库设计和数据

1、menu 菜单表

SpringBoot不同角色显示不同的菜单

 

2、role 表

SpringBoot不同角色显示不同的菜单

 

3、role_menu 表

SpringBoot不同角色显示不同的菜单

 

 

二、核心代码

1、实体

  1. package com.liuyanzhao.blog.api.model;
  2. import lombok.Data;
  3. import java.util.List;
  4. /**
  5.  * 菜单
  6.  *
  7.  * @author liuyanzhao
  8.  */
  9. @Data
  10. public class Menu {
  11.     /**
  12.      * 菜单ID
  13.      */
  14.     private Integer id;
  15.     /**
  16.      * 父级菜单ID
  17.      */
  18.     private Integer pid;
  19.     /**
  20.      * 菜单名称
  21.      */
  22.     private String name;
  23.     /**
  24.      * 菜单类型:top_menu, main_menu, admin_menu
  25.      */
  26.     private String type;
  27.     /**
  28.      * 菜单URL
  29.      */
  30.     private String url;
  31.     /**
  32.      * 菜单图标
  33.      */
  34.     private String icon;
  35.     /**
  36.      * 菜单分数,越大排序越前
  37.      */
  38.     private Integer score;
  39.     /**
  40.      * 子菜单Menu列表
  41.      */
  42.     private List<Menu> childMenu;
  43. }

 

2、Controller 层

  1. @GetMapping("/admin/menu/listAdminMenu")
  2. @ResponseBody
  3. public ResultVO listAdminMenu() {
  4.     List<Menu> result;
  5.     //1、判断当前用户的角色
  6.     Subject subject = SecurityUtils.getSubject();
  7.     if(subject.hasRole("ROLE_ADMIN")) {
  8.         //管理员
  9.         result = menuService.listAdminMenuByRole(1);
  10.     } else {
  11.         //普通用户
  12.         result = menuService.listAdminMenuByRole(2);
  13.     }
  14.     if(result == null || result.size() == 0) {
  15.         return new ResultVO().error("菜单为空");
  16.     }
  17.     return new ResultVO().ok(result);
  18. }

 

3、Service 层

  1. @Override
  2.  @Cacheable(value = "menu", key = "'listAdminMenuByRole'+#p0")
  3.  public List<Menu> listAdminMenuByRole(Integer roleId) {
  4.      List<Menu> menuList;
  5.      List<Menu> newMenuList = new ArrayList<>();
  6.      try {
  7.          //1、根据角色获得所有的菜单(包括一级和二级)
  8.          menuList = menuMapper.listMenuByRoleId(roleId);
  9.          for (int i = 0; i < menuList.size(); i++) {
  10.              Menu menu = menuList.get(i);
  11.              List<Menu> childMenuList = new ArrayList<>();
  12.              //2、拼装二级菜单
  13.              if (menu.getPid() == 0) {
  14.                  for (int j = 0; j < menuList.size(); j++) {
  15.                      if (Objects.equals(menu.getId(), menuList.get(j).getPid())) {
  16.                          childMenuList.add(menuList.get(j));
  17.                      }
  18.                  }
  19.                  menu.setChildMenu(childMenuList);
  20.                  newMenuList.add(menu);
  21.              }
  22.          }
  23.      } catch (Exception e) {
  24.          log.error("【后台菜单获取失败】,cause:{}", e);
  25.      }
  26.      return newMenuList;
  27.  }

 

4、Dao 层

MenuMapper.java

  1. List<Menu> listMenuByRoleId(Integer roleId);

 

MenuMapper.xml

  1. <!--从 role_menu 关联表查询-->
  2. <select id="listMenuByRoleId" parameterType="java.lang.Integer"
  3. resultMap="BaseResultMap">
  4.    select menu.* from role_menu, menu
  5.    where role_menu.role_id = #{value} and role_menu.menu_id = menu.id
  6. </select>

 

5、前台页面

head里引入jquery库和自定义js文件

  1. <script src="/components/jquery/dist/jquery.min.js"></script>
  2. <script src="/js/admin/init.js"></script>

 

将模板页面的菜单列表去掉,准备从后台获取,通过js拼装并填充到页面

  1. <ul class="sidebar-menu" data-widget="tree" id="menu-ul">
  2. </ul>

 

init.js

  1. //初始化菜单
  2. $.ajax({
  3.     url: '/admin/menu/listAdminMenu',
  4.     type: 'GET',
  5.     success: function (data) {
  6.         console.log(data);
  7.         if (data.code == 200) {
  8.             //for循环初始化菜单
  9.             var str = '';
  10.             $.each(data.data, function (i, item) {
  11.                 str += '<li class="treeview">';
  12.                 str += '<a href="' + item.url + '">';
  13.                 str += '<i class="' + item.icon + '"></i>';
  14.                 str += '<span>' + item.name + '</span>';
  15.                 if (item.childMenu.length != 0) {
  16.                     str += '<span class="pull-right-container">';
  17.                     str += '    <i class="fa fa-angle-left pull-right"></i>';
  18.                     str += '</span>';
  19.                 }
  20.                 str += '</a>';
  21.                 str += '<ul class="treeview-menu">';
  22.                 if (item.childMenu.length != 0) {
  23.                     $.each(item.childMenu, function (j, item2) {
  24.                         str += '<li><a href="' + item2.url + '">';
  25.                         str += item2.name;
  26.                         str += '</a></li>';
  27.                     })
  28.                 }
  29.                 str += '</ul></li>';
  30.             });
  31.             $("#menu-ul").html(str);
  32.         }
  33.     },
  34.     error: function () {
  35.     }
  36. });

 

 

三、前台调试

一切完毕后,我们启动项目,访问后台页面,打开浏览器的 console

可以看到 ajax 请求返回的数据

SpringBoot不同角色显示不同的菜单

 

二级菜单数据也有

SpringBoot不同角色显示不同的菜单

 

HTML页面也有元素

SpringBoot不同角色显示不同的菜单

 

 

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
言曌

发表评论

:?::razz::sad::evil::!::smile::oops::grin::eek::shock::???::cool::lol::mad::twisted::roll::wink::idea::arrow::neutral::cry::mrgreen:

目前评论:2   其中:访客  2   博主  0

    • avatar 小白

      看了一下,感觉很不错

      • avatar 0.0

        今天刚刚看了权限管理的视频,但是没想到前端怎么设计,很赞!!!