Springmvc+Shiro+zTree 实战(二):角色管理AND用户管理

角色管理模块:

新增角色:重点在于zTree这部分,这个功能等会做详细介绍

编辑角色:难点在于zTree默认选中用户已拥有的权限,这个功能只介绍数据的回显

删除角色:因为这个功能比较简单,所以直接省略,不过要注意以下两点

1:删除角色时,需要删除role_permission中对应的数据:

2:删除角色时,要考虑到如果有用户绑定了这个角色,那么需要根据自己系统的业务需求来做相应的处理

 

这篇博客难点就是zTree,不熟悉的朋友可以学习一下zTree案例

地址:https://blog.csdn.net/qq_37936542/article/details/78429675

 

角色新增:

新增页面展示:因为前端技术有限,我们只着重介绍zTree和后端逻辑

 

一:封装pojo

角色:

import java.util.List;

public class Role {
	
	private Integer id;
	private String roleName;
	private String roleDesc;
	/**
	 * 因为做这个功能时,前端需要封装权限id的list集合上传,但是我直接用List<Integer> permissions这个属性接收一直报错,
	 * 无奈之下,只能在前端将权限id的list集合json化,然后用perms属性接收再反序列化成list保存。
	 * 如果大家直接实现了List<Integer> permissions属性接收,请赐教
	 */
	private String perms;
	private List<Integer> permissions;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getRoleName() {
		return roleName;
	}
	public void setRoleName(String roleName) {
		this.roleName = roleName;
	}
	public String getRoleDesc() {
		return roleDesc;
	}
	public void setRoleDesc(String roleDesc) {
		this.roleDesc = roleDesc;
	}
	public List<Integer> getPermissions() {
		return permissions;
	}
	public void setPermissions(List<Integer> permissions) {
		this.permissions = permissions;
	}
	
	public String getPerms() {
		return perms;
	}
	public void setPerms(String perms) {
		this.perms = perms;
	}
	@Override
	public String toString() {
		return "Role [id=" + id + ", roleName=" + roleName + ", roleDesc="
				+ roleDesc + ", permissions=" + permissions + ", perms="
				+ perms + "]";
	}
}

zTree节点:

public class Node {

	// 节点id
	private Integer id;
	// 父节点id
	private Integer pId;
	// 节点名称
	private String name;
	// 需要自定义图片时,使用该属性
	private String iconSkin;
	// 通过该属性,设置图片
	private Integer level;
	// 当需要设置某个节点被选中的时候,通过该属性定义
	private Boolean checked;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Integer getpId() {
		return pId;
	}
	public void setpId(Integer pId) {
		this.pId = pId;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getIconSkin() {//根据level的值来返回节点图片
		String icon;
		switch(this.level){
		case 0:
			icon = "icon0";
		    break;
		case 1:
			icon = "icon1";
			break;
		case 2:
			icon = "icon2";
			break;
		default:
			icon = "icon3";
		    break;
		}
		return icon;
	}
	public Integer getLevel() {
		return level;
	}
	public void setLevel(Integer level) {
		this.level = level;
	}
	public Boolean getChecked() {
		return checked;
	}
	public void setChecked(Boolean checked) {
		this.checked = checked;
	}
	@Override
	public String toString() {
		return "Node [id=" + id + ", pId=" + pId + ", name=" + name
				+ ", iconSkin=" + iconSkin + ", level=" + level + ", checked="
				+ checked + "]";
	}

}

 

二:页面引入zTree相关js、css

<link rel="stylesheet" href="js/ztree_v3/css/zTreeStyle/zTreeStyle.css"
	type="text/css">

<script src="js/jquery.min.js"></script>
<script src="js/jquery.ztree.core-3.5.min.js"></script>
<script src="js/jquery.ztree.excheck-3.5.min.js"></script>
<script src="js/jquery.ztree.exedit-3.5.min.js"></script>

三:准备zTree容器

<!-- 这里需要注意class需要设置为ztree,否则可能会导致树的css样式不起作用 -->
<div>
   <ul id="ztree" class="ztree"></ul>
</div>

四:页面js

$(function() {
			
			//zTree相关代码=======================
			var zTreeObj;

			initTree();//加载zTree
			
			function initTree() {//zTree初始化函数
				$.get("role/tree.do", function(data) {
					zTreeObj = $.fn.zTree.init($("#ztree"), setting, data);
					// zTreeObj.expandAll(true); //直接展开树结构
				});
			}
			var setting = {
				check : {// 定义是否显示单选和复选框
					enable : true,
					chkStyle : "checkbox",
					chkboxType : {// 勾选 checkbox 对于父子节点的关联关系
						"Y" : "s",
						"N" : "s"
					}
				},
				data : {// 节点数据系列的属性配置
					simpleData : {
						enable : true,
						idKey : "id",// 节点数据中保存唯一标识的属性名称 默认值:"id"
						pIdKey : "pId"// 节点数据中保存其父节点唯一标识的属性名称 默认值:"pId"
					}
				},
			};
			//zTree相关代码结束 ============================

			$("#addBtn").on("click", function() {//添加按钮点击事件

				//获取选中权限节点id的集合
				var nodes = zTreeObj.getCheckedNodes(true);
				if(nodes.length == 0){
					layer.alert("权限不可为空")
					return;
				}
				var _list = [];
				for (var i = 0; i < nodes.length; i++) {
					_list.push(nodes[i].id)
				}
				
				//字段非空验证
				if (validate())
					return;

				$.ajax({
					url : basePath + "/role.do",
					data : {
						"roleName" : $("#roleName").val(),
						"roleDesc" : $("#roleDesc").val(),
						"perms" : JSON.stringify(_list),
					},
					type : "POST",
					success : function(data) {
						layer.alert("操作成功")
					},
					error : function(data) {
						layer.alert("操作失败")
					}

				});

			})
			
			//字段的非空验证
			function validate() {
				if ($("#roleName").val() == '') {
					$("#validateName").html("角色名称不可为空");
					$("#validateDesc").html("");
					return true;
				}
				if ($("#roleDesc").val() == '') {
					$("#validateName").html("");
					$("#validateDesc").html("角色描述不可为空");
					return true;
				}
				return false;
			}
		});

五:后台请求

1:zTree初始化请求

<!-- Controller代码 -->
@GetMapping("/tree")
@ResponseBody
public ResponseEntity<List<Node>> tree() {
	try {
		List<Node> nodes = roleService.getNodes();
		return new ResponseEntity<List<Node>>(nodes, HttpStatus.OK);
	} catch (Exception e) {
		log.error("获取权限节点失败", e);
		return new ResponseEntity<List<Node>>(
				HttpStatus.INTERNAL_SERVER_ERROR);
	}
}



<!-- sql语句 -->
<select id="getNodes" resultType="com.mote.pojo.Node">
	SELECT p.id id, p.parent_id
	p_id, p.perm_desc name, p.`level` `level` FROM
	permission p
</select>

2:新增按钮点击请求

<!-- jackson工具依赖 -->
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-core</artifactId>
	<version>2.7.3</version>
</dependency>
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-annotations</artifactId>
	<version>2.7.3</version>
</dependency>
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
	<version>2.7.3</version>
</dependency>



<!-- Controller代码 -->
@PostMapping()
@ResponseBody
public ResponseEntity<Integer> addRole(Role role) {
	try {
		roleService.addRole(role);
		return new ResponseEntity<Integer>(Common.common_success,
				HttpStatus.OK);
	    } catch (Exception e) {
			log.error("添加角色失败", e);
			return new ResponseEntity<Integer>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}


<!-- Service代码,这个方法需要加事务控制 -->
public int addRole(Role role) throws Exception {
        //jackson
		ObjectMapper mapper = new ObjectMapper();
		// 添加角色返回主键
		roleDao.addRole(role);
		// 将string转成list
		JavaType jt = mapper.getTypeFactory().constructParametricType(
				ArrayList.class, Integer.class);
		List<Integer> list = mapper.readValue(role.getPerms(), jt);

		role.setPermissions(list);

		// 添加角色-权限
		return roleDao.addRolePrem(role);
	}


<!-- sql语句 -->
<insert id="addRole" useGeneratedKeys="true" keyProperty="id">
	INSERT
		INTO role (role_name, role_desc) VALUES (#{roleName},#{roleDesc});
</insert>

<insert id="addRolePrem">
	INSERT INTO role_permission (role_id, perm_id) VALUES
	<foreach collection="permissions" item="perm" separator=",">
		(#{id}, #{perm})
	</foreach>
</insert>

 

六:页面css(实现zTree的自定义图片)

<style>
<!-- icon0_ico_open:level为0的节点打开时显示的图片,img/house.png:图片路径 -->
.ztree li span.button.icon0_ico_open {
	margin-right: 2px;
	background: url(img/house.png) no-repeat scroll 0 0 transparent;
	vertical-align: top;
	*vertical-align: middle
}
<!-- icon0_ico_close:level为0的节点关闭时显示的图片,img/house.png:图片路径 -->
.ztree li span.button.icon0_ico_close {
	margin-right: 2px;
	background: url(img/house.png) no-repeat scroll 0 0 transparent;
	vertical-align: top;
	*vertical-align: middle
}

.ztree li span.button.icon1_ico_open {
	margin-right: 2px;
	background: url(img/doc.png) no-repeat scroll 0 0 transparent;
	vertical-align: top;
	*vertical-align: middle
}

.ztree li span.button.icon1_ico_close {
	margin-right: 2px;
	background: url(img/doc.png) no-repeat scroll 0 0 transparent;
	vertical-align: top;
	*vertical-align: middle
}

.ztree li span.button.icon2_ico_open {
	margin-right: 2px;
	background: url(img/permission.png) no-repeat scroll 0 0 transparent;
	vertical-align: top;
	*vertical-align: middle
}

.ztree li span.button.icon2_ico_close {
	margin-right: 2px;
	background: url(img/permission.png) no-repeat scroll 0 0 transparent;
	vertical-align: top;
	*vertical-align: middle
}
<!-- icon3_ico_docu:level为3的子节点显示的图片 -->
.ztree li span.button.icon3_ico_docu {
	margin-right: 2px;
	background: url(img/permission.png) no-repeat scroll 0 0 transparent;
	vertical-align: top;
	*vertical-align: middle
}
</style>

 

角色编辑:

效果展示:回显的时候,zTree默认选中用户的权限节点(Node的checked属性为true即为选中)

数据回显的实现逻辑:

点击更新按钮,进入后台,查询出role相关属性,再跳转到角色更新界面,到了界面以后,zTree通过ajax请求去后台查询权限节点数据进行显示。

1:跳转更新界面请求

<!-- Controller代码 -->
@GetMapping("/toUpdRole/{id}")
public ModelAndView toUpdRole(@PathVariable("id") Integer id) {

	ModelAndView mv = new ModelAndView();
	try {
			Role role = roleService.getRole(id);
			mv.addObject("role", role);
		} catch (Exception e) {
			log.error("跳转更新角色页面失败", e);
			mv.setViewName("404");
			return mv;
		}
		mv.setViewName("role/editrole");
		return mv;

	}


<!-- sql语句 -->
<select id="getRole" resultType="com.mote.pojo.Role">
	SELECT * FROM role WHERE id = #{id}
</select>

2,zTree初始化请求

<!-- Controller代码 -->
@GetMapping("/permTree")
@ResponseBody
public ResponseEntity<List<Node>> permTree(@RequestParam("id")Integer id) {
	try {
		List<Node> nodes = roleService.getPermNodes(id);
		return new ResponseEntity<List<Node>>(nodes, HttpStatus.OK);
	} catch (Exception e) {
		log.error("获取权限节点失败", e);
		return new ResponseEntity<List<Node>>(
					HttpStatus.INTERNAL_SERVER_ERROR);
	}
}



<!-- sql语句 -->
<select id="getPermNodes" resultType="com.mote.pojo.Node">
	SELECT p.id,p.parent_id pid,p.perm_desc NAME,p.`level`,
	IF (p.id IN (
	SELECT perm_id FROM role_permission WHERE role_id = #{id}
	), TRUE,FALSE) checked
	FROM permission p
</select>

 

 

用户管理模块

用户添加、用户编辑、用户删除,相比较角色模块,这三个功能实现起来比较简单。就简单展示一下页面结构。

 

用户管理主页:

 

1,新增用户(页面需要的数据:所有的角色)

注意:数据库保存用户密码时,使用shiro自带的MD5撒盐加密

@PostMapping()
	@ResponseBody
	public ResponseEntity<Integer> addUser(User user) {
		try{
			User flag = userService.getUserByName(user.getUserName());//验证用户名
			if(flag != null)
				return new ResponseEntity<Integer>(Common.common_fail, HttpStatus.OK);
			
			Md5Hash pwd = new Md5Hash(user.getPassword(), user.getUserName());//将密码进行MD5盐值加密,盐为用户名
			user.setPassword(pwd.toString());
			
			userService.addUser(user);//添加用户
		}catch(Exception e){
			log.error("添加用户失败",e);
			return new ResponseEntity<Integer>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
		return new ResponseEntity<Integer>(Common.common_success,HttpStatus.OK);

	}

 

2,编辑用户(页面需要的数据:个人信息和所有的角色)

3,删除用户(省略...)

 

上一节:数据库表格设计

下一节:spring整合shiro

 

tip:有错误或疑问,请评论留言,谢谢

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值