按钮级别权限管理数据库设计及后台接口实现
目的:
避免反复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(); }
黄色部分,根据自己后台架构做更改,主要是查询到该用户能操作的菜单项数组。