1 角色治理设计说明

1.1 业务设计说明
本模块次要实现的是企业外部角色(岗位)的治理,能够在增加角色时,为角色分配资源
拜访权限,最初将角色再调配给用户,图-1 所示:

基于对表的设计,其数据逻辑关系的展现,如图-2 所示:

角色表设计脚本如下:

CREATE TABLE `sys_roles` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL COMMENT '角色名称', `note` varchar(500) DEFAULT NULL COMMENT '备注', `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=46 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='角色与菜单对应关系';

用户与角色关系表设计脚本如下:

CREATE TABLE `sys_user_roles` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) DEFAULT NULL COMMENT '用户 ID', `role_id` int(11) DEFAULT NULL COMMENT '角色 I  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户与角色对应关系';

1.2 原型设计说明
基于用户需要,通过动态页面为用户出现角色模块的根本需要。当在主页点击角色治理时,出现角色列表页面,如图-3 所示。

在列表页面点击增加按钮时,出现角色编辑页面,如图-4 所示.

在列表页面点击编辑按钮时,出现角色编辑页面,如图-5 所示。

阐明:如果客户对此原型进行了确认,后续则能够基于此原型进行研发。

  • API设计说明

角色治理业务后盾API分层架构及调用关系如图-6所示:

阐明:分层目标次要将简单问题简单化,实现各司其职,各尽所能。

  • 角色治理列表页面出现

  1. 业务时序剖析

角色列表页面,其加载时序剖析,如图-7所示:

  • 服务端实现

  1. Controller实现

  • 业务形容与设计实现

基于角色治理的申请业务,在PageController中增加返回角色页面相干办法。

  • 要害代码设计与实现

查看PageController中是否有返回UI页面的办法,有则无需增加。如:

@RequestMapping("{module}/{moduleUI}")public String doModuleUI(@PathVariable String moduleUI) { return "sys/"+moduleUI;}
  1. 客户端实现

  2. 首页菜单事件处理

  • 业务形容与设计实现

首先筹备角色列表页面(/templates/module/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); });}

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

  • 角色列表页面

  • 业务形容与设计实现

本页面出现角色信息时要以分页模式进行出现。

  • 要害代码设计与实现:

参考sys_role.html文件内容。

  1. 角色治理列表数据出现

  2. 数据架构剖析

角色列表页面加载实现,启动角色数据异步加载操作,本次角色列表页面要以分页模式出现角色信息,其数据查问时,数据的封装及传递过程,如图-8所示。

阐明:本模块将从数据库查问到的角色数据封装到SysRole对象,一行记录一个SysRole对象。
角色数据分页查问时,其时序剖析如图-9所示:

  • 服务端要害业务及代码实现

  1. Pojo类实现

  • 业务形容及设计实现

构建实体对象(POJO)封装从数据库查问到的记录,一行记录映射为内存中一个的这样的对象。对象属性定义时尽量与表中字段有肯定的映射关系,并增加对应的set/get/toString等办法,便于对数据进行更好的操作。

  • 要害代码剖析及实现
package com.cy.pj.sys.pojo;import com.fasterxml.jackson.annotation.JsonFormat;import lombok.Data;import java.io.Serializable;import java.util.Date;@Datapublic class SysRole implements Serializable {    private static final long serialVersionUID = -8557710039441592130L;    private Integer id;    private String name;    private String note;    @JsonFormat(pattern = "yyyy/MM/dd HH:mm",timezone = "GMT+8")    private Date createdTime;    @JsonFormat(pattern = "yyyy/MM/dd HH:mm",timezone = "GMT+8")    private Date modifiedTime;    private String createdUser;    private String modifiedUser;}

阐明:通过此对象除了能够封装从数据库查问的数据,还能够封装客户端申请数据,实现层与层之间数据的传递。

  • Dao接口实现

  • 业务形容及设计实现

通过数据层对象,基于业务层参数数据查问角色记录总数以及以后页面要出现的角色信息。

  • 要害代码剖析及实现:

第一步:定义角色数据层接口对象,通过将此对象保障给业务层以提供角色数据操作。代码如下:

@Mapperpublic interface SysRoleDao {}

第二步:在SysRoleDao接口中增加getRowCount办法用于按条件统计记录总数。代码如下:

 int getRowCount(String name);

第三步:在SysRoleDao接口中增加findPageObjects办法,基于此办法实现当前页记录的数据查问操作。代码如下:

List<SysRole> findPageObjects(String name,Integer startIndex,Integer pageSize);

阐明:

  1. 当DAO中办法参数多余一个时尽量应用@Param注解进行润饰并指定名字,而后再Mapper文件中便能够通过相似#{username}形式进行获取,否则只能通过#{arg0},#{arg1}或者#{param1},#{param2}等形式进行获取。
  2. 当DAO办法中的参数利用在动静SQL中时无论多少个参数,尽量应用@Param注解进行润饰并定义。
  3. Mapper文件实现

  • 业务形容及设计实现

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

  • 要害代码设计及实现

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

<?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"></mapper>

第二步:在映射文件中增加sql元素实现,SQL中的共性操作,代码如下:

<sql id="queryWhereId"> <where> <if test="name!=null and name!=''"> name like concat("%",#{name},"%") </if> </where> </sql>

第三步:在映射文件中增加id为getRowCount元素,按条件统计记录总数,代码如下:

 <select id="getRowCount"resultType="int"> select count(*) from sys_roles <include refid="queryWhereId"/> </select>

第四步:在映射文件中增加id为findPageObjects元素,实现分页查问。代码如下:

 <select id="findPageObjects"resultType="com.cy.pj.sys.pojo.SysRole">    select *    from sys_roles    <include refid="queryWhereId"/>    order by createdTime desc    limit #{startIndex},#{pageSize} </select>
  1. Service接口及实现类

  • 业务形容与设计实现

在角色分页查问中,业务层对象次要负责对业务数据进行校验,并借助数据层对象实现数据的分页查问操作。

  • 要害代码设计及实现

第一步:定义角色业务接口及办法,裸露外界对角色业务数据的拜访,其代码参考如下:

package com.cy.pj.sys.service;public interface SysRoleService { PageObject<SysRole> findPageObjects(String name,Integer pageCurrent);}

第二步:定义角色业务接口实现类,并增加角色业务数据分页查问操作的具体实现,其代码参考如下:

package com.cy.pj.sys.service.impl;import org.springframework.util.StringUtils;@Servicepublic class SysRoleServiceImpl implements SysRoleService { @Autowired private SysRoleDao sysRoleDao; @Override public PageObject<SysRole> findPageObjects(String name,Integer pageCurrent) { //1.对参数进行校验 if(pageCurrent==null||pageCurrent<1)throw new IllegalArgumentException("以后页码值有效"); //2.查问总记录数并进行校验 int rowCount=sysRoleDao.getRowCount(name); if(rowCount==0)throw new ServiceException("没有找到对应记录"); //3.查问当前页记录 int pageSize=3; int startIndex=(pageCurrent-1)*pageSize; List<SysRole> records=sysRoleDao.findPageObjects(name,startIndex, pageSize); //4.对查问后果进行封装并返回 return new PageObject<>(pageCurrent, pageSize,rowCount, records); }}
  1. Controller类实现

  • 业务形容与设计实现

管制层对象次要负责申请和响应数据的解决,例如,本模块通过业务层对象执行业务逻辑,再通过VO对象封装响应后果(次要对业务层数据增加状态信息),最初将响应后果转换为JSON格局的字符串响应到客户端。

  • 要害代码设计与实现

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

@RequestMapping("/role/")@RestControllerpublic class SysRoleController {private SysRoleService sysRoleService;}

在Controller类中增加菜单查询处理办法,代码参考如下:

@RequestMapping("doFindPageObjects")public JsonResult doFindPageObjects(String name,Integer pageCurrent) { return new JsonResult(sysRoleService.findPageObjects(name,pageCurrent)); }
  1. 客户端要害业务及代码实现

  2. 菜单列表信息出现

  • 业务形容与设计实现

角色分页页面加载实现当前,向服务端发动异步申请加载角色信息,当角色信息加载实现须要将角色信息、分页信息出现到列表页面上。

  • 要害代码设计与实现

异步申请处理函数,要害代码如下:
第一步:分页页面加载实现,向服务端发动异步申请,代码参考如下:

 $(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){ //JsonResul 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){       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>"+       "&nbsp;<a class='btn-update'>update</a></td>";       return tds;   }
  1. 角色治理删除操作实现

  2. 业务时序剖析

基于用户在列表页面上抉择的的用户记录ID,执行删除操作,本次删除业务实现中,首先要基于id删除角色菜单关系数据,而后基于id删除用户角色关系数据,最初删除角色本身信息,如图-10所示:

  1. 服务端要害业务及代码实现

  2. Dao接口实现

  3. 业务形容及设计实现

数据层基于业务层提交的角色记录id,先删除角色相干的关系数据,而后删除角色本身记录信息。

  1. 要害代码设计及实现:

第一步:在创立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实现。

  • 要害代码设计与实现

第一步:创立SysRoleMenuMapper.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.SysRoleMenuDao"> <delete id="deleteObjectsByRoleId"parameterType="int">          delete from sys_role_menus          where role_id=#{roleId}        </delete></mapper>

第二步:在SysUserRoleMapper.xml文件中增加基于id删除用户角色关系数据的元素,要害代码如下:

<delete id="deleteObjectsByRoleId">          delete from sys_user_roles          where role_id=#{roleId}         </delete>

第三步:在SysRoleMapper.xml文件增加delete元素,基于角色id删除角色本身记录信息,要害代码如下:

 <delete id="deleteObject">       delete from sys_roles       where id =#{id}    </delete>
  1. Service接口及实现类

  • 业务形容与设计实现

在角色业务层定义用于执行角色删除业务的办法,首先通过办法参数接管管制层传递的角色id,并对参数id进行校验。而后基于角色id删除角色菜单关系数据,用户角色关系数据。最初删除本身记录信息后并返回业务执行后果。

  • 要害代码设计与实现

第一步:在SysRoleService接口中,增加基于id进行角色删除的办法。要害代码如下:

int deleteObject(Integer id);

第二步:在SysRoleServiceImpl实现类中注入SysRoleMenuDao,SysUserRoleDao相干对象。要害代码如下:

@Autowiredprivate SysRoleMenuDao sysRoleMenuDao;@Autowiredprivate SysUserRoleDao sysUserRoleDao;

第二步:在SysRoleServiceImpl实现类中增加删除业务的具体实现。要害代码如下:

@Override    public int deleteObject(Integer id) {        //1.验证数据的合法性        if(id==null||id<=0)throw new IllegalArgumentException("请先抉择");        //3.基于id删除关系数据        sysRoleMenuDao.deleteObjectsByRoleId(id);        sysUserRoleDao.deleteObjectsByRoleId(id);           //4.删除角色本身        int rows=sysRoleDao.deleteObject(id);        if(rows==0)throw new ServiceException("此记录可能曾经不存在");        //5.返回后果        return rows;    }
  1. Controller类实现

  • 业务形容与设计实现

在角色管制层对象中,增加用于解决角色删除申请的办法。首先在此办法中通过形参接管客户端提交的数据,而后调用业务层对象执行删除操作,最初封装执行后果,并在运行时将响应对象转换为JSON格局的字符串,响应到客户端。

  • 要害代码设计与实现

第一步:在SysRoleController中增加用于执行删除业务的办法。代码如下:

@RequestMapping("doDeleteObject")public JsonResult doDeleteObject(Integer id){       sysRoleService.deleteObject(id);          return new JsonResult("删除胜利");}

第二步:启动tomcat进行拜访测试,关上浏览器输出如下网址:

http://localhost/role/doDeleteObject?id=10
  1. 客户端要害业务及代码实现

  2. 菜单列表页面事件处理

  • 业务形容及设计实现

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

  • 要害代码设计与实现

第一步:页面加载实现当前,在删除按钮上进行点击事件注册。要害代码如下:

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

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

function doDeleteObject(){       //1.获取选中的值(分页显示记录时在tr上要绑定id的值)       var id=$(this).parents("tr").data("id");       //2.构建参数对象       var params={id:id};       //3.异步申请执行删除       var url="role/doDeleteObject";       $.post(url,params,function(result){           if(result.state==1){               alert(result.message);               doGetObjects();           }else{               alert(result.message);           }       })   }
  1. 角色增加页面出现

  2. 业务时序剖析

点击角色列表上的增加按钮,其时序剖析,如图-11所示:

  • 筹备角色编辑页面

筹备角色编辑页面(/templates/pages/sys/role_edit.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);       });    }
  1. 角色编辑页面事件处理

  • 业务形容与设计实现

角色编辑页面加载实现,异步加载菜单信息并出现在页面上。

  • 要害代码设计与实现

第一步:页面中引入zTree相干JS
第二步:页面上定义zTree初始配置

var zTree; var setting = {       data : {           simpleData : {               enable : true,               idKey : "id",  //节点数据中保留惟一标识的属性名称               pIdKey : "parentId",  //节点数据中保留其父节点惟一标识的属性名称               rootPId : null  //根节点id           }       },       check:{           enable:true,           nocheckInherit:true       }}

第三步:异步加载菜单信息并进行出现。

function doLoadSysMenus(){        var url="menu/doFindZtreeMenuNodes"        $.getJSON(url,function(result){            if(result.state==1){            zTree=$.fn.zTree.init(            $("#menuTree"),setting,result.data);             }else{            alert(result.message);            }        });}
  1. 角色数据增加实现

  2. 数据根本架构剖析

用户在角色编辑页面输出数据,而后异步提交到服务端,其繁难数据传递根本架构,如图-12所示:

角色数据保留时,数据时序图剖析,

  • 服务端要害业务及代码实现

  1. DAO接口定义

  • 业务形容与设计实现

负责将用户提交的角色数据,长久化到数据库。

  • 要害代码设计与实现

在SysRoleDao接口中定义数据长久化办法:

int insertObject(SysRole entity);

SysRoleMenuDao接口中办法定义(不存在则创立)

int insertObjects(Integer roleId,Integer[] menuIds);
  1. 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="insertObjects">         insert into sys_role_menus         (role_id,menu_id)         values          <foreach collection="menuIds" separator=","item="item">              (#{roleId},#{item})         </foreach> </insert>
  1. Service接口定义及实现

  • 业务形容与设计实现

基于管制层申请,调用数据层对象将角色以及对应的菜单信息写入到数据库中。

  • 要害代码设计与实现

第一步:在SysRoleService接口中,增加用于保留角色对象的办法。要害代码如下:

int saveObject(SysRole entity,Integer[]menuIds);

第二步:在SysRoleServiceImpl类中,实现菜单保留操作。要害代码如下:

@Override    public int saveObject(SysRole entity, Integer[] menuIds) {        //1.参数有效性校验        if(entity==null)throw new IllegalArgumentException("保留对象不能为空");        if(StringUtils.isEmpty(entity.getName()))throw new IllegalArgumentException("角色名不容许为空");        if(menuIds==null||menuIds.length==0)throw new ServiceException("必须为角色调配权限");        //2.保留角色本身信息        int rows=sysRoleDao.insertObject(entity);        //3.保留角色菜单关系数据        sysRoleMenuDao.insertObjects(entity.getId(), menuIds);        //4.返回业务后果        return rows;    }
  1. Controller类定义

  • 业务形容与设计实现

接管客户端提交的菜单数据,并对其进行封装,而后调用业务层对象进行业务解决,最初将业务层处理结果响应到客户端。

  • 要害代码设计与实现

定义Controller办法,借助此办法解决保留角色数据申请和响应逻辑。要害代码如下:

@RequestMapping("doSaveObject")public JsonResult doSaveObject(SysRole entity,Integer[] menuIds){       sysRoleService.saveObject(entity,menuIds);       return new JsonResult("保留胜利");    }
  1. 客户端要害业务及代码实现

  2. 页面cancel按钮事件处理

  • 业务形容与设计实现

点击页面cancel按钮时,加载菜单那列表页面。

  • 要害代码设计与实现

第一步:事件注册(页面加载实现当前)

$(".box-footer")      .on("click",".btn-cancel",doCancel)

第二步:事件处理函数定义

  function doCancel(){    var url="role/role_list";    $("#mainContentId").load(url);    }
  1. 页面Save按钮事件处理

  • 业务形容与设计实现

点击页面save按钮时,将页面上输出的菜单信息提交到服务端。

  • 要害代码设计与实现

第一步:事件注册(页面加载实现当前)。

 $(".box-footer")      .on("click",".btn-save",doSaveOrUpdate)

第二步:Save按钮事件处理函数定义。要害代码如下:

function doSaveOrUpdate(){      //1.获取表单数据      var params=doGetEditFormData();            //2.异步提交表单数据      var insertUrl="role/doSaveObject";      $.post(insertUrl,params,function(result){          if(result.state==1){              alert(result.message);              doCancel();          }else{              alert(result.message);          }      });  }

第三步:表单数据获取及封装函数定义。要害代码如下:
//获取表单数据

//获取表单数据    function doGetEditFormData(){        var params={            name:$("#nameId").val(),            note:$("#noteId").val()        }        //获取选中的node节点        var menuIds=[];        var  checkedNodes=zTree.getCheckedNodes(true);//zTree        for(var i in checkedNodes){        console.log(checkedNodes[i]);            menuIds.push(checkedNodes[i].id)        }        params.menuIds=menuIds.toString();//(1,2,3,4,5)        return params;    }
  1. 角色批改页面数据出现

  2. 业务时序剖析

点击角色列表页面的编辑按钮,其时序剖析,如图-14所示:

  • 服务端要害业务及代码实现

外围业务:在角色列表页面点击批改按钮时,基于id进行角色信息的查问,在查问角色信息时将角色信息与对应的菜单关系数据封装到到一个值对象,而后传递到客户端在批改页面进行出现,如图-15所示。

  • Pojo定义

  • 业务形容及设计实现

构建值对象(Pojo),用于封装从数据库查问到的角色菜单记录,并增加对应的set/get/toString等办法,便于对数据进行更好的操作。

  • 要害代码剖析及实现
package com.cy.pj.sys.pojo;import lombok.Data;import java.io.Serializable;import java.util.List;@Datapublic class SysRoleMenu implements Serializable {    private static final long serialVersionUID = -2671028987524519218L;    //角色id    private Integer id;    //角色名称    private String name;    //角色备注    private String note;    //角色对应的菜单id    private List<Integer> menuIds;}
  1. DAO接口定义

  • 业务形容与设计实现

负责基于id执行角色数据的查问操作。

  • 要害代码设计与实现

在SysRoleDao接口中定义数据长久化办法:

SysRoleMenu findObjectById(Integer id);
  1. Mapper文件定义

  • 业务形容与设计实现

基于SysRoleDao中findObjectById办法的定义,在映射文件中增加对应的角色查问元素。

  • 要害代码设计与实现

第一步:在SysRoleMapper.xml中增加findObjectById元素,要害代码如下:

 <select id="findObjectById"           resultMap="sysRoleMenu">           select id,name,note           from sys_roles           where id=#{id}           </select>

第二步:在SysRoleMapper.xml中增加第一步中resultMap属性定义的后果映射元素,要害代码如下:

 <!-- resultMap个别用于自定义映射或一些关联查问中 -->   <resultMap type="com.cy.pj.sys.pojo.SysRoleMenu" id="sysRoleMenu">        <!-- 如果基于id做再次执行查问,又心愿将id值存储到值对象,能够对id进行专门映射 -->        <id property="id" column="id"/>        <!-- collection个别利用于one2many查问 -->        <collection property="menuIds"              select="com.cy.pj.sys.dao.SysRoleMenuDao.findMenuIdsByRoleId"              column="id">        </collection>   </resultMap>

第三步:在SysRoleMenuMapper.xml中增加第二步中collection元素外部select属性对应的查问元素。要害代码如下:

 <select id="findMenuIdsByRoleId"resultType="int">            select menu_id            from sys_role_menus            where role_id=#{id}   </select>
  1. Service接口定义及实现

  • 业务形容与设计实现

基于管制层申请,调用数据层办法,查问对应的角色及相干信息。

  • 要害代码设计与实现

第一步:在SysRoleService接口中,增加基于id查问对应角色及相干信息的办法。要害代码如下:

SysRoleMenu findObjectById(Integer id) ;

第二步:在SysRoleService接口对应的实现类SysRoleServiceImpl中增加findObjectById的具体实现。要害代码如下:

@Override    public SysRoleMenuVo findObjectById(Integer id) {        //1.合法性验证        if(id==null||id<=0)throw new IllegalArgumentException("id的值不非法");        //2.执行查问        SysRoleMenuVo result=sysRoleDao.findObjectById(id);          //3.验证后果并返回        if(result==null)throw new ServiceException("此记录曾经不存在");        return result;    }
  1. Controller类定义

  • 业务形容与设计实现

基于管制层申请,调用数据层办法,查问对应的角色及相干信息。

  • 要害代码设计与实现

在SysRoleController类中定义基于角色ID查问角色的办法。要害代码如下:

@RequestMapping("doFindObjectById") public JsonResult doFindObjectById(Integer id){        return new JsonResult(sysRoleService.findObjectById(id)); }
  1. 客户端要害业务及代码实现

  2. 列表页面批改按钮事件处理

  • 业务形容与设计实现

在角色批改按钮上进行事件注册,点击页面批改按钮时,基于角色id向服务端发动异步申请获取角色相干数据,而后加载批改页面。

  • 要害代码设计与实现

第一步:页面加载实现,进行批改按钮事件注册,要害代码如下:

$(function(){      …      //如果是批改        $(".input-group-btn").on("click","btn-update",doLoadEditUI);  });

第二步:批改按钮事件处理函数定义或批改,要害代码如下:

function doLoadEditUI(){      //定义页面题目(内容可能是增加角色也可能是批改角色)      var title;      //断定要执行的操作(是增加还是批改)      if($(this).hasClass("btn-add")){        title="增加角色";         doLoadPageUI(title);      }else{        title="批改角色";        //获取以后行的id值        var id=$(this).parents("tr").data("id");        //依据id查找记录,断定记录是否存在        var url="role/doFindObjectById";        var data={"id":id};        $.getJSON(url,data,function(result){            if(result.state==1){            $("#mainContentId").data("data",result.data)            loadPageUI(title);            }else{             alert(result.message);            }        });      }}  

第三步:定义或批改加载编辑页面的办法。要害代码如下:

 function doLoadPageUI(title){       $("#mainContentId")          .load("role/role_edit",function(){              $(".box-title").html(title);       });    }
  1. 编辑页面菜单数据出现

  • 业务形容与设计实现

页面加载实现,获取编辑页面数据,而后在页面指定地位进行数据出现数据。

  • 要害代码设计与实现

第一步:在角色编辑页面中,菜单数据加载实现当前,获取角色编辑页面中须要的表单数据,而后进行页面数据初始化。要害代码如下:

function doLoadSysMenus(){        var url="menu/doFindZTreeNodes"        $.getJSON(url,function(result){            if(result.state==1){            zTree=$.fn.zTree.init(            $("#menuTree"),setting,result.data);            var data=$("#mainContentId").data("data");            if(data){                doInitEditFormData(data);            }            }else{            alert(result.message);            }        })}

第三步:定义编辑页面数据初始化办法。要害代码如下:

function doInitEditFormData(data){        $("#nameId").val(data.name);        $("#noteId").val(data.note);        //开展所有节点    zTree.expandAll(true);    //勾选角色所领有的菜单    var menuIds = data.menuIds;       for(var i=0; i<menuIds.length; i++) {            //获取key为id值为menuIds[i]的节点            var node = zTree.getNodeByParam("id",menuIds[i]);            //选中以后节点            zTree.checkNode(node,true,false);     }   }
  1. 角色数据更新实现

  2. 业务时序剖析

点击角色编辑页面的更新按钮,其时序剖析,如图-16所示:

  • 服务端要害业务及代码实现

  1. DAO接口实现

  • 业务形容与设计实现

获取角色编辑页面数据,而后异步提交到服务端,将角色信息以及角色对应的菜单关系数据更新到数据库。

  • 要害代码设计与实现

在SysRoleDao接口中增加数据更新办法,要害代码如下:

int updateObject(SysRole entity);
  1. Mapper文件定义

  • 业务形容与设计实现

基于SysRoleDao中updateObject办法的定义,编写用于实现角色更新的SQL元素。

  • 要害代码设计与实现

在SysRoleMapper.xml中增加updateObject元素,用于更新菜单信息。要害代码如下:

<update id="updateObject"parameterType="com.cy.pj.sys.pojo.SysRole">         update sys_roles       set           name=#{name},           note=#{note},           modifiedUser=#{modifiedUser},           modifiedTime=now()        where id=#{id}    </update>
  1. Service接口及实现

  • 业务形容与设计实现

基于管制层申请,对数据进行校验并调用数据层对象将角色信息以及角色菜单关系数据更新到数据库中。

  • 要害代码设计与实现

第一步:在SysRoleService接口中,增加用于更新角色对象的办法。要害代码如下:

int updateObject(SysRole entity,Integer[] menuIds)

第二步:在SysRoleServiceImpl类中,实现更新角色操作。要害代码如下:

@Overridepublic 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.insertObject(entity.getId(),menuIds); //3.返回后果 return rows; }
  1. Controller类定义

  • 业务形容与设计实现

首先接管客户端提交的角色数据,并对其进行封装,而后调用业务层对象对角色信息进行更行更新,最初将业务层处理结果响应到客户端。

  • 要害代码设计与实现

在SysRoleController类中定义更新角色的办法。要害代码如下:

@RequestMapping("doUpdateObject")public JsonResult doUpdateObject(SysRole entity,Integer[] menuIds){ sysRoleService.updateObject(entity,menuIds); return new JsonResult("更新胜利");
  1. 客户端要害业务及代码实现

  2. 编辑页面更新按钮事件处理

  • 业务形容与设计实现

点击页面save按钮时,将页面上输出的角色编辑信息提交到服务端。

  • 要害代码设计与实现

第一步:在角色编辑页面中定义获取角色编辑页面表单数据的函数,要害代码如下:

 function doSaveOrUpdate(){ //1.获取表单数据 var params=doGetEditFormData();var rowData=$("#mainContentId").data("rowData"); //2.定义url var insertUrl="menu/doSaveObject"; var updateUrl="menu/doUpdateObject"; var url=rowData?updateUrl:insertUrl; if(rowData)params.id=rowData.id; //3.异步提交数据 $.post(url,params,function(result){ if(result.state==1){ alert(result.message); doCancel(); }else{ alert(result.message); } }); }

第二步:定义或批改提交编辑页面表单数据办法,要害代码如下:

//点击保留按钮时执行此办法 function doSaveOrUpdate(){//insert/update //获取表单数据 var params=doGetEditFormData(); //如果以后页面.container-fluid对象上绑定着值阐明是批改 var data=$("#mainContentId").data("data"); if(data){ params.id=data.id;//批改时表单数据中须要增加id } //依据当前页面上是否绑定着值来定义url var insertUrl="role/doSaveObject"; var updateUrl="role/doUpdateObject"; var url=data?updateUrl:insertUrl; //异步提交数据 $.post(url,params,function(result){ if(result.state==1){ alert(result.message); doCancel(); }else{ alert(result.message); } }) }
  1. 总结
    =
  2. 重难点剖析

  • 角色数据的删除操作?(关系表中数据的删除)
  • 一对多数据的保留?(保留角色的同时也要保留角色和菜单的关系数据)
  • 一对多数据的查问映射?(基于角色id查问角色信息并将对应的菜单信息也查问进去)
  1. FAQ剖析

  • 角色与菜单之间是什么关系?(Many2Many)
  • 角色与用户之间是什么关系?(Many2Many)
  • 形容一下角色删除业务的实现?
  • 形容一下角色增加业务的实现?
  • 形容一下角色更新业务的实现?
  • 角色和菜单的关系数据如何更新?
  1. BUG剖析

  • 视图解析问题,如图-17所示:


问题剖析:

  1. 查看对应的办法上是否增加@ResponseBody注解。
  2. 查看管制层对象办法的映射门路配置是否正确。