按钮级别权限管理数据库设计及后台接口实现

目的:

  避免反复coding ,将此作为一个 component ,任何项目只需复制起表结构和后台代码即可使用,前端样式可根据项目需求做改动,只需调用后台提供的接口即可。

语言:java

数据库:mysql

数据库设计: 一共 5 张表 ,分别是用户表(t_sec_user),角色表(t_sec_role),菜单表(t_sec_menu),用户角色关系表(t_sec_re_user_role) , 角色菜单关系表(t_sec_re_role_menu)。

这里的逻辑主要是 :一个用户能够操作哪些菜单 作为一个‘组' ,'组'在这里的定义是 对菜单而言的 。对用户而言,假设 n个的用户都是很奇怪的 ,他们都想拥有不同的操作菜单。作为开发人员的我们,对于这种想法完全可以不用管。在我们心中 不管用户数量再多,我们都能用一个规则去划分用户类别,在同一个类别的用户  所操作的菜单是一样的 。简单理解 就是 菜单是小兵,角色是军队的头衔 ,用户 就是可以赋予这些头衔的人类。用户能够控制哪些小兵,是要看他是怎样的头衔(角色)。

建表sql 如下:

  1 /*
  2 Navicat MySQL Data Transfer
  3 
  4 Source Server         : 127.0.0.1mysql
  5 Source Server Version : 50519
  6 Source Host           : localhost:3306
  7 Source Database       : pms
  8 
  9 Target Server Type    : MYSQL
 10 Target Server Version : 50519
 11 File Encoding         : 65001
 12 
 13 Date: 2017-08-13 00:23:56
 14 */
 15 
 16 SET FOREIGN_KEY_CHECKS=0;
 17 
 18 -- ----------------------------
 19 -- Table structure for t_sec_menu
 20 -- ----------------------------
 21 DROP TABLE IF EXISTS `t_sec_menu`;
 22 CREATE TABLE `t_sec_menu` (
 23   `id` varchar(128) NOT NULL,
 24   `name` varchar(128) DEFAULT NULL COMMENT '菜单名',
 25   `display_name` varchar(128) DEFAULT NULL COMMENT '菜单展示名',
 26   `router` varchar(1024) DEFAULT NULL COMMENT '前端跳转路由',
 27   `params` varchar(4096) DEFAULT NULL COMMENT '参数',
 28   `active` decimal(1,0) DEFAULT NULL COMMENT '是否启用',
 29   `read_only` decimal(1,0) DEFAULT NULL COMMENT '是否只读 1 只读 ',
 30   `parent` varchar(128) DEFAULT NULL COMMENT '父级id',
 31   `sence` varchar(128) DEFAULT NULL COMMENT '场景',
 32   `m_icon` varchar(128) DEFAULT NULL COMMENT '图标样式',
 33   `note` varchar(1024) DEFAULT NULL COMMENT '备注',
 34   `seq` int(38) DEFAULT NULL COMMENT '序号',
 35   `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
 36   `create_user` varchar(128) DEFAULT NULL COMMENT '创建用户',
 37   `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',
 38   `update_user` varchar(128) DEFAULT NULL COMMENT '修改用户',
 39   `delete_flag` decimal(1,0) DEFAULT NULL COMMENT '删除标志',
 40   PRIMARY KEY (`id`)
 41 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单项';
 42 
 43 -- ----------------------------
 44 -- Records of t_sec_menu
 45 -- ----------------------------
 46 
 47 -- ----------------------------
 48 -- Table structure for t_sec_re_role_menu
 49 -- ----------------------------
 50 DROP TABLE IF EXISTS `t_sec_re_role_menu`;
 51 CREATE TABLE `t_sec_re_role_menu` (
 52   `id` varchar(128) NOT NULL,
 53   `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
 54   `create_user` varchar(128) DEFAULT NULL COMMENT '创建用户',
 55   `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',
 56   `update_user` varchar(128) DEFAULT NULL COMMENT '修改用户',
 57   `delete_flag` decimal(1,0) DEFAULT NULL COMMENT '删除标志',
 58   `role_id` varchar(128) DEFAULT NULL COMMENT '角色id',
 59   `menu_id` varchar(128) DEFAULT NULL COMMENT '菜单id',
 60   PRIMARY KEY (`id`)
 61 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色菜单关系表';
 62 
 63 -- ----------------------------
 64 -- Records of t_sec_re_role_menu
 65 -- ----------------------------
 66 
 67 -- ----------------------------
 68 -- Table structure for t_sec_re_user_role
 69 -- ----------------------------
 70 DROP TABLE IF EXISTS `t_sec_re_user_role`;
 71 CREATE TABLE `t_sec_re_user_role` (
 72   `id` varchar(128) NOT NULL,
 73   `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
 74   `create_user` varchar(128) DEFAULT NULL COMMENT '创建用户',
 75   `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',
 76   `update_user` varchar(128) DEFAULT NULL COMMENT '修改用户',
 77   `delete_flag` decimal(1,0) DEFAULT NULL COMMENT '删除标志',
 78   `role_id` varchar(128) DEFAULT NULL COMMENT '角色 id',
 79   `user_id` varchar(128) DEFAULT NULL COMMENT '用户id',
 80   PRIMARY KEY (`id`)
 81 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户角色关联表';
 82 
 83 -- ----------------------------
 84 -- Records of t_sec_re_user_role
 85 -- ----------------------------
 86 
 87 -- ----------------------------
 88 -- Table structure for t_sec_role
 89 -- ----------------------------
 90 DROP TABLE IF EXISTS `t_sec_role`;
 91 CREATE TABLE `t_sec_role` (
 92   `id` varchar(128) NOT NULL,
 93   `name` varchar(128) DEFAULT NULL COMMENT '角色名',
 94   `note` varchar(2048) DEFAULT NULL COMMENT '备注信息',
 95   `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
 96   `create_user` varchar(128) DEFAULT NULL COMMENT '创建用户',
 97   `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',
 98   `update_user` varchar(128) DEFAULT NULL COMMENT '修改用户',
 99   `delete_flag` decimal(1,0) DEFAULT NULL COMMENT '删除标志',
100   PRIMARY KEY (`id`)
101 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色';
102 
103 -- ----------------------------
104 -- Records of t_sec_role
105 -- ----------------------------
106 
107 -- ----------------------------
108 -- Table structure for t_sec_user
109 -- ----------------------------
110 DROP TABLE IF EXISTS `t_sec_user`;
111 CREATE TABLE `t_sec_user` (
112   `id` varchar(128) NOT NULL,
113   `name` varchar(128) DEFAULT NULL COMMENT '登陆用户名',
114   `password` varchar(1024) DEFAULT NULL COMMENT '密码',
115   `display_name` varchar(128) DEFAULT NULL COMMENT '前台展示名',
116   `telephone` varchar(64) DEFAULT NULL COMMENT '办公电话',
117   `mobile` varchar(64) DEFAULT NULL COMMENT '移动电话',
118   `fax` varchar(64) DEFAULT NULL COMMENT '传真',
119   `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
120   `create_user` varchar(128) DEFAULT NULL COMMENT '创建用户',
121   `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修改时间',
122   `pwd_update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '最近密码更改时间',
123   `update_user` varchar(128) DEFAULT NULL COMMENT '修改用户',
124   `delete_flag` decimal(1,0) DEFAULT NULL COMMENT '删除标志',
125   PRIMARY KEY (`id`)
126 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
127 
128 -- ----------------------------
129 -- Records of t_sec_user
130 -- ----------------------------

后台结构 这里 我使用脚手架自动生成,详细代码就不展现了,无非是数据的增删改查,主要结构如下,

在用户登陆时,将用户信息放入session 中,登陆成功后,发出获取菜单请求,后台取出session 中的用户信息(用到的是 用户id),根据用户的id 关联查询出,该用户能操作的所有菜单项 。这时候需要整合下 菜单项,因为如果是一次性查出所有菜单,结果是一个List ,并不是一个树状菜单 ,因为菜单有一个parent 字段表示该菜单的父级菜单, 如果parent为null 那么这就是一个顶级菜单,不为空则为子菜单, 这里的整合无非就是 将一个数组,整合成一个树,这个算法很简单,

 @Override
    public List<Menu> getAllMenuByUser(String id) {
        String allMenuSql = getAllMenuSql();
        StringBuffer sql = new StringBuffer() ;
        sql.append(allMenuSql) ;
        List params = new ArrayList();
        params.add(id);
        //查询到该用户能操作的菜单项数组
        List<Menu> allMenus = getDataBase().query4Model(sql.toString(),Menu.class ,params.toArray());
        
        List<Menu> tmpMenus = new ArrayList(); //存放菜单树
        if (allMenus != null) {
            for (int i = 0,length = allMenus.size(); i <length; i++) {
                Menu menu = allMenus.get(i) ;
                if (StringUtils.isEmpty(menu.getParent())){
                    //如果没有父亲 那自己就是 最上层父级菜单
                    List<Menu> childMenus = findChildren(menu,allMenus);
                    if (childMenus!=null && childMenus.size() >0){
                        menu.setChildren(childMenus);
                    }
                    tmpMenus.add(menu);
                }
            }
        }


        return tmpMenus ;

    }
/**
     * 递归找孩子
     * @param menu
     * @param allMenus
     * @return
     */
    private  List<Menu> findChildren(Menu menu, List<Menu> allMenus) {
        if (menu.getChildren() == null) {
            menu.setChildren(new ArrayList<Menu>());
        }
        for (int i = 0,length = allMenus.size(); i < length; i++) {
            Menu child = allMenus.get(i) ;

            if (!StringUtils.isEmpty(child.getParent())){
                if (child.getParent().equals(menu.getId())){
                    List<Menu> childrenMenu = findChildren(child,allMenus);
                    if (childrenMenu!=null && childrenMenu.size() >0){
                        child.setChildren(childrenMenu);
                    }
                    menu.getChildren().add(child);
                }
            }
        }
        return menu.getChildren();
    }

 黄色部分,根据自己后台架构做更改,主要是查询到该用户能操作的菜单项数组。

原文地址:https://www.cnblogs.com/hsc13-lxy14/p/7344479.html