目的:
避免反复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();
}
黄色部分,根据自己后台架构做更改,主要是查询到该用户能操作的菜单项数组。