用户动态权限菜单管理简单实现方式
1.说明
根据用户角色的权限进行菜单管理,根据拥有的权限访问范围内的菜单
2.数据库表设计
2.1用户表
CREATE TABLE `sys_user` ( `uid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户Id', `username` varchar(100) NOT NULL COMMENT '用户名', `password` varchar(100) NOT NULL COMMENT '密码', `phone` varchar(11) DEFAULT NULL COMMENT '手机', `email` varchar(100) DEFAULT NULL COMMENT '邮箱', `locked` int(1) DEFAULT NULL COMMENT '账号是否被锁定', PRIMARY KEY (`uid`), UNIQUE KEY `uk_u_1` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
2.2角色表
Create Table CREATE TABLE `sys_role` ( `roleId` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色Id', `roleName` varchar(100) DEFAULT NULL COMMENT '角色名称', `roleDesc` varchar(100) DEFAULT NULL COMMENT '角色描述', `role` varchar(100) DEFAULT NULL COMMENT '角色标志', PRIMARY KEY (`roleId`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
2.3权限表
Create Table CREATE TABLE `sys_permission` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限Id', `pdesc` varchar(100) DEFAULT NULL COMMENT '权限描述', `name` varchar(100) DEFAULT NULL COMMENT '权限名称', `menuId` int(11) DEFAULT NULL COMMENT '菜单Id', PRIMARY KEY (`id`), KEY `p_fk_1` (`menuId`), CONSTRAINT `p_fk_1` FOREIGN KEY (`menuId`) REFERENCES `sys_menu` (`menuId`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8
2.4菜单表
CREATE TABLE `sys_menu` ( `menuId` int(11) NOT NULL AUTO_INCREMENT COMMENT '菜单Id', `parentId` int(11) DEFAULT NULL COMMENT '上级Id', `menuName` varchar(100) DEFAULT NULL COMMENT '菜单名称', `menuUrl` varchar(100) DEFAULT NULL COMMENT '菜单链接', `menuStatus` varchar(10) DEFAULT NULL COMMENT '菜单状态', `level` int(4) NOT NULL COMMENT '菜单等级', PRIMARY KEY (`menuId`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8
3.代码
3.1设计思路
本次菜单只有两级,所有采用hashmap方式解决,Map<String, List<SysMenu>>,key值为父菜单,value为子菜单集合.
dao层:根据用户登录的session值取到用户id,根据用户id关联查询出所有菜单列表(包括父子菜单)
service层:双层for循环,判断menuById.get(I).getParentid() == 0且menuById.get(I).getMenuid() == menuById.get(J).getParentid();这样就可以得到父菜单及其子菜单,
将子菜单对象放在list集合中,在将父菜单的name作为key,子菜单的集合作为value存入map中;如图可以看出端倪:
servlet层:获取登陆后session中保存的uid,调用service方法.返回主页面;
前端:el表达式,双重foreach,动态展示各父菜单及子菜单
3.2.dao层
QueryRunner queryRunner = new QueryRunner(ComboPooledDataSourceUtil.getDataSourceByxml());
List<Object> param = new ArrayList<>();
StringBuffer buffer = new StringBuffer();
@Override public List<SysMenu> findMenuById(Integer uid) { //清空list和stringbuffer delListAndStringBuf(); buffer.append("SELECT m.*"); buffer.append(" FROM `sys_user` u"); buffer.append(" INNER JOIN `sys_user_role` ur"); buffer.append(" ON u.`uid`=ur.`userId`"); buffer.append(" INNER JOIN `sys_role` r"); buffer.append(" ON ur.`roleId`=r.`roleId`"); buffer.append(" INNER JOIN `sys_role_permission` rp"); buffer.append(" ON r.`roleId`=rp.`roleId`"); buffer.append(" INNER JOIN `sys_permission` p"); buffer.append(" ON rp.`permissionId`=p.`id`"); buffer.append(" JOIN`sys_menu` m"); buffer.append(" ON m.`menuId`=p.`menuId`"); buffer.append(" WHERE m.`menuStatus`=0"); buffer.append(" AND u.`locked`=0"); buffer.append(" AND u.`uid`=?"); param.add(uid); //list集合转化为数组 Object[] objects = param.toArray(); List<SysMenu> menu =null; // try { menu = queryRunner.query(buffer.toString(), new BeanListHandler<SysMenu>(SysMenu.class), objects); } catch (SQLException e) { } return menu; }
//清空list和stringbuffer
public void delListAndStringBuf(){
param.clear();
buffer.delete(0,buffer.length());
}
3.3.service层
@Override public Map<String, List<SysMenu>> menus(Integer uid) { //key为父菜单,value为父菜单下的子菜单集合 Map<String, List<SysMenu>> menus = new HashMap<>(); //父子菜单集合 List<SysMenu> menuById = permissionMenuDao.findMenuById(uid); for (int i = 0; i < menuById.size(); i++) { //子菜单集合,外层循环时为另外一个父菜单的子菜单 List<SysMenu> childMenu = new ArrayList<>(); for (int j = 0; j < menuById.size(); j++) { //SysMenu创建对象,二次循环时为同父菜单下的另外一个子菜单对象 SysMenu sm = new SysMenu(); if (menuById.get(i).getParentid() == 0 & menuById.get(i).getMenuid() == menuById.get(j).getParentid()) { sm.setMenuname(menuById.get(j).getMenuname()); sm.setMenuurl(menuById.get(j).getMenuurl()); sm.setMenuid(menuById.get(j).getMenuid()); // childMenu对象 childMenu.add(sm); //将父菜单以及对应的子菜单集合封装在map里面 menus.put(menuById.get(i).getMenuname(), childMenu); } } } return menus; }
3.4servlet层
@WebServlet("/main/") public class PermissionMenuServlet extends BaseServlet { PermissionMenuService service=new PermissionMenuServiceImpl(); public String index (HttpServletRequest request, HttpServletResponse response){ HttpSession session = request.getSession(); SysUser user= (SysUser) session.getAttribute("user"); System.out.println("user:"+user.getUid()); Map<String, List<SysMenu>> menus = service.menus(user.getUid()); request.setAttribute("menus",menus); return "/WEB-INF/views/main/mainpage.jsp"; } }
4.0 前端
<aside class="Hui-aside"> <div class="menu_dropdown bk_2"> <%--父菜单--%> <c:forEach items="${requestScope.menus}" var="mainMenu"> <dl id="menu-article"> <dt><i class="Hui-iconfont"></i> ${mainMenu.key}<i class="Hui-iconfont menu_dropdown-arrow"></i></dt> <dd> <%--子菜单--%> <c:forEach items="${mainMenu.value}" var="childMenu"> <ul> <li><a data-href=${childMenu.menuurl} data-title=${childMenu.menuname} href="javascript:void(0)">${childMenu.menuname}</a></li> </ul> </c:forEach> </dd> </dl> </c:forEach> </div> </aside>
备注:登录的service层需加入在session中加入uid
request.getSession().setAttribute("user",user);