当前位置: 首页 > news >正文

SpringBoot 动态路由菜单 权限系统开发 菜单权限 数据库设计 不同角色对应不同权限

介绍

系统中的路由配置可以根据用户的身份、角色或其他权限信息动态生成,而不是固定在系统中。不同的用户根据其权限会看到不同的路由,访问不同的页面。对应各部门不同的权限。

效果

[
    {
        "id": 1,
        "menuName": "用户管理",
        "path": "/user",
        "icon": null,
        "child": [
            {
                "id": 2,
                "menuName": "个人中心",
                "path": "/info",
                "icon": null,
                "child": [
                    {
                        "id": 7,
                        "menuName": "修改密码",
                        "path": "/alterPassword",
                        "icon": null
                    }
                ]
            },
            {
                "id": 3,
                "menuName": "添加用户",
                "path": "/addUser",
                "icon": null
            }
        ]
    },
    {
        "id": 4,
        "menuName": "系统管理",
        "path": "/sysManange",
        "icon": null,
        "child": [
            {
                "id": 5,
                "menuName": "站点配置",
                "path": "/siteConfig",
                "icon": null
            }
        ]
    }
]

用户表设计

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL COMMENT '编号',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

INSERT INTO `user` VALUES (1, 'dpc520');

SET FOREIGN_KEY_CHECKS = 1;

在这里插入图片描述

角色表设计

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (
  `id` int(11) NOT NULL COMMENT '编号',
  `role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '角色名称',
  `role_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '权限字符串',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

INSERT INTO `role` VALUES (1, '超级管理员', 'admin');

SET FOREIGN_KEY_CHECKS = 1;

在这里插入图片描述

菜单表设计

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
  `menu_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '菜单名称',
  `parent_id` int(11) NULL DEFAULT NULL COMMENT '父亲ID',
  `path` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '路由路径',
  `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '图标',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

INSERT INTO `menu` VALUES (1, '用户管理', 0, '/user', NULL);
INSERT INTO `menu` VALUES (2, '个人中心', 1, '/info', NULL);
INSERT INTO `menu` VALUES (3, '添加用户', 1, '/addUser', NULL);
INSERT INTO `menu` VALUES (4, '系统管理', 0, '/sysManange', NULL);
INSERT INTO `menu` VALUES (5, '站点配置', 4, '/siteConfig', NULL);
INSERT INTO `menu` VALUES (7, '修改密码', 2, '/alterPassword', NULL);

SET FOREIGN_KEY_CHECKS = 1;

在这里插入图片描述

用户与角色关联

对应不同用户的身份

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role`  (
  `user_id` int(11) NOT NULL COMMENT '用户id',
  `role_id` int(11) NOT NULL COMMENT '角色id',
  PRIMARY KEY (`user_id`, `role_id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Fixed;

INSERT INTO `user_role` VALUES (1, 1);

SET FOREIGN_KEY_CHECKS = 1;

在这里插入图片描述

角色与菜单关联

对应不同角色查看不同菜单的权限

在这里插入图片描述

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

DROP TABLE IF EXISTS `role_menu`;
CREATE TABLE `role_menu`  (
  `role_id` int(11) NOT NULL COMMENT '角色ID',
  `menu_id` int(11) NOT NULL COMMENT '菜单ID',
  PRIMARY KEY (`role_id`, `menu_id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Fixed;

INSERT INTO `role_menu` VALUES (1, 1);
INSERT INTO `role_menu` VALUES (1, 2);
INSERT INTO `role_menu` VALUES (1, 3);
INSERT INTO `role_menu` VALUES (1, 4);
INSERT INTO `role_menu` VALUES (1, 5);
INSERT INTO `role_menu` VALUES (1, 7);

SET FOREIGN_KEY_CHECKS = 1;

SQL语句

根据用户ID,查出对应的角色,根据角色查出对应的菜单

SELECT m.id ,m.menu_name ,m.parent_id,m.path,m.icon FROM user u
LEFT JOIN user_role ur ON ur.user_id=u.id
LEFT JOIN role r ON ur.role_id=r.id
LEFT JOIN role_menu rm ON  rm.role_id=r.id
LEFT JOIN menu m  ON  rm.menu_id=m.id
WHERE u.id=1 ORDER BY m.parent_id ASC

查出数据
在这里插入图片描述

后端根据id和parent_id进行菜单的匹配


控制器

@RestController
@RequestMapping("/menu")
@RequiredArgsConstructor
public class MenuController {

    private final IMenuService menuService;

    @GetMapping("/getMenu")
    public List<Menu> getMenu(){
        return menuService.getMenuList();
    }
    
}

实体类

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("menu")
public class Menu implements Serializable {

    private static final long serialVersionUID = 1L;

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

    /**
     * 菜单名称
     */
    @TableField("menu_name")
    private String menuName;

    /**
     * 父亲ID
     */
    @TableField("parent_id")
    @JsonIgnore // 不返回该字段
    private Integer parentId;

    /**
     * 路由路径
     */
    @TableField("path")
    private String path;

    /**
     * 菜单图标
     */
    @TableField("icon")
    private String icon;

    /**
     * 子菜单
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @TableField(exist=false)
    List<Menu> child;
    
}

业务层

@Service 
@RequiredArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    private final MenuMapper mapper;

    /**
     * 获取菜单列表
     * @return 返回构建好的菜单列表(包含顶级菜单及其子菜单)
     */
    @Override
    public List<Menu> getMenuList() {
        // 从数据库获取所有菜单列表
        List<Menu> list = mapper.getMenuList();

        // 创建一个返回给前端的菜单列表
        List<Menu> returnList = new ArrayList<Menu>();

        // 遍历数据库中获取的菜单列表
        for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();)
        {
            // 获取当前菜单
            Menu t = iterator.next();

            // 判断是否为顶级菜单(ParentId 为 0)
            if (t.getParentId() == 0)
            {
                // 如果是顶级菜单,查找并设置其子菜单
                recursionFn(list, t);
               
                // 将该菜单加入到返回列表
                returnList.add(t);
            }
        }

        // 返回构建好的菜单列表
        return returnList;
    }

    /**
     * 递归查找并设置子菜单
     * @param list 菜单列表
     * @param t 当前菜单(可能是父菜单)
     */
    private void recursionFn(List<Menu> list, Menu t)
    {
        // 获取当前菜单的所有子菜单
        List<Menu> childList = getChildList(list, t);

        // 设置当前菜单的子菜单
        t.setChild(childList);

        // 遍历子菜单,递归处理每个子菜单的子菜单
        for (Menu tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                // 如果子菜单还有子菜单,递归调用
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 获取某个菜单的所有子菜单
     * @param list 菜单列表
     * @param t 当前菜单(父菜单)
     * @return 当前菜单的子菜单列表
     */
    private List<Menu> getChildList(List<Menu> list, Menu t)
    {
        // 存储当前菜单的子菜单
        List<Menu> tlist = new ArrayList<Menu>();

        // 使用迭代器遍历菜单列表
        Iterator<Menu> it = list.iterator();
        while (it.hasNext())
        {
            // 获取当前菜单
            Menu n = it.next();

            // 如果菜单的 ParentId 等于当前菜单的 ID,表示该菜单是当前菜单的子菜单
            if (n.getParentId() == t.getId())
            {
                // 将子菜单添加到子菜单列表中
                tlist.add(n);
            }
        }

        // 返回子菜单列表
        return tlist;
    }

    /**
     * 判断一个菜单是否有子菜单
     * @param list 菜单列表
     * @param t 当前菜单(父菜单)
     * @return 如果当前菜单有子菜单则返回 true,否则返回 false
     */
    private boolean hasChild(List<Menu> list, Menu t)
    {
        // 如果获取的子菜单列表的大小大于 0,说明当前菜单有子菜单
        return getChildList(list, t).size() > 0;
    }
}

数据层

<select id="getMenuList"  resultMap="menuList">
    SELECT m.id ,m.menu_name ,m.parent_id,m.path,m.icon FROM user u
        LEFT JOIN user_role ur ON ur.user_id=u.id
        LEFT JOIN role r ON ur.role_id=r.id
        LEFT JOIN role_menu rm ON  rm.role_id=r.id
        LEFT JOIN menu m  ON  rm.menu_id=m.id
    WHERE u.id=1 ORDER BY m.parent_id ASC
</select>

<resultMap id="menuList" type="com.role.web.pojo.Menu" autoMapping="true">
    <id property="id" column="id"></id>
    <result property="menuName" column="menu_name"></result>
</resultMap>

相关文章:

  • 量化交易 - 聚宽joinquant - 多因子入门研究 - 源码开源
  • 高效数据拷贝方法总结
  • 第16届蓝桥杯c++省赛c组个人题解
  • 基于spring boot的交通旅游订票系统
  • 输入输出系统(I/O系统)
  • 记一次项目上线404--Nginx配置文件
  • 【mllm】——qnn后端解读
  • Linux多线程同步与互斥:从互斥锁原理到死锁防范的深度实践
  • Tkinter事件与绑定
  • 计算机组成原理笔记(十五)——3.5指令系统的发展
  • 使用FormData格式上传图片
  • zk(Zookeeper)实现分布式锁
  • Java基本数据类型与包装类的区别
  • Linux安装开源版MQTT Broker——EMQX服务器环境从零到一的详细搭建教程
  • Linux驱动开发-网络设备驱动
  • 游戏引擎学习第216天
  • Python 的安装与快速入门
  • 联想电脑开机出现Defalut Boot Device Missing or Boot Failed怎么办
  • nfs共享目录主配置文件权限参数
  • 从“被动跳闸”到“主动预警”:智慧用电系统守护老旧小区安全
  • 《尤物公园》连演8场:观众上台,每一场演出都独一无二
  • 高盛上调A股未来12个月目标点位,沪深300指数潜在回报15%
  • 港理大研究揭示:塑胶废物潜藏微生物群落或引发生态危机
  • 是谁提议特朗普向好莱坞征税?
  • 陕西礼泉一村民被冒名贷款40余万,法院发现涉嫌经济犯罪驳回起诉
  • 媒体:不能让追求升学率,成为高中不双休的借口