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

用户治理设计说明

业务设计说明

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

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

用户表设计的脚本如下:

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)表关联查问映射,表嵌套查问映射。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理