优秀的编程知识分享平台

网站首页 > 技术文章 正文

SpringBoot学习笔记七之菜单维护(springboot菜单权限控制)

nanyue 2024-08-26 17:49:45 技术文章 6 ℃

创建数据库

CREATE TABLE `t_menu` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pid` int(11) DEFAULT NULL,
`name` varchar(200) DEFAULT NULL,
`url` varchar(200) DEFAULT NULL,
`icon` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

添加样例数据

insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('1',NULL,'系统权限菜单','glyphicon
glyphicon-th-list',NULL);
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('2','1',' 控 制 面 板 ','glyphicon
glyphicon-dashboard','main.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('3','1','权限管理','glyphicon glyphicon
glyphicon-tasks',NULL);
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('4','3',' 用 户 维 护 ','glyphicon
glyphicon-user','user/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('5','3',' 角 色 维 护 ','glyphicon
glyphicon-king','role/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('6','3',' 菜 单 维 护 ','glyphicon
glyphicon-lock','permission/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('7','1',' 业 务 审 核 ','glyphicon
glyphicon-ok',NULL);
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('8','7',' 实 名 认 证 审 核 ','glyphicon
glyphicon-check','auth_cert/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('9','7',' 广 告 审 核 ','glyphicon
glyphicon-check','auth_adv/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('10','7',' 项 目 审 核 ','glyphicon
glyphicon-check','auth_project/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('11','1',' 业 务 管 理 ','glyphicon
glyphicon-th-large',NULL);
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('12','11',' 资 质 维 护 ','glyphicon
glyphicon-picture','cert/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('13','11',' 分 类 管 理 ','glyphicon
glyphicon-equalizer','certtype/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('14','11',' 流 程 管 理 ','glyphicon
glyphicon-random','process/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('15','11',' 广 告 管 理 ','glyphicon
glyphicon-hdd','advert/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('16','11',' 消 息 模 板 ','glyphicon
glyphicon-comment','message/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('17','11',' 项 目 分 类 ','glyphicon
glyphicon-list','projectType/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('18','11',' 项 目 标 签 ','glyphicon
glyphicon-tags','tag/index.htm');
insert into `t_menu` (`id`, `pid`, `name`, `icon`, `url`) values('19','1',' 参 数 管 理 ','glyphicon
glyphicon-list-alt','param/index.htm');

在Java类中表示树形结构

在Menu类中使用List

children属性存储当前节点的子节点

为了配合 zTree 所需要添加的属性

pid 属性:找到父节点

name 属性:作为节点名称

icon 属性:当前节点使用的图标

open 属性:控制节点是否默认打开

url 属性:点击节点时跳转的位置

利用逆向工程生成文件,然后添加上面的属性

生成entity需要的文件

添加属性,构造方法和toString和之前一样添加

MenuMapper

MenuMapper.xml

添加service和serviceimpl

实现代码

实现类

创建Handler

完成Handler

更新、删除

保存

获取所有方法

查询所有

继续接着

跳转菜单维护页面,配置文件spring-web-mvc.xml中

新建menu-page.jsp、modal-menu-add.jsp、modal-menu-confirm.jsp

menu-page.jsp页面代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="zh-CN">
<%@include file="/WEB-INF/include-head.jsp"%>
<link rel="stylesheet" href="ztree/zTreeStyle.css"/>
<script type="text/javascript" src="ztree/jquery.ztree.all-3.5.min.js"></script>
<script type="text/javascript" src="crowd/my-menu.js"></script>
<script type="text/javascript">
 
$(function(){
 
// 调用专门封装好的函数初始化树形结构
generateTree();
 
// 给添加子节点按钮绑定单击响应函数
$("#treeDemo").on("click",".addBtn",function(){
 
// 将当前节点的id,作为新节点的pid保存到全局变量
window.pid = this.id;
 
// 打开模态框
$("#menuAddModal").modal("show");
 
return false;
});
 
// 给添加子节点的模态框中的保存按钮绑定单击响应函数
$("#menuSaveBtn").click(function(){
 
// 收集表单项中用户输入的数据
var name = $.trim($("#menuAddModal [name=name]").val());
var url = $.trim($("#menuAddModal [name=url]").val());
 
// 单选按钮要定位到“被选中”的那一个
var icon = $("#menuAddModal [name=icon]:checked").val();
 
// 发送Ajax请求
$.ajax({
"url":"menu/save.json",
"type":"post",
"data":{
"pid": window.pid,
"name":name,
"url":url,
"icon":icon
},
"dataType":"json",
"success":function(response){
var result = response.result;
 
if(result == "SUCCESS") {
layer.msg("操作成功!");
 
// 重新加载树形结构,注意:要在确认服务器端完成保存操作后再刷新
// 否则有可能刷新不到最新的数据,因为这里是异步的
generateTree();
}
 
if(result == "FAILED") {
layer.msg("操作失败!"+response.message);
}
},
"error":function(response){
layer.msg(response.status+" "+response.statusText);
}
});
 
// 关闭模态框
$("#menuAddModal").modal("hide");
 
// 清空表单
// jQuery对象调用click()函数,里面不传任何参数,相当于用户点击了一下
$("#menuResetBtn").click();
});
 
// 给编辑按钮绑定单击响应函数
$("#treeDemo").on("click",".editBtn",function(){
 
// 将当前节点的id保存到全局变量
window.id = this.id;
 
// 打开模态框
$("#menuEditModal").modal("show");
 
// 获取zTreeObj对象
var zTreeObj = $.fn.zTree.getZTreeObj("treeDemo");
 
// 根据id属性查询节点对象
// 用来搜索节点的属性名
var key = "id";
 
// 用来搜索节点的属性值
var value = window.id;
 
var currentNode = zTreeObj.getNodeByParam(key, value);
 
// 回显表单数据
$("#menuEditModal [name=name]").val(currentNode.name);
$("#menuEditModal [name=url]").val(currentNode.url);
 
// 回显radio可以这样理解:被选中的radio的value属性可以组成一个数组,
// 然后再用这个数组设置回radio,就能够把对应的值选中
$("#menuEditModal [name=icon]").val([currentNode.icon]);
 
return false;
});
 
// 给更新模态框中的更新按钮绑定单击响应函数
$("#menuEditBtn").click(function(){
 
// 收集表单数据
var name = $("#menuEditModal [name=name]").val();
var url = $("#menuEditModal [name=url]").val();
var icon = $("#menuEditModal [name=icon]:checked").val();
 
// 发送Ajax请求
$.ajax({
"url":"menu/update.json",
"type":"post",
"data":{
"id": window.id,
"name":name,
"url":url,
"icon":icon
},
"dataType":"json",
"success":function(response){
var result = response.result;
 
if(result == "SUCCESS") {
layer.msg("操作成功!");
 
// 重新加载树形结构,注意:要在确认服务器端完成保存操作后再刷新
// 否则有可能刷新不到最新的数据,因为这里是异步的
generateTree();
}
 
if(result == "FAILED") {
layer.msg("操作失败!"+response.message);
}
},
"error":function(response){
layer.msg(response.status+" "+response.statusText);
}
});
 
// 关闭模态框
$("#menuEditModal").modal("hide");
 
});
 
// 给“×”按钮绑定单击响应函数
$("#treeDemo").on("click",".removeBtn",function(){
 
// 将当前节点的id保存到全局变量
window.id = this.id;
 
// 打开模态框
$("#menuConfirmModal").modal("show");
 
// 获取zTreeObj对象
var zTreeObj = $.fn.zTree.getZTreeObj("treeDemo");
 
// 根据id属性查询节点对象
// 用来搜索节点的属性名
var key = "id";
 
// 用来搜索节点的属性值
var value = window.id;
 
var currentNode = zTreeObj.getNodeByParam(key, value);
 
$("#removeNodeSpan").html("【<i class='"+currentNode.icon+"'></i>"+currentNode.name+"】");
 
return false;
});
 
// 给确认模态框中的OK按钮绑定单击响应函数
$("#confirmBtn").click(function(){
 
$.ajax({
"url":"menu/remove.json",
"type":"post",
"data":{
"id":window.id
},
"dataType":"json",
"success":function(response){
var result = response.result;
 
if(result == "SUCCESS") {
layer.msg("操作成功!");
 
// 重新加载树形结构,注意:要在确认服务器端完成保存操作后再刷新
// 否则有可能刷新不到最新的数据,因为这里是异步的
generateTree();
}
 
if(result == "FAILED") {
layer.msg("操作失败!"+response.message);
}
},
"error":function(response){
layer.msg(response.status+" "+response.statusText);
}
});
 
// 关闭模态框
$("#menuConfirmModal").modal("hide");
});
 
});
 
</script>
<body>
 
<%@ include file="/WEB-INF/include-nav.jsp"%>
<div class="container-fluid">
<div class="row">
<%@ include file="/WEB-INF/include-sidebar.jsp"%>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
 
<div class="panel panel-default">
<div class="panel-heading">
<i class="glyphicon glyphicon-th-list"></i> 权限菜单列表
<div style="float: right; cursor: pointer;" data-toggle="modal"
data-target="#myModal">
<i class="glyphicon glyphicon-question-sign"></i>
</div>
</div>
<div class="panel-body">
<!-- 这个ul标签是zTree动态生成的节点所依附的静态节点 -->
<ul id="treeDemo" class="ztree"></ul>
</div>
</div>
</div>
</div>
</div>
 
<%@include file="/WEB-INF/modal-menu-add.jsp" %>
<%@include file="/WEB-INF/modal-menu-confirm.jsp" %>
<%@include file="/WEB-INF/modal-menu-edit.jsp" %>
</body>
</html>

modal-menu-add.jsp页面代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<div id="menuAddModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">系统弹窗</h4>
</div>
<form>
<div class="modal-body">
请输入节点名称:<input type="text" name="name" /><br />
请输入URL地址:<input type="text" name="url" /><br />
<i class="glyphicon glyphicon-th-list"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-th-list" /> 
 
<i class="glyphicon glyphicon-dashboard"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-dashboard" />  
 
<i class="glyphicon glyphicon glyphicon-tasks"></i>
<input type="radio" name="icon" value="glyphicon glyphicon glyphicon-tasks" />  
 
<i class="glyphicon glyphicon-user"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-user" />  
 
<i class="glyphicon glyphicon-king"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-king" />  
 
<i class="glyphicon glyphicon-lock"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-lock" />  
 
<i class="glyphicon glyphicon-ok"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-ok" />  
 
<i class="glyphicon glyphicon-check"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-check" />  
 
<i class="glyphicon glyphicon-th-large"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-th-large" /> <br />
 
<i class="glyphicon glyphicon-picture"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-picture" />  
 
<i class="glyphicon glyphicon-equalizer"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-equalizer" />  
 
<i class="glyphicon glyphicon-random"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-random" />  
 
<i class="glyphicon glyphicon-hdd"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-hdd" />  
 
<i class="glyphicon glyphicon-comment"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-comment" />  
 
<i class="glyphicon glyphicon-list"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-list" />  
 
<i class="glyphicon glyphicon-tags"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-tags" />  
 
<i class="glyphicon glyphicon-list-alt"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-list-alt" />  
<br />
 
</div>
<div class="modal-footer">
<button id="menuSaveBtn" type="button" class="btn btn-default"><i class="glyphicon glyphicon-plus"></i> 保存</button>
<button id="menuResetBtn" type="reset" class="btn btn-primary"><i class="glyphicon glyphicon-refresh"></i> 重置</button>
</div>
</form>
</div>
</div>
</div>

modal-menu-edit.jsp页面代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<div id="menuEditModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">系统弹窗</h4>
</div>
<form>
<div class="modal-body">
请输入节点名称:<input type="text" name="name" /><br />
请输入URL地址:<input type="text" name="url" /><br />
<i class="glyphicon glyphicon-th-list"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-th-list" /> 
 
<i class="glyphicon glyphicon-dashboard"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-dashboard" />  
 
<i class="glyphicon glyphicon glyphicon-tasks"></i>
<input type="radio" name="icon" value="glyphicon glyphicon glyphicon-tasks" />  
 
<i class="glyphicon glyphicon-user"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-user" />  
 
<i class="glyphicon glyphicon-king"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-king" />  
 
<i class="glyphicon glyphicon-lock"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-lock" />  
 
<i class="glyphicon glyphicon-ok"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-ok" />  
 
<i class="glyphicon glyphicon-check"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-check" />  
 
<i class="glyphicon glyphicon-th-large"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-th-large" /> <br />
 
<i class="glyphicon glyphicon-picture"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-picture" />  
 
<i class="glyphicon glyphicon-equalizer"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-equalizer" />  
 
<i class="glyphicon glyphicon-random"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-random" />  
 
<i class="glyphicon glyphicon-hdd"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-hdd" />  
 
<i class="glyphicon glyphicon-comment"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-comment" />  
 
<i class="glyphicon glyphicon-list"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-list" />  
 
<i class="glyphicon glyphicon-tags"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-tags" />  
 
<i class="glyphicon glyphicon-list-alt"></i>
<input type="radio" name="icon" value="glyphicon glyphicon-list-alt" />  
<br />
 
</div>
<div class="modal-footer">
<button id="menuEditBtn" type="button" class="btn btn-default"><i class="glyphicon glyphicon-edit"></i> 更新</button>
</div>
</form>
</div>
</div>
</div> 


modal-menu-confirm.jsp页面代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<div id="menuConfirmModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">系统弹窗</h4>
</div>
<form>
<div class="modal-body">
您真的要删除<span id="removeNodeSpan"></span>这个节点吗?
</div>
<div class="modal-footer">
<button id="confirmBtn" type="button" class="btn btn-danger"><i class="glyphicon glyphicon-ok"></i> OK</button>
</div>
</form>
</div>
</div>
</div>

创建my-menu.js文件

完成代码

// 声明专门的函数显示确认模态框
function showConfirmModal(roleArray) {
 
// 打开模态框
$("#confirmModal").modal("show");
 
// 清除旧的数据
$("#roleNameDiv").empty();
 
// 在全局变量范围创建数组用来存放角色id
window.roleIdArray = [];
 
// 遍历roleArray数组
for(var i = 0; i < roleArray.length; i++) {
var role = roleArray[i];
var roleName = role.roleName;
$("#roleNameDiv").append(roleName+"<br/>");
 
var roleId = role.roleId;
 
// 调用数组对象的push()方法存入新元素
window.roleIdArray.push(roleId);
}
 
}
 
// 执行分页,生成页面效果,任何时候调用这个函数都会重新加载页面
function generatePage() {
 
// 1.获取分页数据
var pageInfo = getPageInfoRemote();
 
// 2.填充表格
fillTableBody(pageInfo);
 
}
 
// 远程访问服务器端程序获取pageInfo数据
function getPageInfoRemote() {
 
// 调用$.ajax()函数发送请求并接受$.ajax()函数的返回值
var ajaxResult = $.ajax({
"url": "role/get/page/info.json",
"type":"post",
"data": {
"pageNum": window.pageNum,
"pageSize": window.pageSize,
"keyword": window.keyword
},
"async":false,
"dataType":"json"
});
 
console.log(ajaxResult);
 
// 判断当前响应状态码是否为200
var statusCode = ajaxResult.status;
 
// 如果当前响应状态码不是200,说明发生了错误或其他意外情况,显示提示消息,让当前函数停止执行
if(statusCode != 200) {
layer.msg("失败!响应状态码="+statusCode+" 说明信息="+ajaxResult.statusText);
return null;
}
 
// 如果响应状态码是200,说明请求处理成功,获取pageInfo
var resultEntity = ajaxResult.responseJSON;
 
// 从resultEntity中获取result属性
var result = resultEntity.result;
 
// 判断result是否成功
if(result == "FAILED") {
layer.msg(resultEntity.message);
return null;
}
 
// 确认result为成功后获取pageInfo
var pageInfo = resultEntity.data;
 
// 返回pageInfo
return pageInfo;
}
 
// 填充表格
function fillTableBody(pageInfo) {
 
// 清除tbody中的旧的内容
$("#rolePageBody").empty();
 
// 这里清空是为了让没有搜索结果时不显示页码导航条
$("#Pagination").empty();
 
// 判断pageInfo对象是否有效
if(pageInfo == null || pageInfo == undefined || pageInfo.list == null || pageInfo.list.length == 0) {
$("#rolePageBody").append("<tr><td colspan='4' align='center'>抱歉!没有查询到您搜索的数据!</td></tr>");
 
return ;
}
 
// 使用pageInfo的list属性填充tbody
for(var i = 0; i < pageInfo.list.length; i++) {
 
var role = pageInfo.list[i];
 
var roleId = role.id;
 
var roleName = role.name;
 
var numberTd = "<td>"+(i+1)+"</td>";
var checkboxTd = "<td><input id='"+roleId+"' class='itemBox' type='checkbox'></td>";
var roleNameTd = "<td>"+roleName+"</td>";
 
var checkBtn = "<button type='button' class='btn btn-success btn-xs'><i class=' glyphicon glyphicon-check'></i></button>";
 
// 通过button标签的id属性(别的属性其实也可以)把roleId值传递到button按钮的单击响应函数中,在单击响应函数中使用this.id
var pencilBtn = "<button id='"+roleId+"' type='button' class='btn btn-primary btn-xs pencilBtn'><i class=' glyphicon glyphicon-pencil'></i></button>";
 
// 通过button标签的id属性(别的属性其实也可以)把roleId值传递到button按钮的单击响应函数中,在单击响应函数中使用this.id
var removeBtn = "<button id='"+roleId+"' type='button' class='btn btn-danger btn-xs removeBtn'><i class=' glyphicon glyphicon-remove'></i></button>";
 
var buttonTd = "<td>"+checkBtn+" "+pencilBtn+" "+removeBtn+"</td>";
 
var tr = "<tr>"+numberTd+checkboxTd+roleNameTd+buttonTd+"</tr>";
 
$("#rolePageBody").append(tr);
}
 
// 生成分页导航条
generateNavigator(pageInfo);
}
 
// 生成分页页码导航条
function generateNavigator(pageInfo) {
 
// 获取总记录数
var totalRecord = pageInfo.total;
 
// 声明相关属性
var properties = {
"num_edge_entries": 3,
"num_display_entries": 5,
"callback": paginationCallBack,
"items_per_page": pageInfo.pageSize,
"current_page": pageInfo.pageNum - 1,
"prev_text": "上一页",
"next_text": "下一页"
}
 
// 调用pagination()函数
$("#Pagination").pagination(totalRecord, properties);
}
 
// 翻页时的回调函数
function paginationCallBack(pageIndex, jQuery) {
 
// 修改window对象的pageNum属性
window.pageNum = pageIndex + 1;
 
// 调用分页函数
generatePage();
 
// 取消页码超链接的默认行为
return false;
 
}



在include-sidebar.jsp完成跳转

测试下

Tags:

最近发表
标签列表