56--DB旅游生态系统-角色管理模块设计
角色管理模块设计
业务设计说明
本模块主要实现的是企业内部角色(岗位)的管理,可以在添加角色时,为角色分配资源访问权限,最后将角色再分配给用户.
角色表设计(sys_roles)
字段 | 类型 | 注释 |
---|---|---|
id | bigint(20) | 主键ID自增 |
name | varchar(100) | 角色名称 |
note | varchar(500) | 备注 |
createdTime | datetime | 创建时间 |
modifiedTime | datetime | 修改时间 |
createdUser | varchar(20) | 创建用户 |
modifiedUser | varchar(20) | 修改用户 |
菜单与角色的关系表(sys_role_menus)
字段 | 类型 | 注释 |
---|---|---|
id | int(11) | 主键自增 |
role_id | int(11) | 角色ID |
menu_id | int(11) | 菜单ID |
用户与角色关系表(sys_user_roles)
字段 | 类型 | 注释 |
---|---|---|
id | int(11) | 主键自增 |
user_id | int(11) | 角色ID |
role_id | int(11) | 菜单ID |
原型设计
角色管理展示
添加操作
修改操作
API设计说明
角色管理业务后台API分层架构及调用关系
角色管理列表页面呈现
业务时序分析
服务端实现
Controller实现
-
业务描述与设计实现
基于角色管理的请求业务,在PageController中添加返回角色页面相关方法。
-
关键代码设计与实现
@RequestMapping("{module}/{moduleUI}") public String doModuleUI(@PathVariable String moduleUI) { return "sys/"+moduleUI; }
客户端实现
首页菜单事件处理
-
业务描述与设计实现
首先准备角色列表页面(/templates/pages/sys/role_list.html),然后在starter.html页面中点击菜单管理时异步加载角色列表页面。
-
关键代码设计与实现
找到项目中的starter.html 页面,页面加载完成以后,注册菜单管理项的点击事件,当点击角色管理时,执行事件处理函数
$(function(){ … doLoadUI("load-role-id","role/role_list") }) function doLoadUI(id,url){ $("#"+id).click(function(){ $("#mainContentId").load(url); }); }
角色管理列表数据呈现
数据架构分析
角色列表页面加载完成,启动角色数据异步加载操作,本次角色列表页面要以分页形式呈现角色信息,其数据查询时,数据的封装及传递过程
时序分析
服务端关键业务及代码实现
POJO类实现
-
业务描述及设计
实现构建实体对象(POJO)封装从数据库查询到的记录,一行记录映射为内存中一个的这样的对象。对象属性定义时尽量与表中字段有一定的映射关系,并添加对应的set/get/toString等方法,便于对数据进行更好的操作。
-
关键代码分析及实现
package com.cy.pj.sys.pojo;
import lombok.Data;
@Data
public class SysRole implements Serializable{
private static final long serialVersionUID = -8557710039441592130L;
private Integer id;
private String name;
private String note;
private Date createdTime;
private Date modifiedTime;
private String createdUser;
private String modifiedUser;
}
Dao接口实现
-
业务描述及设计实现
通过数据层对象,基于业务层参数数据查询角色记录总数以及当前页面要呈现的角色信息。
-
关键代码分析及实现:
第一步:定义角色数据层接口对象,通过将此对象保证给业务层以提供角色数据操作。
第二步:在SysRoleDao接口中添加getRowCount方法用于按条件统计记录总数。
第三步:在SysRoleDao接口中添加findPageObjects方法,基于此方法实现当前页记录的数据查询操作。
package com.cy.pj.sys.dao; @Mapper public interface SysRoleDao { //获取总记录数 int getRowCount(@Param("name")String name); //获取角色的记录条数 List<SysRole> findPageObjects( @Param("name")String name, @Param("startIndex")Integer startIndex, @Param("pageSize")Integer pageSize ); }
Mapper文件实现
-
业务描述及设计实现
基于Dao接口创建映射文件,在此文件中通过相关元素(例如select)描述要执行的数据操作。
-
关键代码分析及实现:
第一步:在映射文件的设计目录中添加SysRoleMapper.xml映射文件
第二步:在映射文件中添加sql元素实现,SQL中的共性操作
第三步:在映射文件中添加id为getRowCount元素,按条件统计记录总数
在映射文件中添加id为findPageObjects元素,实现分页查询。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cy.pj.sys.dao.SysRoleDao"> <sql id="queryWhereId"> from sys_roles <where> <if test="name!=null and name!=''"> name like concat("%",#{name},"%") </if> </where> </sql> <!-- 查询总记录条数--> <select id="getRowCount" resultType="int"> select count(*) <include refid="queryWhereId"/> </select> <!-- 查询当前页记录条数--> <select id="findPageObjects" resultType="com.cy.pj.sys.pojo.SysRole"> select * <include refid="queryWhereId"/> order by createdTime desc limit #{startIndex},#{pageSize} </select> </mapper>
Service接口及实现类
-
业务描述及设计实现
在角色分页查询中,业务层对象主要负责对业务数据进行校验,并借助数据层对象完成数据的分页查询操作。
-
关键代码分析及实现:
第一步:定义角色业务接口及方法,暴露外界对角色业务数据的访问
package com.cy.pj.sys.service; public interface SysRoleService { //根据name,当前页码,以及页面大小查询当前页记录 PageObject<SysRole> findPageObjects(String name, Integer pageCurrent,Integer pageSize); }
第二步:定义角色业务接口实现类,并添加角色业务数据分页查询操作的具体实现
package com.cy.pj.sys.service.impl; @Service public class SysRoleServiceImpl implements SysRoleService { @Autowired private SysRoleDao sysRoleDao; @Override public PageObject<SysRole> findPageObjects( String name, Integer pageCurrent,Integer pageSize) { //参数校验 if (pageCurrent==null || pageCurrent<1) { throw new IllegalArgumentException("当前页码值无效"); } //获取总记录条数 int rowCount = sysRoleDao.getRowCount(name); //设置页面大小 if (pageSize==null||pageSize<1) { pageSize=5;//默认每页五条记录 } //设置起始索引 int startIndex =(pageCurrent-1)*pageSize; //计算总页数 //int pageCount = (rowCount-1)/pageSize+1; //基于name查询角色记录条数 List<SysRole> records = sysRoleDao.findPageObjects(name, startIndex, pageSize);; //封装结果 PageObject<SysRole> pageObject = new PageObject<>(rowCount, pageSize, pageCurrent, records); //返回结果 return pageObject; } }
Controller类实现
-
业务描述及设计实现
控制层对象主要负责请求和响应数据的处理,例如,本模块通过业务层对象执行业务逻辑,再通过POJO对象封装响应结果(主要对业务层数据添加状态信息),最后将响应结果转换为JSON格式的字符串响应到客户端。
-
关键代码分析及实现:
定义Controller类,并将此类对象使用Spring框架中的@RestController注解进行标识,表示此类对象要交给Spring管理。然后基于@RequestMapping注解为此类定义根路径映射。
package com.cy.pj.sys.controller; @RestController @RequestMapping("/role/") public class SysRoleController { @Autowired private SysRoleService sysRoleService; //查询当前页记录 @RequestMapping("doFindPageObjects") public JsonResult doPageObjects(String name,Integer pageCurrent,Integer pageSize) { PageObject<SysRole> pageObject = sysRoleService.findPageObjects(name, pageCurrent,pageSize); return new JsonResult(pageObject); } }
客户端关键业务及代码实现
菜单列表信息呈现
-
业务描述及设计实现
角色分页页面加载完成以后,向服务端发起异步请求加载角色信息,当角色信息加载完成需要将角色信息、分页信息呈现到列表页面上。
-
关键代码分析及实现:
第一步:分页页面加载完成,向服务端发起异步请求
$(function(){ //为什么要将doGetObjects函数写到load函数对应的回调内部。 $("#pageId").load("doPageUI", doGetObjects) });
第二步:定义异步请求处理函数
function doGetObjects(){ //debugger;//断点调试 //1.定义url和参数 var url="role/doFindPageObjects" var params={"pageCurrent":1};//pageCurrent=2 //2.发起异步请求 $.getJSON(url,params,function(result){ doHandleResponseResult(result); });//特殊的ajax函数 }
第三步:定义回调函数,处理服务端的响应结果。
function doHandleResponseResult (result){ //JsonResult if(result.state==1){//ok //更新table中tbody内部的数据 doSetTableBodyRows(result.data.records);//将数据呈现在页面上 //更新页面page.html分页数据 doSetPagination(result.data); //此方法写到page.html中 }else{ alert(result.msg); } }
第四步:将异步响应结果呈现在table的tbody位置。
function doSetTableBodyRows(records){ //1.获取tbody对象,并清空对象 var tBody=$("#tbodyId"); tBody.empty(); //2.迭代records记录,并将其内容追加到tbody for(var i in records){ //2.1 构建tr对象 var tr=$("<tr></tr>"); //2.2 构建tds对象 var tds=doCreateTds(records[i]); //2.3 将tds追加到tr中 tr.append(tds); //2.4 将tr追加到tbody中 tBody.append(tr); } }
第五步:创建每行中的td元素,并填充具体业务数据。
function doCreateTds(row,i){//i代表序号 var tds= "<td>"+(parseInt(i)+1)+"</td>"+ "<td>"+row.name+"</td>"+ "<td>"+row.note+"</td>"+ "<td>"+new Date(row.createdTime).toLocaleString()+"</td>"+ "<td>"+new Date(row.modifiedTime).toLocaleString()+"</td>"+ "<td>"+row.createdUser+"</td>"+ "<td>"+row.modifiedUser+"</td>"+ "<td><a class='btn-delete'>delete</a>"+ " <a class='btn-update'>update</a></td>"; return tds; }
角色管理删除操作实现
业务时序分析
基于用户在列表页面上选择的的用户记录ID,执行删除操作,本次删除业务实现中,首先要基于id删除角色菜单关系数据,然后基于id删除用户角色关系数据,最后删除角色自身信息.
服务端关键业务及代码实现
Dao接口实现
-
业务描述及设计实现
数据层基于业务层提交的角色记录id,先删除角色相关的关系数据,然后删除角色自身记录信息。
-
关键代码分析及实现:
第一步:创建SysRoleMenuDao接口并定义基于角色id删除关系数据的方法
public interface SysRoleMenuDao { int deleteObjectsByRoleId(Integer roleId); }
第二步:创建SysUserRoleDao接口并定义基于角色id删除关系数据的方法
public interface SysUserRoleDao { int deleteObjectsByRoleId(Integer roleId); }
第三步:在SysRoleDao中添加基于菜单id删除角色记录的方法。
int deleteObject(Integer id);
Mapper文件实现
-
业务描述及设计实现
在SysRoleMenuDao,SysUserRoleDao,SysRoleDao接口对应的映射文件中添加用于执行删除业务的delete元素,然后在元素内部定义具体的SQL实现。
-
关键代码分析及实现:
第一步:创建SysUserRoleMapper.xml文件并添加基于角色id删除用户角色关系数据的元素
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cy.pj.sys.dao.SysUserRoleDao"> <delete id="deleteObjectsByRoleId"> delete from sys_user_roles where role_id=#{roleId} </delete> </mapper>
第二步:在SysRoleMenuMapper.xml文件中添加基于角色id删除角色菜单关系数据的元素
<delete id="deleteObjectsByRoleId" parameterType="int"> delete from sys_role_menus where role_id=#{roleId} </delete>
第三步:在SysRoleMapper.xml文件添加delete元素,基于角色id删除角色自身记录信息
<delete id="deleteObject"> delete from sys_roles where id =#{id} </delete>
Service接口及实现类
-
业务描述及设计实现
在角色业务层定义用于执行角色删除业务的方法,首先通过方法参数接收控制层传递的角色id,并对参数id进行校验。然后基于角色id删除角色菜单关系数据,用户角色关系数据。最后删除自身记录信息后并返回业务执行结果。
-
关键代码分析及实现:
第一步:在SysRoleService接口中,添加基于id进行角色删除的方法。
int deleteObject(Integer id);
第二步:在SysRoleServiceImpl实现类中注入SysRoleMenuDao,SysUserRoleDao相关对象。
@Autowired private SysRoleMenuDao sysRoleMenuDao; @Autowired private SysUserRoleDao sysUserRoleDao;
第三步:在SysRoleServiceImpl实现类中添加删除业务的具体实现。
@Override public int deleteObject(Integer id) { //参数校验 if (id==null ||id<1) { throw new IllegalArgumentException("参数值无效"); } //删除角色与用户和菜单的关系数据 sysRoleMenuDao.deleteObjectsByRoleId(id); sysUserRoleDao.deleteObjectByRoleId(id); //删除角色自身数据 int rows = sysRoleDao.deleteObject(id); //结果校验 if (rows==0) { throw new ServiceException("记录可能已经不存在"); } return rows; }
Controller类实现
-
业务描述及设计实现
在角色控制层对象中,添加用于处理角色删除请求的方法。首先在此方法中通过形参接收客户端提交的数据,然后调用业务层对象执行删除操作,最后封装执行结果,并在运行时将响应对象转换为JSON格式的字符串,响应到客户端。
-
关键代码分析及实现:
第一步:在SysRoleController中添加用于执行删除业务的方法。
@RequestMapping("doDeleteObject") public JsonResult doDeleteObjects(Integer id) { sysRoleService.deleteObject(id); return new JsonResult("delete ok"); }
第二步:启动tomcat进行访问测试
http://localhost/role/doDeleteObject?id=16
客户端关键业务及代码实现
菜单列表页面事件处理
-
业务描述及设计实现
用户在页面上首先选择要删除的元素,然后点击删除按钮,将用户选择的记录id异步提交到服务端,最后在服务端执行角色的删除动作。
-
关键代码分析及实现:
第一步:页面加载完成以后,在删除按钮上进行点击事件注册。
... $(".input-group-btn") .on("click",".btn-delete",doDeleteObject) ...
第二步:定义删除操作对应的事件处理函数。
function doDeleteObject(){ //1.params var id=$(this).parents("tr").data("id"); var params={"id":id}; //2.url var url="role/doDeleteObject" //进行确认提示 if(!confirm("确认删除吗?"))return; //3.ajax request $.post(url,params,function(result){ if(result.state==1){ alert(result.message); doGetObjects(); }else{ alert(result.message); } }) }
角色添加页面呈现
业务时序分析
角色添加页面呈现
-
业务描述及设计实现
在角色列表页面中点击添加按钮时,呈现角色编辑页面。
-
关键代码分析及实现:
第一步:角色列表事件注册,在role_list.html中
$(document).ready(function(){ ... $(".input-group-btn") .on("click",".btn-add",doLoadEditUI); });
第二步:定义角色列表页面添加按钮的事件处理函数
//异步加载编辑页面 function doLoadEditUI(){ var title; //hasClass函数用于判定对象中是否包含某个样式 if($(this).hasClass("btn-add")){ title="角色添加"; }else{ title="角色修改"; } loadPageUI(url); }
第三步: 定义加载添加页面事件处理函数
function loadPageUI(title){ $("#mainContentId") .load("role/role_edit",function(){ $(".box-title").html(title); }); }
角色添加页面事件处理
-
业务描述及设计实现
角色编辑页面加载完成,异步加载菜单信息并呈现在页面上。
-
关键代码分析及实现:
第一步:页面中引入zTree相关JS
第二步:页面上定义zTree初始配置
var zTree; var setting = { data : { simpleData : { enable : true, //使用简单数据模式 idKey : "id", //节点数据中保存唯一标识的属性名称 pIdKey : "parentId", //节点数据中保存其父节点唯一标识的属性名称 rootPId : null //根节点id } }, check:{ enable:true, nocheckInherit:true }//此配置提供复选框操作(可查官方zTree) }
第三步:异步加载菜单信息并进行呈现。
$(function(){ //异步加载菜单信息,初始化页面菜单 doLoadSysMenus(); }); //页面加载完成时初始化zTree function doLoadSysMenus(){ var url="menu/doFindZtreeMenuNodes" $.getJSON(url,function(result){ console.log(result); if(result.state==1){ zTree=$.fn.zTree.init( $("#menuTree"),setting,result.data); //修改时添加如下代码(注意先后顺序) var rowData=$("#mainContentId").data("data"); if(rowData)doInitEditFormData(rowData); }else{ alert(result.message); } }); }
角色数据添加实现
数据基本架构分析
用户在角色编辑页面输入数据,然后异步提交到服务端,其简易数据传递基本架构,添加的时候需要在添加自身角色信息的基础上,通过一对多的方式添加角色和菜单的关系数据
业务时序分析
服务端关键业务及代码实现
Dao接口实现
-
业务描述及设计实现
负责将用户提交的角色数据,持久化到数据库。
-
关键代码分析及实现:
在SysRoleDao接口中定义数据持久化方法
int insertObject(SysRole sysRole);
SysRoleMenuDao接口中方法定义(不存在则创建)
int insertObjces(@Param("roleId")Integer roleId, @Param("menuIds")Integer[] menuIds);
Mapper文件实现
-
业务描述及设计实现
基于SysRoleDao中方法的定义,编写用于实现角色添加的SQL元素。
-
关键代码分析及实现:
第一步:在SysRoleMapper.xml中添加insertObject元素,用于写入菜单信息。其中useGeneratedKeys 表示使用insert操作的自增主键值,keyProperty表示将获取的自增主键值赋值给参数对象的id属性
<!-- 新增角色信息 --> <insert id="insertObject" parameterType="com.cy.pj.sys.pojo.SysRole" useGeneratedKeys="true" keyProperty="id"> insert into sys_roles (id,name,note,createdTime,modifiedTime, createdUser,modifiedUser) values (null,#{name},#{note},now(),now(), #{createdUser},#{modifiedUser}) </insert>
第二步:在SysRoleMenuMapper中元素定义,
<insert id="insertObjcets"> insert into sys_role_menus (role_id,menu_id) values <foreach collection="menuIds" item="menuId" separator=","> (#{roleId},#{menuId}) </foreach> </insert>
Service接口及实现类
-
业务描述及设计实现
基于控制层请求,调用数据层对象将角色以及对应的菜单信息写入到数据库中。
-
关键代码分析及实现:
第一步:在SysRoleService接口中,添加用于保存角色对象的方法。
int saveObjcets(SysRole sysRole,Integer[] menuIds);
第二步:在SysRoleServiceImpl类中,实现菜单保存操作。
@Override public int saveObjcets(SysRole sysRole, Integer[] menuIds) { //参数校验 if(sysRole==null) { throw new ServiceException("新增的角色不能为空"); } if (menuIds==null || menuIds.length==0) { throw new ServiceException("必须为角色授权"); } //先新增自身角色数据 int rows =sysRoleDao.insertObject(sysRole); //再新增关系数据 int rows2 =sysRoleMenuDao.insertObjects(sysRole.getId(), menuIds); //校验新增结果 if (rows==0||rows2==0) { throw new ServiceException("添加失败"); } return rows; }
Controller类实现
-
业务描述及设计实现
接收客户端提交的菜单数据,并对其进行封装,然后调用业务层对象进行业务处理,最后将业务层处理结果响应到客户端。
-
关键代码分析及实现:
定义Controller方法,借助此方法处理保存角色数据请求和响应逻辑。
@RequestMapping("doSaveObject") public JsonResult doSaveObject(SysRole sysRole,Integer[] menuIds) { sysRoleService.saveObjcets(sysRole, menuIds); return new JsonResult("save ok"); }
客户端关键业务及代码实现
页面cancel按钮事件处理
-
业务描述及设计实现
点击页面cancel按钮时,加载菜单那列表页面。
-
关键代码分析及实现:
第一步:事件注册(页面加载完成以后)
$(".box-footer") .on("click",".btn-cancel",doCancel)
第二步:事件处理函数定义
function doCancel(){ var url="role/role_list"; $("#mainContentId").load(url); }
页面Save按钮事件处理
-
业务描述及设计实现
点击页面save按钮时,将页面上输入的菜单信息提交到服务端。
-
关键代码分析及实现:
第一步:事件注册(页面加载完成以后)。
$(".box-footer") .on("click",".btn-save",doSaveOrUpdate)
第二步:Save按钮事件处理函数定义。
function doSaveOrUpdate(){ debugger //1.参数(表单数据) var params=doGetEditFormData(); if(!params.name.trim()){ alert("角色名不能为空"); return; } if(!params.menuIds.trim()){ alert("请为角色赋予权限") return; } var data=$("#mainContentId").data("data"); if(data)params.id=data.id; //2.url var insertUrl="role/doSaveObject"; var updateUrl="role/doUpdateObject"; var url=data?updateUrl:insertUrl; //3.ajax request $.post(url,params,function(result){ if(result.state==1){ alert(result.message); doCancel(); }else{ alert(result.message); } }) }
第三步:表单数据获取及封装函数定义。
function doGetEditFormData(){ //1.获取角色自身信息 var params={ name:$("#nameId").val(), note:$("#noteId").val() } //2.获取选中菜单信息 var menuIds=[]; console.log(zTree) var checkedNodes= zTree.getCheckedNodes(true); for(var i in checkedNodes){ menuIds.push(checkedNodes[i].id); } params.menuIds=menuIds.toString(); return params; }
角色修改页面数据呈现
业务时序分析
服务端关键业务及代码实现
在角色列表页面点击修改按钮时,基于id进行角色信息的查询,在查询角色信息时将角色信息与对应的菜单关系数据封装到到一个值对象,然后传递到客户端在修改页面进行呈现
更新操作获取数据的方案
逻辑分析图:
POJO定义
-
业务描述及设计实现
构建值对象(POJO),用于封装从数据库查询到的角色菜单记录,并添加对应的set/get/toString等方法,便于对数据进行更好的操作。
-
关键代码分析及实现:
package com.cy.pj.sys.pojo;
// 基于此对象封装,封装基于角色id查询到的角色自身信息以及角色对应的菜单id。
@Data
public class SysRoleMenu implements Serializable{
private static final long serialVersionUID = -2671028987524519218L;
private Integer id;
private String name;
private String note;
/**角色对应的菜单id*/
private List<Integer> menuIds;
}
Dao接口实现
-
业务描述及设计实现
负责基于id执行角色数据的查询操作。
-
关键代码分析及实现:
在SysRoleDao接口中定义数据持久化方法
//基于角色id查询角色自身信息 SysRoleMenu findById(Integer id);
Mapper文件实现(亮点)
-
业务描述及设计实现
基于SysRoleDao中findObjectById方法的定义,在映射文件中添加对应的角色查询元素。
-
关键代码分析及实现:
第一步:在SysRoleMapper.xml中添加findById元素
第二步:在SysRoleMapper.xml中添加第一步中resultMap属性定义的结果映射元素
<select id="findById" resultMap="sysRoleMenu"> select id,name,note from sys_roles where id=#{id} </select> <!-- resultMap是mybatis中用于实现高级映射的一个非常重要的元素,主要应用于 自定义映射规则的设计,例如字段的自定义映射,表嵌套查询映射,表关联查询映射 --> <resultMap type="com.cy.pj.sys.pojo.SysRoleMenu" id="sysRoleMenu"> <!-- id元素用于实现主键字段映射:尤其是当在再次基于主键值执行其它查询, 建议将id主键值进行手动映射 --> <id property="id" column="id"/> <result property="name" column="name"/> <result property="note" column="note"/> <collection property="menuIds" column="id" select="com.cy.pj.sys.dao.SysRoleMenuDao.findMenuIdsByRoleId"/> </resultMap>
第三步:在SysRoleMenuMapper.xml中添加第二步中collection元素内部select属性对应的查询元素。
<!-- 基于角色id查询菜单id --> <select id="findMenuIdsByRoleId" resultType="integer"> select menu_id from sys_role_menus where role_id=#{roleId} </select>
图解:一对多查询
Service接口及实现类
-
业务描述及设计实现
基于控制层请求,调用数据层方法,查询对应的角色及相关信息。
-
关键代码分析及实现:
第一步:在SysRoleService接口中,添加基于id查询对应角色及相关信息的方法。
/** * 基于角色id查询角色以及角色对应的菜单id * @param id * @return */ SysRoleMenu findById(Integer id);
第二步:在SysRoleService接口对应的实现类SysRoleServiceImpl中添加findById的具体实现。
//方案2:业务层查询1次,数据层查询2次 @Override public SysRoleMenu findById(Integer id) { //1.参数校验 AssertUtil.isArgumentValid(id==null||id<1, "id值无效"); //2.查询角色自身信息 SysRoleMenu sysRoleMenu=sysRoleDao.findById(id); //System.out.println("sysRoleMenu="+sysRoleMenu); return sysRoleMenu; }
或者采用:
//方案1:业务层多次查询 // @Override // public SysRoleMenu findById(Integer id) { // //1.参数校验 // AssertUtil.isArgumentValid(id==null||id<1, "id值无效"); // //2.查询角色自身信息 // SysRoleMenu sysRoleMenu=sysRoleDao.findById(id); // //3.查询角色对应的菜单id // List<Integer> menuIds=sysRoleMenuDao.findMenuIdsByRoleId(id); // //4.封装查询结果并返回 // sysRoleMenu.setMenuIds(menuIds); // return sysRoleMenu; // }
Controller类实现
-
业务描述及设计实现
基于控制层请求,调用数据层方法,查询对应的角色及相关信息。
-
关键代码分析及实现:
@RequestMapping("doFindObjectById") public JsonResult doFindObjectById(Integer id) { return new JsonResult(sysRoleService.findById(id)); }
客户端关键业务及代码实现
列表页面修改按钮事件处理
-
业务描述及设计实现
在角色修改按钮上进行事件注册,点击页面修改按钮时,基于角色id向服务端发起异步请求获取角色相关数据,然后加载修改页面。
-
关键代码分析及实现:
第一步:页面加载完成,进行修改按钮事件注册
$(function(){ //... $(".input-group-btn").on("click","btn-update",doLoadEditUI); });
第二步:修改按钮事件处理函数定义或修改
function doLoadEditUI(){ var title; if($(this).hasClass('btn-add')){ title="添加角色"; doLoadPageUI(title); }else{ title="修改角色" var id=$(this).parents("tr").data("id"); var params={"id":id}; var url="role/doFindObjectById"; $.getJSON(url,params,function(result){ if(result.state==1){ result.data.id=id;//在结果中动态追加id $("#mainContentId").data("data",result.data);//绑定基于id查询到的数据 doLoadPageUI(title);//异步加载页面 }else{ alert(result.message); } }); } }
第三步:定义或修改加载编辑页面的方法。
function doLoadPageUI(title){ var url="role/role_edit" $("#mainContentId") .load(url,function(){ $(".box-title").html(title); }) }
编辑页面菜单数据呈现
-
业务描述及设计实现
页面加载完成,获取编辑页面数据,然后在页面指定位置进行数据呈现数据。
-
关键代码分析及实现:
第一步:在角色编辑页面中,菜单数据加载完成以后,获取角色编辑页面中需要的表单数据,然后进行页面数据初始化。需要加载菜单的树结构
//页面加载完成时初始化zTree function doLoadSysMenus(){ var url="menu/doFindZtreeMenuNodes" $.getJSON(url,function(result){ console.log(result); if(result.state==1){ zTree=$.fn.zTree.init( $("#menuTree"),setting,result.data); //修改时添加如下代码(注意先后顺序) var rowData=$("#mainContentId").data("data");//获取绑定的数据 if(rowData)doInitEditFormData(rowData); }else{ alert(result.message); } }); }
第二步:定义编辑页面数据初始化方法。
function doInitEditFormData(data){ console.log("data",data); //1.初始化角色自身信息 $("#nameId").val(data.name); $("#noteId").val(data.note); //2.初始化菜单信息 //2.1展开树节点 zTree.expandAll(true); //2.2获取角色对应的菜单id var menuIds=data.menuIds; //2.3迭代所有菜单id for(var i in menuIds){ //基于菜单id获取ztree中的node节点 var node=zTree.getNodeByParam("id",menuIds[i]); //让节点选中 zTree.checkNode(node,true,false); } }
如何选中查找到的菜单信息
角色数据更新实现
业务时序分析
服务端关键业务及代码实现
Dao接口实现
-
业务描述及设计实现
获取角色编辑页面数据,然后异步提交到服务端,将角色信息以及角色对应的菜单关系数据更新到数据库。
-
关键代码分析及实现:
在SysRoleDao接口中添加数据更新方法
int updateObject(SysRole entity);
Mapper文件实现
-
业务描述及设计实现
基于SysRoleDao中updateObject方法的定义,编写用于实现角色更新的SQL元素。
-
关键代码分析及实现:
<!-- 更新角色自身信息 --> <update id="updateObject"> update sys_roles set name=#{name}, note=#{note}, modifiedTime=now(), modifiedUser=#{modifiedUser} where id=#{id} </update>
Service接口及实现类
-
业务描述及设计实现
基于控制层请求,对数据进行校验并调用数据层对象将角色信息以及角色菜单关系数据更新到数据库中。
-
关键代码分析及实现:
第一步:在SysRoleService接口中,添加用于更新角色对象的方法。
/** * 更新角色自身信息以及角色对应的菜单自身信息 * @param entity * @param menuIds * @return */ int updateObject(SysRole entity,Integer[] menuIds);
第二步:在SysRoleServiceImpl类中,实现更新角色操作。
@Override public int updateObject(SysRole entity,Integer[] menuIds) { //1.合法性验证 if(entity==null) throw new IllegalArgumentException("更新的对象不能为空"); if(entity.getId()==null) throw new IllegalArgumentException("id的值不能为空"); if(StringUtils.isEmpty(entity.getName())) throw new IllegalArgumentException("角色名不能为空"); if(menuIds==null||menuIds.length==0) throw new IllegalArgumentException("必须为角色指定一个权限"); //2.更新数据 int rows=sysRoleDao.updateObject(entity); if(rows==0) throw new ServiceException("对象可能已经不存在"); //先删除原有的关系数据 sysRoleMenuDao.deleteObjectsByRoleId(entity.getId()); //再新增现有的关系数据 sysRoleMenuDao.insertObjects(entity.getId(),menuIds); //3.返回结果 return rows; }
Controller类实现
-
业务描述及设计实现
首先接收客户端提交的角色数据,并对其进行封装,然后调用业务层对象对角色信息进行更行更新,最后将业务层处理结果响应到客户端。
-
关键代码分析及实现:
在SysRoleController类中定义更新角色的方法。
@RequestMapping("doUpdateObject") public JsonResult doUpdateObject(SysRole entity,Integer[] menuIds) { sysRoleService.updateObject(entity,menuIds); return new JsonResult("update ok"); }
客户端关键业务及代码实现
编辑页面更新按钮事件处理
-
业务描述与设计实现
点击页面save按钮时,将页面上输入的角色编辑信息提交到服务端。
-
关键代码设计与实现
第一步:在角色编辑页面中定义获取角色编辑页面表单数据的函数
function doSaveOrUpdate(){ debugger //1.参数(表单数据) var params=doGetEditFormData(); if(!params.name.trim()){ alert("角色名不能为空"); return; } if(!params.menuIds.trim()){ alert("请为角色赋予权限") return; } var data=$("#mainContentId").data("data"); if(data)params.id=data.id; //2.url var insertUrl="role/doSaveObject"; var updateUrl="role/doUpdateObject"; var url=data?updateUrl:insertUrl; //3.ajax request $.post(url,params,function(result){ if(result.state==1){ alert(result.message); doCancel(); }else{ alert(result.message); } }) }
第二步:定义或修改提交编辑页面表单数据方法
function doGetEditFormData(){ //1.获取角色自身信息 var params={ name:$("#nameId").val(), note:$("#noteId").val() } //2.获取选中菜单信息 var menuIds=[]; console.log(zTree) var checkedNodes= zTree.getCheckedNodes(true); for(var i in checkedNodes){ menuIds.push(checkedNodes[i].id); } params.menuIds=menuIds.toString(); return params; }
角色模块至此!