四、菜单管理(1) 您所在的位置:网站首页 menu标签定义菜单列表 四、菜单管理(1)

四、菜单管理(1)

2023-12-08 04:23| 来源: 网络整理| 查看: 265

文章目录 一、菜单管理设计说明1.1 业务设计说明1.2 原型设计说明1.3 API设计说明 二、菜单管理列表页面呈现2.1 业务时序分析2.2 服务端实现2.2.1 Controller实现 2.3 客户端实现2.3.1 首页菜单事件处理2.3.2 菜单列表页面 三、菜单管理列表数据呈现3.1 数据架构分析3.2 服务端关键业务及代码实现3.2.1 Dao接口实现3.2.2 Mapper文件实现3.2.3 Service接口及实现类3.2.4 Controller类实现 3.3 客户端关键业务及代码实现3.3.1 菜单列表信息呈现 四、菜单管理删除操作实现4.1 业务时序分析4.2 服务端关键业务及代码实现4.2.1 Dao接口实现4.2.2 Mapper文件实现4.2.3 Service接口及实现类4.2.4 Controller类实现 4.3 客户端关键业务及代码实现4.3.1 菜单列表页面事件处理

在这里插入图片描述

一、菜单管理设计说明 1.1 业务设计说明

菜单管理又称为资源管理,是系统资源对外的表现形式。本模块主要是实现对菜单进行添加、修改、查询、删除等操作。其表设计语句如下:

CREATE TABLE `sys_menus` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL COMMENT '资源名称', `url` varchar(200) DEFAULT NULL COMMENT '资源URL', `type` int(11) DEFAULT NULL COMMENT '类型 1:菜单 2:按钮', `sort` int(11) DEFAULT NULL COMMENT '排序', `note` varchar(100) DEFAULT NULL COMMENT '备注', `parentId` int(11) DEFAULT NULL COMMENT '父菜单ID,一级菜单为0', `permission` varchar(500) DEFAULT NULL COMMENT '授权(如:sys:user:create)', `createdTime` datetime DEFAULT NULL COMMENT '创建时间', `modifiedTime` datetime DEFAULT NULL COMMENT '修改时间', `createdUser` varchar(20) DEFAULT NULL COMMENT '创建用户', `modifiedUser` varchar(20) DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='资源管理';

菜单表与角色表是 多对多 的关系,在表设计时,多对多关系通常由中间表(关系表)进行维护,如图所示: 在这里插入图片描述 基于角色菜单表的设计,其角色和菜单对应的关系数据要存储到关系表中,其具体存储形式,如图所示: 在这里插入图片描述 菜单与角色的关系表脚本设计如下:

CREATE TABLE `sys_role_menus` ( `id` int(11) NOT NULL AUTO_INCREMENT, `role_id` int(11) DEFAULT NULL COMMENT '角色ID', `menu_id` int(11) DEFAULT NULL COMMENT 'ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='角色与菜单对应关系'; 1.2 原型设计说明

基于用户需求,实现菜单静态页面(html/css/js),通过静态页面为用户呈现菜单模块的基本需求实现。 当在主页左侧菜单栏,点击菜单管理时,在主页内容呈现区,呈现菜单列表页面,如图所示:在这里插入图片描述 当在菜单列表页面点击添加按钮时,异步加载菜单编辑页面,并在列表内容呈现区,呈现菜单编辑页面,如图所示:

在这里插入图片描述 在菜单编辑页面选择上级菜单时,异步加载菜单信息,并以树结构的形式呈现上级菜单,如图所示: 在这里插入图片描述 说明: 假如客户对此原型进行了确认,后续则可以基于此原型进行研发。

1.3 API设计说明

菜单管理业务后台API分层架构及调用关系如图所示: 在这里插入图片描述 说明:分层目的主要将复杂问题简单化,实现各司其职,各尽所能。

二、菜单管理列表页面呈现 2.1 业务时序分析

菜单管理页面的加载过程,其时序分析如图所示: 在这里插入图片描述

2.2 服务端实现 2.2.1 Controller实现 业务描述与设计实现

基于菜单管理的请求业务,在PageController中添加doMenuUI方法,用于返回菜单列表页面。

关键代码设计与实现

第一步:在PageController中定义返回菜单列表的方法。代码如下:

@RequestMapping("menu/menu_list") public String doMenuUI() { return "sys/menu_list"; }

第二步:在PageController中基于rest风格的url方式优化返回UI页面的方法。找出共性进行提取,例如:

@RequestMapping("{module}/{moduleUI}") public String doModuleUI(@PathVariable String moduleUI) { return "sys/"+moduleUI; } 2.3 客户端实现 2.3.1 首页菜单事件处理 业务描述与设计实现

首先准备菜单列表页面(/templates/pages/sys/menu_list.html),然后在starter.html页面中点击菜单管理时异步加载菜单列表页面。

关键代码设计与实现

找到项目中的starter.html页面,页面加载完成以后,注册菜单管理项的点击事件,当点击菜单管理时,执行事件处理函数。关键代码如下:

$(function(){ … doLoadUI("load-menu-id","menu/menu_list") })

说明: 对于doLoadUI函数,假如在starter.html中已经定义,则无需再次定义.

function doLoadUI(id,url){ $("#"+id).click(function(){ $("#mainContentId").load(url); }); }

其中,load函数为jquery中的ajax异步请求函数。

2.3.2 菜单列表页面 业务描述与设计实现

本页面呈现菜单信息时要以树结构形式进行呈现。此树结构会借助jquery中的treeGrid插件进行实现,所以在菜单列表页面需要引入treeGrid相关JS。但是,具体的treeGrid怎么用可自行在网上进行查询(已比较成熟)。

关键代码设计与实现:

关键JS引入(menu_list.html),代码如下:

三、菜单管理列表数据呈现 3.1 数据架构分析

菜单列表页面加载完成,启动菜单数据异步加载操作,本次菜单列表页面要呈现菜单以及2息,其数据查询时,数据的封装及传递过程,如图所示: 在这里插入图片描述 说明:本模块将从数据库查询到的菜单数据封装到map对象,一行记录一个map对象,其中key为表中的字段(列)名,值为字段(列)对应的值。

数据加载过程其时序分析,如图所示: 在这里插入图片描述

3.2 服务端关键业务及代码实现 3.2.1 Dao接口实现 业务描述及设计实现

通过数据层对象,基于业务层参数,查询菜单以及上级菜单信息(要查询上级菜单名)。

关键代码分析及实现

第一步:定义数据层接口对象,通过此对象实现数据库中菜单数据的访问操作。关键代码如下:

@Mapper public interface SysMenuDao { }

第二步:在SysMenuDao接口中添加findObjects方法,基于此方法实现菜单数据的查询操作。代码如下:

List findObjects();

说明: 一行记录映射为一个map对象,多行存储到list。 思考: 这里为什么使用map存储数据,有什么优势劣势?

3.2.2 Mapper文件实现 业务描述及设计实现

基于Dao接口创建映射文件,在此文件中通过相关元素(例如select)描述要执行的数据操作。

关键代码设计及实现

第一步:在映射文件的设计目录中添加SysMenuMapper.xml映射文件,代码如下:

第二步:在映射文件中添加id为findObjects的元素,实现菜单记录查询。我们要查询所有菜单以及菜单对应的上级菜单名称。关键代码如下:

select c.*,( select p.name from sys_menus p where c.parentId=p.id ) parentName from sys_menus c

说明:自关联查询分析,如图所示: 在这里插入图片描述

3.2.3 Service接口及实现类 业务描述与设计实现

在菜单查询中,业务层对象主要是借助数据层对象完成菜单数据的查询。后续还可以基于AOP对数据进行缓存,记录访问日志等。

关键代码设计及实现

第一步:定义菜单业务接口及方法,暴露外界对菜单业务数据的访问,其代码参考如下:

package com.cy.pj.sys.service; public interface SysMenuService { List findObjects(); }

第二步:定义菜单业务接口实现类,并添加菜单业务数据对应的查询操作实现,其代码参考如下:

package com.cy.pj.sys.service.impl; @Service public class SysMenuServiceImpl implements SysMenuService{ @Autowired private SysMenuDao sysMenuDao; @Override public List findObjects() { List list= sysMenuDao.findObjects(); if(list==null||list.size()==0) throw new ServiceException("没有对应的菜单信息"); return list; } 3.2.4 Controller类实现 业务描述与设计实现

控制层对象主要负责请求和响应数据的处理,例如,本模块通过业务层对象执行业务逻辑,再通过VO对象封装响应结果(主要对业务层数据添加状态信息),最后将响应结果转换为JSON格式的字符串响应到客户端。

关键代码设计与实现

定义Controller类,并将此类对象使用Spring框架中的@Controller注解进行标识,表示此类对象要交给Spring管理。然后基于@RequestMapping注解为此类定义根路径映射。代码参考如下:

package com.cy.pj.sys.controller; @RequestMapping("/menu/") @RestController public class SysMenuController { }

说明: 这里的@RestController注解等效于在类上同时添加了@Controller和 @ResponseBody注解. 在Controller类中添加菜单查询处理方法,代码参考如下:

@RequestMapping("doFindObjects") public JsonResult doFindObjects() { return new JsonResult(sysMenuService.findObjects()); } 3.3 客户端关键业务及代码实现 3.3.1 菜单列表信息呈现 业务描述与设计实现

菜单页面加载完成以后,向服务端发起异步请求加载菜单信息,当菜单信息加载完成需要将菜单信息呈现到列表页面上。

关键代码设计与实现

第一步:在菜单列表页面引入treeGrid插件相关的JS。

第二步:在菜单列表页面,定义菜单列表配置信息,关键代码如下:

var columns = [ { field : 'selectItem', radio : true }, { title : '菜单ID', field : 'id', align : 'center', valign : 'middle', width : '80px' }, { title : '菜单名称', field : 'name', align : 'center', valign : 'middle', width : '130px' }, { title : '上级菜单', field : 'parentName', align : 'center', valign : 'middle', sortable : true, width : '100px' }, { title : '类型', field : 'type', align : 'center', valign : 'middle', width : '70px', formatter : function(item, index) { if (item.type == 1) { return '菜单'; } if (item.type == 2) { return '按钮'; } } }, { title : '排序号', field : 'sort', align : 'center', valign : 'middle', sortable : true, width : '70px' }, { title : '菜单URL', field : 'url', align : 'center', valign : 'middle', width : '160px' }, { title : '授权标识',//要显示的标题名称 field : 'permission',//json串中的key align : 'center',//水平居中 valign : 'middle',//垂直居中 sortable : false //是否排序 } ];//格式来自官方demos -->treeGrid(jquery扩展的一个网格树插件)

第三步:定义异步请求处理函数,代码参考如下:

function doGetObjects(){//treeGrid //1.构建table对象(bootstrap框架中treeGrid插件提供) var treeTable=new TreeTable( "menuTable",//tableId "menu/doFindObjects",//url columns); //设置从哪一列开始展开(默认是第一列) //treeTable.setExpandColumn(2); //2.初始化table对象(底层发送ajax请求获取数据) treeTable.init();//getJSON,get(),... }

第四步:页面加载完成,调用菜单查询对应的异步请求处理函数,关键代码如下:

$(function(){ doGetObjects(); }) 四、菜单管理删除操作实现 4.1 业务时序分析

基于用户在列表页面上选择的的菜单记录ID,执行删除操作,本次删除业务实现中,首先要基于id判断当前菜单是否有子菜单,假如有子菜单则不允许删除,没有则先删除菜单角色关系数据,然后再删除菜单自身信息。其时序分析如图所示: 在这里插入图片描述

4.2 服务端关键业务及代码实现 4.2.1 Dao接口实现 业务描述及设计实现

数据层基于业务层提交的菜单记录id,删除菜单角色关系以及菜单数据,菜单自身记录信息。

关键代码设计及实现

第一步:创建SysRoleMenuDao并定义基于菜单id删除关系数据的方法,关键代码如下:

@Mapper public interface SysRoleMenuDao { int deleteObjectsByMenuId(Integer menuId); }

第二步:在SysMenuDao中添加基于菜单id查询子菜单记录的方法。代码参考如下:

int getChildCount(Integer id);

第三步:在SysMenuDao中添加基于菜单id删除菜单记录的方法。代码参考如下:

int deleteObject(Integer id); 4.2.2 Mapper文件实现 业务描述及设计实现

在SysRoleMenuDao,SysMenuDao接口对应的映射文件中添加用于执行删除业务的delete元素,然后在元素内部定义具体的SQL实现。

关键代码设计与实现

第一步:创建SysRoleMenuMapper.xml文件并添加基于菜单id删除关系数据的元素,关键代码如下:

delete from sys_role_menus where menu_id=#{menuId}

第二步:在SysMenuMapper.xml文件中添加基于id统计子菜单数量的元素,关键代码如下:

select count(*) from sys_menus where parentId=#{id}

第三步:在SysMenuMapper.xml文件添加delete元素,基于带单id删除菜单自身记录信息,关键代码如下:

delete from sys_menus where id =#{id} 4.2.3 Service接口及实现类 业务描述与设计实现

在菜单业务层定义用于执行菜单删除业务的方法,首先通过方法参数接收控制层传递的菜单id,并对参数id进行校验。然后基于菜单id统计子菜单个数,假如有子菜单则抛出异常,提示不允许删除。假如没有子菜单,则先删除角色菜单关系数据。最后删除菜单自身记录信息后并返回业务执行结果。

关键代码设计与实现

第一步:在SysMenuService接口中,添加基于id进行菜单删除的方法。关键代码如下:

int deleteObject(Integer id);

第二步:在SysMenuServiceImpl实现类中注入SysRoleMenuDao相关对象。关键代码如下:

@Autowired private SysRoleMenuDao sysRoleMenuDao;

第三步:在SysMenuServiceImpl实现类中添加删除业务的具体实现。关键代码如下:

@Override public int deleteObject(Integer id) { //1.验证数据的合法性 if(id==null||id0) throw new ServiceException("请先删除子菜单"); //3.删除角色,菜单关系数据 sysRoleMenuDao.deleteObjectsByMenuId(id); //4.删除菜单元素 int rows=sysMenuDao.deleteObject(id); if(rows==0) throw new ServiceException("此菜单可能已经不存在"); //5.返回结果 return rows; } 4.2.4 Controller类实现 业务描述与设计实现

在菜单控制层对象中,添加用于处理菜单删除请求的方法。首先在此方法中通过形参接收客户端提交的数据,然后调用业务层对象执行删除操作,最后封装执行结果,并在运行时将响应对象转换为JSON格式的字符串,响应到客户端。

关键代码设计与实现

第一步:在SysMenuController中添加用于执行删除业务的方法。代码如下:

@RequestMapping("doDeleteObject") public JsonResult doDeleteObject(Integer id){ sysMenuService.deleteObject(id); return new JsonResult("delete ok"); }

第二步:启动tomcat进行访问测试,打开浏览器输入如下网址:

http://localhost/menu/doDeleteObject?id=10 4.3 客户端关键业务及代码实现 4.3.1 菜单列表页面事件处理 业务描述及设计实现

用户在页面上首先选择要删除的元素,然后点击删除按钮,将用户选择的记录id异步提交到服务端,最后在服务端执行菜单的删除动作。

关键代码设计与实现

第一步:页面加载完成以后,在删除按钮上进行点击事件注册。关键代码如下:

... $(".input-group-btn") .on("click",".btn-delete",doDeleteObject) ...

第二步:定义删除操作对应的事件处理函数。关键代码如下:

function doDeleteObject(){ //1.获取选中的记录id var id=doGetCheckedId(); if(!id){ alert("请先选择"); return; } //2.给出提示是否确认删除 if(!confirm("确认删除吗"))return; //3.异步提交请求删除数据 var url="menu/doDeleteObject"; var params={"id":id}; $.post(url,params,function(result){ if(result.state==1){ alert(resulssage); $("tbody input[type='radio']:checked") .parents("tr").remove(); }else{ alert(resulssage); } }); }

第三步:定义获取用户选中的记录id的函数。关键代码如下:

function doGetCheckedId(){ //1.获取选中的记录 var selections=$("#menuTable") //bootstrapTreeTable是treeGrid插件内部定义的jquery扩展函数 //getSelections为扩展函数内部要调用的一个方法 .bootstrapTreeTable("getSelections"); //2.对记录进行判定 if(selections.length==1) return selections[0].id; }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有