知识点:
1.内查询使用
2.pagehelper的使用:
1.引入坐标
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
2.修改service实现类代码
@Override
public PageObject<SysLog> findPageObjects(String userName, Integer pageCurrent) {
if (pageCurrent == null || pageCurrent < 1) {
throw new IllegalArgumentException("当前页码不正确");
}
int pageSize =10;
PageHelper.startPage(pageCurrent, pageSize, true);//true是否进行count查询
PageHelper.orderBy("createdTime desc");
List<SysLog> records = sysLogDao.findByPageHelper(userName);
PageInfo<SysLog> pageInfo = new PageInfo<SysLog>(records);
int total = (int)pageInfo.getTotal();
return new PageObject<>(pageCurrent, pageSize, total, records);
}
3.Mybatis中Mapper映射文件的输入和输出:
1.输入类型:parameterType
1)传入简单类型:
<select id=“findById” parametertype="int">
2)传入pojo对象
<select id=“findById” parametertype="com.cy.pj.sys.User">
3)传入pojo包装对象
public class QueryVo {
private String query;
private User user;
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
在UserMapper中定义方法
```css
**
* 根据QueryVo提供的数据进行查询
* @param vo
* @return
*/
User getUserByQueryVo(QueryVo vo);
UserMapper.xml映射文件
<select id="getUserByQueryVo" parameterType="com.oak.po.QueryVo">
select * from `user` where id=#{user.id} and name=#{user.name}
</select>
输出类型(resultType):
1)简单类型输出
2)pojo对象输出:
3)输出pojo列表(返回值为集合)
业务设计说明
本模块主要是实现对用户信息的管理,包括用户查询,保存,更新,禁用启用等操作,其业务分析如下图所示
基于对表的设计,其数据逻辑关系的展示:
原型设计说明
基于用户需求,通过静态页面为用户呈现用户模块的基本需求。
当在主页点击用户管理时,呈现用户列表页面,如图
在列表页面点击添加按钮时,呈现用户编辑页面,
在编辑页面点击所属部门时,呈现部门树结构信息
说明:假如客户对此原型进行了确认,后续则可以基于此原型进行研发。
API设计说明
说明:分层目的主要将复杂问题简单化,实现各司其职,各尽所能。
业务时序分析
用户列表页面,其加载时序分析,如图
服务端实现
PageController中
@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异步请求函数
数据架构分析
用户列表页面加载完成,启动用户数据的异步加载操作,本次列表页面要以分页形式呈现用户信息,其数据查询时,数据的封装及传递过程,如图
说明:本模块将从数据库查询到的用户及相关数据封装到SysUserDeptVo对象,一行记录一个SysUserDeptVo对象。
用户列表数据加载,其时序分析
服务端
SysUserDeptVo类
package com.cy.pj.sys.vo;
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 {
int getRowCount( String username);
String username,
Integer startIndex,
Integer pageSize);
}
Mapper文件
from sys_users
username like concat("%",# {username},"%")
{startIndex},#{pageSize}
"com.cy.pj.sys.vo.SysUserDeptVo"
id="sysUserDeptVo">
"sysDept"
column="deptId"
select="com.cy.pj.sys.dao.SysDeptDao.findById">
Service接口
package com.cy.pj.sys.service;
public interface SysUserService {
PageObject findPageObjects(
String username,Integer pageCurrent);
}
package com.cy.pj.sys.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class SysUserServiceImpl implements SysUserService {
@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类
package com.cy.pj.sys.controller;
@RequestMapping("/user/")
@RestController
public class SysUserController {
@Autowired
private SysUserService sysUserService;
@RequestMapping("doFindPageObjects")
public JsonResult doFindPageObjects(
String username,Integer pageCurrent) {
return new JsonResult(
sysUserService.findPageObjects(name,
pageCurrent));
}
}
客户端关键业务及代码实现
角色分页页面加载完成以后,向服务端发起异步请求加载角色信息,当角色信息加载完成需要将角色信息、分页信息呈现到列表页面上。
异步请求处理函数,关键代码如下:
第一步:分页页面加载完成,向服务端发起异步请求,代码参考如下:
$(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=$(" ");
//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=" "+
""+row.username+" "+
""+(row.sysDept?row.sysDept.name:'未分配')+" "+
""+row.email+" "+
""+row.mobile+" "+
""+(row.valid?"启用":"禁用")+" "+
""+new Date(row.createdTime).toLocaleString()+" "+
""+new Date(row.modifiedTime).toLocaleString()+" "+
" ";
return tds;
}
核心业务分析
基于用户在列表页面上选择的的用户记录ID,执行禁用或启用操作,后续业务中被禁用的用户不允许登陆系统。 其时序分析,如图
服务端关键业务及代码实现
创建SysUserDao中添加修改用户状态信息的方法
int validById(
@Param("id")Integer id,
@Param("valid")Integer valid,
@Param("modifiedUser")String modifiedUser);
在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!=1&&valid!=0)
throw new ServiceException("参数不合法,valie="+valid);
if(StringUtils.isEmpty(modifiedUser))
throw new ServiceException("修改用户不能为空");
//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:3306/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);
});
};
用户编辑页面呈现以后,发起异步任务从服务端获取角色信息然后呈现在页面上,其时序分析如图
服务端关键业务及代码实现
创建CheckBox类,基于此类对象封装角色id,角色名信息。
package com.cy.pj.common.vo;
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();
在SysRoleMapper.xml中添加findObjects元素。
<select id="findObjects"
resultType="com.cy.pj.common.vo.CheckBox">
select id,name
from sys_roles
</select>
Service接口及实现类
第一步:在SysRoleService接口中添加findObjects方法。
List<CheckBox> findObjects();
第二步:在SysRoleService接口中添加findObjects方法实现。
@Override
public List<CheckBox> findObjects() {
return sysRoleDao.findObjects();
}
Controller类实现
@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=
"[name]";
for(var i in data){
div.append(
checkBox.replace("[id]",data[i].id)
.replace("[name]",data[i].name));
}
}
用户在编辑页面点击保存按钮时,获取编辑页面用户输入的基本信息异步提交到服务端,实现用户数据的持久化操作。其时序分析,如图
服务端关键业务及代码实现
定义SysUser类,并通过相关数据封装用户基本信息,关键代码如下:
package com.cy.pj.sys.entity;
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;
}
}
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 entity,Integer[]roleIds);
第二步:在SysUserServiceImpl类中,实现用户保存操作。关键代码如下:
@Override
public int saveObject(SysUser entity, Integer[] roleIds) {
long start=System.currentTimeMillis();
log.info("start:"+start);
//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();
//Spring框架内置的DigestUtils工具类
// String hashedPwd=DigestUtils.md5DigestAsHex((salt+entity.getPassword()).getBytes());
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;
}
MD5加密特点:不可逆,相同内容加密结果一定相同
//1.对密码进行加密(本次使用MD5加密)
String source=entity.getPassword();
String salt=UUID.randomUUID().toString();//随机字符串作为加密盐
//Spring框架内置的DigestUtils工具类实现加密
String hashedPwd=DigestUtils.md5DigestAsHex((salt+entity.getPassword()).getBytes());
//基于shiro框架中的api进行加密
SimpleHash sh=new SimpleHash(
"MD5",//algorithmName算法名称
source,
salt,
1//hashIterations 加密次数,加密次数越多安全性越好
);
entity.setSalt(salt);
entity.setPassword(sh.toHex());//机密结果转化为16进制
说明:使用SimpleHash时,要添加一个shiro框架依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
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按钮事件处理
第一步:事件注册(页面加载完成以后)
$(".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;
}
服务端关键业务及代码实现
SysUserDao接口
SysUserDeptVo findObjectById(Integer id);
SysUserRoleDao接口
List<Integer> findRoleIdsByUserId(Integer id);
Mapper文件定义
第一步:在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);
}
客户端关键业务及代码实现
第一步:页面加载完成,进行修改按钮事件注册,关键代码如下:
$(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);
}
}
核心业务分析
在用户编辑页面点击更新按钮时,异步提交数据到服务端,服务端要更新用户自身信息以及用户和角色关系数据,其时序图分析,如图
服务端关键业务及代码实现
获取用户编辑页面数据,然后异步提交到服务端,将用户信息以及用户对应的角色关系数据更新到数据库。
第一步:在SysUserDao接口中添加数据更新方法,关键代码如下:
int updateObject(SysUser entity);
第二步:在SysUserRoleDao接口中添加基于用户id删除关系数据的方法,关键代码如下:
int deleteObjectsByUserId(Integer userId);
Mapper文件定义
第一步:在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);
}
})
}