关于jquery:权限子系统四用户模块

23次阅读

共计 29337 个字符,预计需要花费 74 分钟才能阅读完成。

用户治理设计说明

业务设计说明

本模块次要是实现对用户信息的治理, 包含用户查问, 保留, 更新, 禁用启用等操作, 其业务剖析如下图所示:

基于对表的设计,其数据逻辑关系的展现,如图

用户表设计的脚本如下:

CREATE TABLE `sys_users` (`id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(100) DEFAULT NULL COMMENT '明码',
  `salt` varchar(50) DEFAULT NULL COMMENT '盐',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `mobile` varchar(100) DEFAULT NULL COMMENT '手机号',
  `valid` tinyint(4) DEFAULT NULL COMMENT '状态',
  `deptId` int(11) DEFAULT NULL,
  `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`),
  UNIQUE KEY `username` (`username`)
) 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 '角色 ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户与角色对应关系';

原型设计说明

基于用户需要,通过动态页面为用户出现用户模块的根本需要。
当在主页点击用户治理时,出现用户列表页面,如图

在列表页面点击增加按钮时,出现用户编辑页面, 如图

在编辑页面点击所属部门时,出现部门树结构信息,如图

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

API 设计说明

用户治理业务后盾 API 分层架构及调用关系如图

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

用户治理列表页面出现

业务时序剖析

用户列表页面,其加载时序剖析,如图

服务端实现

Controller 实现

▪ 业务形容与设计实现
基于用户治理的申请业务,在 PageController 中增加返回用户页面相干办法。

▪ 要害代码设计与实现
查看 PageController 中是否有返回 UI 页面的办法,有则无需增加。例如:

@RequestMapping("{module}/{moduleUI}")
public String doModuleUI(@PathVariable String moduleUI) {return "sys/"+moduleUI;}

客户端实现

首页菜单事件处理

▪ 业务形容与设计实现
首先筹备用户列表页面(/templates/pages/sys/user_list.html),而后 starter.html 页面中点击用户治理时异步加载用户列表页面。

▪ 要害代码设计与实现
找到我的项目中的 starter.html 页面,页面加载实现当前,注册用户治理项的点击事件,当点击用户治理时,执行事件处理函数。要害代码如下:

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

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

用户列表页面

▪ 业务形容与设计实现
本页面出现用户信息时要以分页模式进行出现。

▪ 要害代码设计与实现:
参考 sys_user.html 文件内容

用户治理列表数据出现

数据架构剖析

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

阐明:本模块将从数据库查问到的用户及相干数据封装到 SysUserDeptVo 对象,一行记录一个 SysUserDeptVo 对象。
用户列表数据加载, 其时序剖析,如图

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

Vo 类实现

▪ 业务形容及设计实现
构建 pojo 对象,封装从数据库查问到的用户以及用户对应的部门信息,一行记录映射为内存中一个的这样的对象。

▪ 要害代码剖析及实现
定义 SysUserDeptVo 类,基于此类对象属性封装数据。要害代码如下:

package com.cy.pj.sys.pojo.vo;
import java.io.Serializable;
import java.util.Date;
public class SysUserDeptVo implements Serializable {
    private static final long serialVersionUID = 5477389876913514595L;
 private Integer id;
 private String username;
 private String password;//md5
 private String salt;
 private String email;
 private String mobile;
 private Integer valid=1;
 //private SysDept sysDept; //private Integer deptId;
 private Date createdTime;
 private Date modifiedTime;
 private String createdUser;
 private String modifiedUser;
 public Integer getValid() {return valid;}
    public void setValid(Integer valid) {this.valid = valid;}
    public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getUsername() {return username;}
    public void setUsername(String username) {this.username = username;}
    public String getPassword() {return password;}
    public void setPassword(String password) {this.password = password;}
    public String getSalt() {return salt;}
    public void setSalt(String salt) {this.salt = salt;}
    public String getEmail() {return email;}
    public void setEmail(String email) {this.email = email;}
    public String getMobile() {return mobile;}
    public void setMobile(String mobile) {this.mobile = mobile;}
    /*public SysDept getSysDept() {return sysDept;} public void setSysDept(SysDept sysDept) {this.sysDept = sysDept;}*/ public Date getCreatedTime() {return createdTime;}
    public void setCreatedTime(Date createdTime) {this.createdTime = createdTime;}
    public Date getModifiedTime() {return modifiedTime;}
    public void setModifiedTime(Date modifiedTime) {this.modifiedTime = modifiedTime;}
    public String getCreatedUser() {return createdUser;}
    public void setCreatedUser(String createdUser) {this.createdUser = createdUser;}
    public String getModifiedUser() {return modifiedUser;}
    public void setModifiedUser(String modifiedUser) {this.modifiedUser = modifiedUser;}
}

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

Dao 接口实现

▪ 业务形容及设计实现
通过数据层对象,基于业务层的参数数据,查问用户记录总数以及以后页面要出现的用户根本信息。

▪ 要害代码剖析及实现:
第一步:定义用户数据层接口对象,通过此对象实现用户业务的数据操作。代码如下:

@Mapper
public interface SysUserDao {}

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

int getRowCount(String username);

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

List<SysUserDeptVo> findPageObjects(String  username,
                                    Integer startIndex,
                                    Integer pageSize);
Mapper 文件实现

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

▪ 要害代码设计及实现
第一步:在映射文件的设计目录中增加 SysUserMapper.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.SysUserDao">
</mapper>

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

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

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

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

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

<select id="findPageObjects"
 resultMap="sysUserDeptVo">
 select *
 <include refid="queryWhereId"/>
 order by createdTime desc
    limit #{startIndex},#{pageSize}
</select>

第五步:定义查问后果映射元素。代码如下:

<resultMap type="com.cy.pj.sys.vo.SysUserDeptVo"
 id="sysUserDeptVo">
 <!-- 个别利用于 many2one 或 one2one 做关联查问
 在以后利用是基于 deptId 查问部门信息并将其
 存储到 SysUserDeptVo 对象的 sysDept 属性中。-->
 <association property="sysDept"
 column="deptId"
 select="com.cy.pj.sys.dao.SysDeptDao.findById">
 </association></resultMap>

思考:
1) resultMap 用户进行自定义后果映射。
2) association 元素用于定义关联数据的查问。

Service 接口及实现类

▪ 业务形容与设计实现
在用户分页查问中,业务层对象次要负责对业务数据进行校验,并借助数据层对象实现数据的分页查问操作。

▪ 要害代码设计及实现
第一步:定义用户业务接口及办法,裸露外界对用户业务数据的拜访,其代码参考如下:

package com.cy.pj.sys.service;
import com.cy.pj.common.pojo.bo.PageObject;
import com.cy.pj.sys.pojo.vo.SysUserDeptVo;
public interface SysUserService {
    PageObject<SysUserDeptVo> findPageObjects(String username,Integer pageCurrent);
}

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

package com.cy.pj.sys.service.impl;
import com.cy.pj.common.exception.ServiceException;
import com.cy.pj.common.pojo.bo.PageObject;
import com.cy.pj.sys.dao.SysUserDao;
import com.cy.pj.sys.pojo.vo.SysUserDeptVo;
import com.cy.pj.sys.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
     private SysUserDao sysUserDao;
     @Override
     public PageObject<SysUserDeptVo> findPageObjects(String username,Integer pageCurrent) {
            //1. 对参数进行校验
         if(pageCurrent==null||pageCurrent<1)
                    throw new IllegalArgumentException("以后页码值有效");
         //2. 查问总记录数并进行校验
         int rowCount=sysUserDao.getRowCount(username);
         if(rowCount==0)
                    throw new ServiceException("没有找到对应记录");
         //3. 查问当前页记录
         int pageSize=2;
         int startIndex=(pageCurrent-1)*pageSize;
         List<SysUserDeptVo> records=
                        sysUserDao.findPageObjects(username,
         startIndex, pageSize);
         //4. 对查问后果进行封装并返回
         return new PageObject<>(pageCurrent, pageSize, rowCount, records);
     }
}
Controller 类实现

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

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

@RequestMapping("/user/")
@RestController
public class SysUserController {
    @Autowired
 private SysUserService sysUserService;
}

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

@RequestMapping("doFindPageObjects")
public JsonResult doFindPageObjects(String username,Integer pageCurrent) {
    return new JsonResult(
            sysUserService.findPageObjects(username,
 pageCurrent));
}

1.1 客户端要害业务及代码实现

菜单列表信息出现

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

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

$(function(){
       // 为什么要将 doGetObjects 函数写到 load 函数对应的回调外部。$("#pageId").load("doPageUI",function(){doGetObjects();
       });
}

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

 function doGetObjects(){
       //debugger;// 断点调试
       //1. 定义 url 和参数
       var url="user/doFindPageObjects"
       var params={"pageCurrent":1};//pageCurrent=2
       //2. 发动异步申请
       // 请问如下 ajax 申请的回调函数参数名能够是任意吗?能够, 必须合乎标识符的标准
       $.getJSON(url,params,function(result){
           // 请问 result 是一个字符串还是 json 格局的 js 对象?对象
                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){console.log(row);
       var tds="<td><input type='radio'name='radioId'value='"+row.id+"'></td>"+
         "<td>"+row.username+"</td>"+
         "<td>"+(row.sysDept?row.sysDept.name:'未调配')+"</td>"+
         "<td>"+row.email+"</td>"+
         "<td>"+row.mobile+"</td>"+
         "<td>"+(row.valid?"启用":"禁用")+"</td>"+
         "<td>"+new Date(row.createdTime).toLocaleString()+"</td>"+
         "<td>"+new Date(row.modifiedTime).toLocaleString()+"</td>"+
         "<td><button type='button'class='btn btn-default btn-valid'>"+(row.valid?"禁用":"启用")+"</button></td>"; 
       return tds;
   }

用户治理禁用操作实现

外围业务剖析

基于用户在列表页面上抉择的的用户记录 ID,执行禁用或启用操作,后续业务中被禁用的用户不容许登陆零碎。其时序剖析,如图

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

Dao 接口实现

▪ 业务形容及设计实现
基于用户 id,批改用户状态信息,对此用户进行禁用或启用。

▪ 要害代码设计及实现:
在创立 SysUserDao 中增加批改用户状态信息的办法。要害代码如下:

int validById(@Param("id")Integer id,
 @Param("valid")Integer valid,
 @Param("modifiedUser")String modifiedUser);
Mapper 文件实现

▪ 业务形容及设计实现
在 SysUserDao 接口对应的映射文件中增加批改用户状态信息的元素,而后在元素外部定义具体的 SQL 实现。

▪ 要害代码设计与实现
在 SysUserMapper.xml 文件,增加批改用户状态的 SQL 元素定义,要害代码如下:

<update id="validById">
 update sys_users
    set valid=#{valid},
        modifiedUser=#{modifiedUser},
        modifiedTime=now()
    where id=#{id}
</update>
Service 接口及实现类

▪ 业务形容与设计实现
在用户业务层,增加用于实现禁用或启用用户状态的相干业务办法及实现。

▪ 要害代码设计与实现
第一步:在 SysUserService 接口中,增加批改用户装填的办法。要害代码如下:

int validById(Integer id,Integer valid);

第二步:在 SysUserServiceImpl 实现类中增加禁用,启用业务的具体实现。要害代码如下:

@Override
public int validById(Integer id,Integer valid) {
    //1. 合法性验证
 if(id==null||id<=0)
        throw new ServiceException("参数不非法,id="+id);
 if(valid==null||(valid!=1&&valid!=0))
        throw new ServiceException("参数不非法,valid="+valid);
 //2. 执行禁用或启用操作(admin 为后续登陆用户)int rows=sysUserDao.validById(id, valid,"admin");
 //3. 断定后果, 并返回
 if(rows==0)
        throw new ServiceException("此记录可能曾经不存在");
 return rows;
}
Controller 类实现

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

▪ 要害代码设计与实现
第一步:在 SysUserController 中增加用于执行删除业务的办法。代码如下:

@RequestMapping("doValidById")
public JsonResult doValidById(Integer id,Integer valid){sysUserService.validById(id,valid);
 return new JsonResult("update ok");
}

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

http://localhost/user/doValidById?id=10

客户端要害业务及代码实现

用户列表页面事件处理

▪ 业务形容及设计实现
用户在用户列表页面上点击禁用或按钮,将用户记录 id 异步提交到服务端,最初在服务端执行用户的禁用、启用动作。

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

...
$(".input-group-btn")
       .on("click",".btn-valid",doValidById)
...

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

function doValidById(){
       //1. 获取对象 id,validId 的值
       var btn=$(this);//this 执行调用 dom 对象
       var user=btn.parents("tr").data("rowData");
       var id=user.id;
       var valid=user.valid;
       //2. 构建 url, 参数对象
       var url="user/doValidById";
       var params={"id":id,"valid":valid?0:1}
       //3. 发送异步申请, 更新数据
       $.post(url,params,function(result){if(result.state==1){alert(result.message);
               //doGetObjects();// 一种刷新形式
               doEditRow(btn,valid?0:1);// 一种部分刷新形式
           }else{alert(result.message);
           }
       })
   }

第三步:定义禁用、启用操作对应的部分刷新处理函数。要害代码如下:

function doEditRow(btn,valid){
          //1. 批改按钮上内容
          btn.html(valid?"禁用":"启用");
          //2. 批改 td 中元素内容
          var tr=btn.parents("tr");
          tr.find("td:eq(5)").html(valid?"启用":"禁用");
      //3. 批改并从新绑定数据
      var sysUser=tr.data("sysUser");
      sysUser.valid=valid;
      tr.data("sysUser",sysUser);
}

用户增加页面出现

业务时序剖析

在用户列表页面,点击增加按钮时加载编辑页面,其加载时序剖析,如图

筹备用户编辑页面

筹备用户编辑页面(/templates/pages/sys/user_edit.html)

用户编辑页面出现

▪ 业务形容与设计实现
在用户列表页面中点击增加按钮时,出现用户编辑页面。

▪ 要害代码设计与实现
第一步:用户列表事件注册,要害代码如下:

$(document).ready(function(){
    ...    
    $(".input-group-btn")
    .on("click",".btn-add",doLoadEditUI);
});

第二步:定义用户列表页面增加按钮的事件处理函数,要害代码如下:

function doLoadEditUI(){//1. 定义题目(增加或批改)
      var title;
      if($(this).hasClass("btn-add")){title="用户增加";}else{title="用户批改";}
      //2. 异步加载页面
      var url="user/user_edit";
      $("#mainContentId").load(url,function(){$(".box-title").html(title);
      });
 };

用户页面角色出现

外围业务剖析

用户编辑页面出现当前,发动异步工作从服务端获取角色信息而后出现在页面上, 其时序剖析如图

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

Vo 类定义

▪ 业务形容与设计实现
定义 VO 对象,基于此对象封装用户角色信息。

▪ 要害代码设计与实现
创立 CheckBox 类,基于此类对象封装角色 id,角色名信息。要害代码如下:

package com.cy.pj.common.pojo.vo;
import java.io.Serializable;
public class CheckBox implements Serializable {
    private static final long serialVersionUID = 2031967811425337153L;
 private Integer id;
 private String name;
 public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    @Override
 public String toString() {return "CheckBox [id=" + id + ", name=" + name + "]";
 }
}
Dao 接口定义

▪ 业务形容与设计实现
在角色数据层接口中增加查问角色相干信息的办法,并对查问后果进行封装。

▪ 要害代码设计与实现
在 SysRole 增加查问角色 id,name 的相干办法。要害代码如下

List<CheckBox> findObjects();
Mapper 文件实现

▪ 业务形容与设计实现
在角色数据层接口对应的映射文件中,定义角色查问对应的映射元素。

▪ 要害代码设计与实现
在 SysRoleMapper.xml 中增加 findObjects 元素。要害代码如下:

<select id="findObjects"
 resultType="com.cy.pj.common.vo.CheckBox">
 select id,name
         from sys_roles
</select>
Service 接口及实现类

▪ 业务形容与设计实现
在角色业务层接口中增加查问角色 id,name 相干信息的业务办法。

▪ 要害代码设计与实现
第一步:在 SysRoleService 接口中增加 findObjects 办法。要害代码如下:

List<CheckBox> findObjects();

第二步:在 SysRoleService 接口中增加 findObjects 办法实现。要害代码如下:

@Override
public List<CheckBox> findObjects() {return sysRoleDao.findObjects();
}
Controller 类实现

▪ 业务形容与设计实现
在角色管制层对象中增加查问角色 id,name 相干信息的业务办法。

▪ 要害代码设计与实现
在 SysRoleController 中增加 doFindRoles 办法。要害代码如下:

@RequestMapping("doFindRoles")
public JsonResult doFindRoles() {return new JsonResult(sysRoleService.findObjects());
}

客户端要害业务及代码实现

用户编辑页面实现

▪ 业务形容与设计实现
在用户编辑页面加载实现当前,异步加载角色信息,并在页面上进行出现。

▪ 要害代码设计与实现
第一步:页面加载实现当前,异步加载角色相干信息。要害代码如下:

$(document).ready(function(){doLoadSysRoles();
}

第二步:定义异步加载角色信息的办法。要害代码如下:

function doLoadSysRoles(){
     var url="role/doFindObjects";
     $.getJSON(url,function(result){if(result.state==1){
             // 初始化角色信息
            doInitDivSysRoles(result.data);
         }else{alert(result.message);
         }
     })
 };

第三步:定义页面初始化办法,实现页面角色信息的初始化操作。要害代码如下:

// 初始化表单角色数据
 function doInitDivSysRoles(data){var div=$("#rolesId");
     var checkBox=
    "<input type='checkbox'name='roleItem'value='[id]'>[name]";
     for(var i in data){
         div.append(checkBox.replace("[id]",data[i].id)
                  .replace("[name]",data[i].name));
     }
 }

用户数据增加实现

外围业务剖析

用户在编辑页面点击保留按钮时,获取编辑页面用户输出的根本信息异步提交到服务端,实现用户数据的长久化操作。其时序剖析,如图

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

Entity 类定义

▪ 业务形容与设计实现
负责封装用户的根本信息,而后由数据层长久化到数据库。

▪ 要害代码设计与实现
定义 SysUser 类,并通过相干数据封装用户根本信息,要害代码如下:

package com.cy.pj.sys.pojo;
import java.io.Serializable;
import java.util.Date;
public class SysUser implements Serializable {
    private static final long serialVersionUID = 177030063138338860L;
 private Integer id;
 private String username;
 private String password;
 private String salt;// 盐值
 private String email;
 private String mobile;
 private Integer valid=1;
 private Integer deptId;
 private Date createdTime;
 private Date modifiedTime;
 private String createdUser;
 private String modifiedUser;
 public Integer getId() {return id;}
    public void setId(Integer id) {this.id = id;}
    public String getUsername() {return username;}
    public void setUsername(String username) {this.username = username;}
    public String getPassword() {return password;}
    public void setPassword(String password) {this.password = password;}
    public String getSalt() {return salt;}
    public void setSalt(String salt) {this.salt = salt;}
    public String getEmail() {return email;}
    public void setEmail(String email) {this.email = email;}
    public String getMobile() {return mobile;}
    public void setMobile(String mobile) {this.mobile = mobile;}
    public Integer getValid() {return valid;}
    public void setValid(Integer valid) {this.valid = valid;}
    public Date getCreatedTime() {return createdTime;}
    public void setCreatedTime(Date createdTime) {this.createdTime = createdTime;}
    public Date getModifiedTime() {return modifiedTime;}
    public void setModifiedTime(Date modifiedTime) {this.modifiedTime = modifiedTime;}
    public String getCreatedUser() {return createdUser;}
    public void setCreatedUser(String createdUser) {this.createdUser = createdUser;}
    public String getModifiedUser() {return modifiedUser;}
    public void setModifiedUser(String modifiedUser) {this.modifiedUser = modifiedUser;}
}
DAO 接口定义

▪ 业务形容与设计实现
负责将用户提交的用户根本信息,长久化到数据库。

▪ 要害代码设计与实现
在 SysUserDao 接口中定义数据长久化办法:

int insertObject(SysUser sysUser);

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

int insertObjects(@Param("userId")Integer userId,
        @Param("roleIds")Integer[] roleIds);
Mapper 映射文件定义

▪ 业务形容与设计实现
基于 SysUserDao 中办法的定义,在对应的映射文件中增加的对应 SQL 元素。用于将用户信息增加到数据库。

▪ 要害代码设计与实现
第一步: 在 SysUserMapper.xml 中增加 insertObject 元素,用于写入用户信息。要害代码如下:

 <insert id="insertObject"
             parameterType="com.cy.pj.sys.entity.SysUser"
             useGeneratedKeys="true"
             keyProperty="id">
     insert into sys_users
       (username,password,deptId,email,mobile,salt,valid,
       createdTime,modifiedTime,createdUser,modifiedUser)
       values
     (#{username},#{password},#{deptId},#{email},#{mobile},#{salt},#{valid},
       now(),now(),#{createdUser},#{modifiedUser})
</insert>

第二步: 在 SysUserRoleMapper 中元素定义,要害代码如下:

<insert id="insertObjects">
 insert into sys_user_roles
    (user_id,role_id)
    values
    <foreach collection="roleIds" separator="," item="roleId">
 (#{userId},#{roleId})
    </foreach>
</insert>
Service 接口定义及实现

▪ 业务形容与设计实现
基于管制层申请,调用数据层对象将用户以及对应的角色信息写入到数据库中。

▪ 要害代码设计与实现
第一步:在 SysUserService 接口中,增加用于保留用户对象的办法。要害代码如下:

int saveObject(SysUser sysUser, Integer[]roleIds);

第二步:在 SysUserServiceImpl 类中,实现用户保留操作。要害代码如下:

@Override
public int saveObject(SysUser entity, Integer[] roleIds) {long start=System.currentTimeMillis();
     //1. 参数校验
     if(entity==null)
            throw new IllegalArgumentException("保留对象不能为空");
     if(StringUtils.isEmpty(entity.getUsername()))
            throw new IllegalArgumentException("用户名不能为空");
     if(StringUtils.isEmpty(entity.getPassword()))
            throw new IllegalArgumentException("明码不能为空");
     if(roleIds==null || roleIds.length==0)
            throw new IllegalArgumentException("至多要为用户调配角色");
     //2. 保留用户本身信息
     //2.1 对明码进行加密
     String source=entity.getPassword();
     String salt= UUID.randomUUID().toString();
     SimpleHash sh=new SimpleHash(//Shiro 框架
     "MD5",//algorithmName 算法
     source,// 原明码
     salt, // 盐值
     1);//hashIterations 示意加密次数
     entity.setSalt(salt);
     entity.setPassword(sh.toHex());
     int rows=sysUserDao.insertObject(entity);
     //3. 保留用户角色关系数据
     sysUserRoleDao.insertObjects(entity.getId(), roleIds);
     long end=System.currentTimeMillis();
     log.info("end:"+end);
     log.info("total time :"+(end-start));
     //4. 返回后果
     return rows;
}

阐明:应用 SimpleHash 时,要增加一个 shiro 框架依赖

<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.4.1</version>
  </dependency>

阐明:类上加注解开启门面模式的日志输入,同时诸如依赖 sysUserRoleDao

@Service
@Slf4j
public class SysUserServiceImpl implements SysUserService {
    @Autowired
 private SysUserDao sysUserDao;
 @Autowired
 private SysUserRoleDao sysUserRoleDao;
Controller 类定义

▪ 业务形容与设计实现
接管客户端提交的用户相干数据,并对其进行封装,而后调用业务层对象进行业务解决,最初将业务层处理结果响应到客户端。

▪ 要害代码设计与实现
定义 Controller 办法,借助此办法解决保留用户数据的申请和响应逻辑。要害代码如下:

@RequestMapping("doSaveObject")
public JsonResult doSaveObject(
        SysUser entity,
 Integer[] roleIds){sysUserService.saveObject(entity,roleIds);
 return new JsonResult("save ok");
}

客户端要害业务及代码实现

用户编辑页面部门信息出现

▪ 业务形容与设计实现
用户点击所属部门时,异步加载部门信息并以 zTree 构造进行出现,而后用户能够抉择对应的部门,将部门相干信息更新到页面上。

▪ 要害代码设计与实现
第一步:在所有部门相干 dom 元素上进行事件注册,要害代码如下:

$(".form-horizontal")
     .on("click",".load-sys-dept",doLoadZTreeNodes);

第二步:定义事件处理函数,用户出现部门信息,要害代码如下:

function doLoadZTreeNodes(){
      var url="dept/doFindZTreeNodes";
      $("#treeLayer").css("display","block");
      $.getJSON(url,function(result){if(result.state==1){zTree = $.fn.zTree.init($("#zTreeId"),setting,result.data);
          }else{alert(result.message);
          }
      });
 }

第三步:部门 div 容器中注册,确定和勾销事件,要害代码如下:
页面加载实现当前,进行事件注册:

$("#treeLayer")
      .on("click",".btn-cancel",doHideTree)
      .on("click",".btn-confirm",doConfirm);

确定按钮事件处理函数定义:

function doConfirm(){//1. 获取选中的记录(id,name);
      var selectedNodes=zTree.getSelectedNodes();
      var node=selectedNodes[0];
      //2. 将 id 和 name 填写或绑定在具体对象上
      $("#deptId").val(node.name);
      $("#deptId").data("deptId",node.id)
      //3. 暗藏 zTree 对应的 Div
      doHideTree();}

勾销按钮事件处理函数定义:

function doHideTree(){$("#treeLayer").css("display","none");
 }
页面 cancel 按钮事件处理

▪ 业务形容与设计实现
点击页面 cancel 按钮时,加载菜单那列表页面。

▪ 要害代码设计与实现
第一步:事件注册(页面加载实现当前)

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

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

function doCancel(){$("#mainContentId").removeData("rowData");
    $("#mainContentId").load("user/user_list");
 }
页面 Save 按钮事件处理

▪ 业务形容与设计实现
点击页面 save 按钮时,将页面上输出的菜单信息提交到服务端。

▪ 要害代码设计与实现
第一步:事件注册(页面加载实现当前)。

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

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

function doSaveOrUpdate(){
     //1.url
     var insertUrl="user/doSaveObject";
     //2. 获取表单数据
     var params=doGetEditFormData();
     //3. 发动异步申请
     $.post(insertUrl,params,function(result){if(result.state==1){alert(result.message);
             doCancel();}else{alert(result.message);
         }
     })
 }

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

function doGetEditFormData(){
     var params={"username":$("#usernameId").val(),
          "password":$("#passwordId").val(),
          "email":$("#emailId").val(),
          "mobile":$("#phoneId").val(),
          "deptId":$("#deptId").data("deptId"),
     }
     var roleIds=new Array();
     $("#rolesId input[type='checkbox']")
     .each(function(){if($(this).prop("checked")){roleIds.push($(this).val())
         }
     });
     params.roleIds=roleIds.toString();
     console.log(params);
     return params;
     
 }

用户批改页面数据出现

外围业务剖析

基于用户 id 查问用户以及用户对应的部门和角色信息,并将其对应的信息出现在用户编辑页面上,其时序图剖析如图

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

DAO 接口定义

▪ 业务形容与设计实现
负责基于 id 执行用户和角色信息数据的查问操作。

▪ 要害代码设计与实现
在 SysUserDao 接口中定义基于用户 id 查问用户相干信息的办法,要害代码如下:

SysUserDeptVo findObjectById(Integer id);

在 SysUserRoleDao 接口中定义基于用户 id 查问角色 id 信息的办法,要害代码如下:

List<Integer> findRoleIdsByUserId(Integer id);
Mapper 文件定义

▪ 业务形容与设计实现
基于 SysUserDao,SysUserRoleDao 中办法的定义,在映射文件中增加对应的用户查问元素。

▪ 要害代码设计与实现
第一步:在 SysUserMapper.xml 中增加 id 为 findObjectById 的 select 元素,要害代码如下:

<select id="findObjectById"
 parameterType="int"
 resultMap="sysUserDeptVo">
 select * 
from sys_users   
        where id=#{id}     
</select>

第二步:在 SysUserRoleMapper.xml 中增加 id 为 findRoleIdsByUserId 的 select 元素,要害代码如下:

<select id="findRoleIdsByUserId"
 resultType="int">
 select role_id
    from sys_user_roles
    where user_id=#{id}
</select>
Service 接口定义及实现

▪ 业务形容与设计实现
基于管制层申请,调用数据层办法,查问对应的用户及相干信息。

▪ 要害代码设计与实现
第一步:在 SysUserService 接口中,增加基于 id 查问用户及相干信息的办法。要害代码如下:

Map<String,Object> findObjectById(Integer userId) ;

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

@Override
public Map<String, Object> findObjectById(Integer userId) {
    //1. 合法性验证
     if(userId==null||userId<=0)
            throw new IllegalArgumentException("参数数据不非法,userId="+userId);
     //2. 业务查问
     SysUserDeptVo user=
                sysUserDao.findObjectById(userId);
     if(user==null)
            throw new ServiceException("此用户曾经不存在");
     List<Integer> roleIds=
                sysUserRoleDao.findRoleIdsByUserId(userId);
     //3. 数据封装
     Map<String,Object> map=new HashMap<>();
     map.put("user", user);
     map.put("roleIds", roleIds);
     return map;
}
Controller 类定义

▪ 业务形容与设计实现
基于客户端申请,调用业务层办法,查问对应的用户及相干信息。

▪ 要害代码设计与实现
在 SysUserController 类中定义基于用户 ID 查问用户的相干办法。要害代码如下:

@RequestMapping("doFindObjectById")
public JsonResult doFindObjectById(Integer id){
    Map<String,Object> map=
            sysUserService.findObjectById(id);
 return new JsonResult(map);
}

客户端要害业务及代码实现

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

▪ 业务形容与设计实现
在用户列表批改按钮上进行事件注册,点击页面批改按钮时,基于用户 id 向服务端发动异步申请获取用户相干数据,而后加载批改页面。

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

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

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

function doLoadEditUI(){
       //1. 断定点击的对象
       var title;
       if($(this).hasClass("btn-add")){
           title="增加用户";
           doLoadPage(title);
       }else if($(this).hasClass("btn-update")){
           title="批改用户";
           var id=$("tbody input[name='radioId']:checked").val();
           console.log("id="+id)
           if(!id){alert("请先抉择");
              return;
           }
           // 基于 id 进行查问并加载编辑页面
           doFindObjectById(id,title);
       }
   }

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

function doLoadPage(title){
       var url="user/user_edit"
       $("#mainContentId").load(url,function(){$(".box-title").html(title);
       }) 
   }

第四步:定义基于 id 查问用户信息的办法。要害代码如下:

function doFindObjectById(id,title){
       //1.params
       var params={"id":id};
       //2.url
       var url="user/doFindObjectById";
       //3.ajax request
       $.getJSON(url,params,function(result){//JsonResult
           if(result.state==1){$("#mainContentId").data("rowData",result.data); 
              doLoadPage(title);
           }else{alert(result.message);
           }
       });
   }
编辑页面角色数据出现

▪ 业务形容与设计实现
页面加载实现,获取编辑页面数据,而后在页面指定地位进行数据出现数据。

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

function doLoadRoles(){
     var url="role/doFindRoles"
     $.getJSON(url,function(result){if(result.state==1){doInitPageRoles(result.data);
          doInitFormData();// 批改时}else{alert(result.message);
         }
     })
 }

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

function doInitFormData(){var data=$("#mainContentId").data("rowData");
     if(!data)return;
     $("#pwdDiv").remove();
     console.log(data);
     // 初始化用户信息 
     $("#usernameId").val(data.user.username);
     $("#deptId").val(data.user.sysDept?data.user.sysDept.name:'');
     $("#deptId").data("deptId",data.user.sysDept?data.user.sysDept.id:'');
     $("#emailId").val(data.user.email);
     $("#phoneId").val(data.user.mobile);
     // 初始化用户角色信息
     var ids=data.roleIds;
     for(var i in ids){$("#rolesId input[value='"+ids[i]+"']")
      .prop("checked",true);
     }
 }

用户数据更新实现

外围业务剖析

在用户编辑页面点击更新按钮时,异步提交数据到服务端,服务端要更新用户本身信息以及用户和角色关系数据,其时序图剖析,如图

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

DAO 接口实现

▪ 业务形容与设计实现
获取用户编辑页面数据,而后异步提交到服务端,将用户信息以及用户对应的角色关系数据更新到数据库。

▪ 要害代码设计与实现
第一步:在 SysUserDao 接口中增加数据更新办法,要害代码如下:

int updateObject(SysUser sysUser);

第二步:在 SysUserRoleDao 接口中增加基于用户 id 删除关系数据的办法,要害代码如下:

int deleteObjectsByUserId(Integer userId);
Mapper 文件定义

▪ 业务形容与设计实现
基于 SysUserDao,SysUserRoleDao 中办法的定义,编写用于实现用户更新的 SQL 元素。

▪ 要害代码设计与实现
第一步:在 SysUserMapper.xml 中增加 updateObject 元素,用于更新菜单信息。要害代码如下:

 <update id="updateObject"
 parameterType="com.cy.pj.sys.entity.SysUser">
 update sys_users
     set username=#{username},
         mobile=#{mobile},
         email=#{email},
         deptId=#{deptId},
         modifiedTime=now(),
         modifiedUser=#{modifiedUser}
      where id=#{id}
</update>

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

 <delete id="deleteObjectsByUserId"
     parameterType="int">
     delete from sys_user_roles
      where user_id=#{userId}          
</delete>
Service 接口及实现

▪ 业务形容与设计实现
基于管制层申请,对数据进行校验并调用数据层对象将角色信息以及角色菜单关系数据更新到数据库中。

▪ 要害代码设计与实现
第一步:在 SysUserService 接口中,增加用于更新角色对象的办法。要害代码如下:

int updateObject(SysUser entity,Integer[] roleIds);

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

@Override
public int updateObject(SysUser entity,Integer[] roleIds) {
    //1. 参数有效性验证
     if(entity==null)
            throw new IllegalArgumentException("保留对象不能为空");
     if(StringUtils.isEmpty(entity.getUsername()))
            throw new IllegalArgumentException("用户名不能为空");
     if(roleIds==null||roleIds.length==0)
            throw new IllegalArgumentException("必须为其指定角色");
     // 其它验证本人实现,例如用户名曾经存在,明码长度,...
     //2. 更新用户本身信息
     int rows=sysUserDao.updateObject(entity);
     //3. 保留用户与角色关系数据
     sysUserRoleDao.deleteObjectsByUserId(entity.getId());
     sysUserRoleDao.insertObjects(entity.getId(),
     roleIds);
     //4. 返回后果
     return rows;
}
Controller 类定义

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

▪ 要害代码设计与实现
在 SysUserController 类中定义更新角色的办法。要害代码如下:

@RequestMapping("doUpdateObject")
public JsonResult doUpdateObject(SysUser entity,Integer[] roleIds){sysUserService.updateObject(entity,roleIds);
 return new JsonResult("update ok");
}

客户端要害业务及代码实现

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

▪ 业务形容与设计实现
点击页面 save 按钮时,将页面上输出的用户编辑信息异步提交到服务端进行更新。

▪ 要害代码设计与实现
批改用户编辑页面中保留表单数据的 JS 函数,要害代码如下:

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

批改明码页面出现

服务端要害业务设计及实现

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

@RequestMapping("{module}/{moduleUI}")
public String doModuleUI(@PathVariable String moduleUI) {return "sys/"+moduleUI;}

客户端要害业务设计及实现

筹备明码编辑页面

筹备明码编辑页面(/templates/pages/sys/pwd_edit.html)

明码编辑页面出现

▪ 业务形容与设计实现
在零碎首页左侧操作菜单中点击批改明码时,出现明码编辑页面。

▪ 要害代码设计与实现
在 starter.html 页面尾部的页面加载实现的事件处理函数中增加事件处理,要害代码如下:

$(function(){
     …
     doLoadUI("load-user-id","user/user_list")
})
function doLoadUI(id,url){$("#"+id).click(function(){$("#mainContentId").load(url);
    });
}

明码批改页面数据长久化实现

服务端要害业务设计及实现

DAO 接口定义

▪ 业务形容及设计实现
基于用户 id,批改用户明码和盐值。

▪ 要害代码设计及实现:
在创立 SysUserDao 中增加批改用户明码信息的办法。要害代码如下:

int updatePassword(@Param("password")String password,
 @Param("salt")String salt,
 @Param("id")Integer id);
Mapper 映射文件定义

▪ 业务形容及设计实现
基于用户 SysUserDao 中批改明码办法的定义,在映射文件中定义映射元素。

▪ 要害代码设计及实现:
在创立 SysUserMapper.xml 中定义批改明码对应的映射元素。要害代码如下:

<update id="updatePassword">
 update sys_users
     set password=#{password},
         salt=#{salt},
         modifiedTime=now()
     where id=#{id}
</update>
Service 接口定义及实现

▪ 业务形容及设计实现
基于管制层提交的用户相干信息,实现批改明码业务。

▪ 要害代码设计及实现:
第一步:在 SysUserService 接口中增加,用于实现明码批改业务的办法。要害代码如下:

int updatePassword(String password,
 String newPassword,
 String cfgPassword);

第二步:在 SysUserService 接口的实现类 SysUserServiceImpl 中增加明码批改业务的具体实现。要害代码如下:

@Override
public int updatePassword(String password, String newPassword,
 String cfgPassword) {
     //1. 断定新密码与明码确认是否雷同
     if(StringUtils.isEmpty(newPassword))
            throw new IllegalArgumentException("新密码不能为空");
     if(StringUtils.isEmpty(cfgPassword))
            throw new IllegalArgumentException("确认明码不能为空");
     if(!newPassword.equals(cfgPassword))
            throw new IllegalArgumentException("两次输出的明码不相等");
     //2. 断定原明码是否正确
     if(StringUtils.isEmpty(password))
            throw new IllegalArgumentException("原明码不能为空");
     // 获取登陆用户
     SysUser user=(SysUser) SecurityUtils.getSubject().getPrincipal();
     SimpleHash sh=new SimpleHash("MD5",
     password, user.getSalt(), 1);
     if(!user.getPassword().equals(sh.toHex()))
            throw new IllegalArgumentException("原明码不正确");
     //3. 对新密码进行加密
     String salt=UUID.randomUUID().toString();
     sh=new SimpleHash("MD5",newPassword,salt, 1);
     //4. 将新密码加密当前的后果更新到数据库
     int rows=sysUserDao.updatePassword(sh.toHex(), salt,user.getId());
     if(rows==0)
            throw new ServiceException("批改失败");
     return rows;
}
Controller 类定义

▪ 业务形容及设计实现
基于客户端提交的批改明码申请,定义解决申请的相干办法及映射。

▪ 要害代码设计及实现:
在 SysUserController 类中增加用于实现明码批改的管制层办法。要害代码如下:

@RequestMapping("doUpdatePassword")
public JsonResult doUpdatePassword(
        String pwd,
 String newPwd,
 String cfgPwd) {sysUserService.updatePassword(pwd, newPwd, cfgPwd);
 return new JsonResult("update ok");
}

客户端要害业务设计及实现

▪ 业务形容及设计实现
获取批改页面表单中用户填写的数据,而后向服务端发动异步申请进行数据更新。

▪ 要害代码设计及实现:
第一步:对保留和勾销按钮进行事件注册,要害代码如下:

$(function(){$(".box-footer")
       .on("click",".btn-cancel",doCancel)
       .on("click",".btn-save",doUpdateObject)
   });

第二步:定义保留和勾销事件处理函数,要害代码如下:

function doCancel(){$("#mainContentId").html("");
   }
function doUpdateObject(){
       //1. 获取用户提交数据
       var params={pwd:$("#pwdId").val(),
                  newPwd:$("d").val(),
                  cfgPwd:$("#cfgPwdId")#newPwdI.val()}
       //2. 定义申请的 url
       var url="user/doUpdatePassword"
       //3. 异步提交申请, 执行更新操作
       $.post(url,params,function(result){alert(result.message);
       })
   }

总结

重难点剖析

▪ 一对多数据的保留?(保留用户信息,保留用户和角色的关系数据)
▪ 多对一数据的查问映射?(查问用户时查问用户对应的部门信息)。
▪ 用户明码的加密实现?(对用户明码进行 MD5 盐值加密)

FAQ 剖析

▪ 用户与角色之间是什么关系?(Many2Many)
▪ 形容一下用户查问业务的实现?
▪ 形容一下用户增加业务的实现?
▪ 形容一下用户更新业务的实现?
▪ resultMap 元素利用场景?

1)表中字段名与内存中的映射对象属性不统一(set 办法不匹配)
2)表关联查问映射,表嵌套查问映射。

正文完
 0