Java全栈开发---Java ERP系统开发:商业ERP(十四)ERP系统的权限分配

一、权限系统分析与构建

1、需求与实现思路

1)每个用户登陆进去看到的菜单应该取决于他们所拥有的权限,对于不同的用户,他们进入系统后看到的菜单可能是不同的。

2)如果对每个用户都去设置权限,操作起来是非常繁琐的。

实际中很多用户的权限是一样的。我们把这多个权限合起来,给它一个名称叫角色(有的系统称为“用户组”)。这样我们通过角色设置权限,即一个角色可以有多个权限(菜单项),一个权限也可以被多个角色同时拥有。在这种情况下,角色和权限之间就是典型的多对多关联

3)每个角色包含了很多权限(菜单),那么用户指定为某种角色,即拥有该角色的权限。

实际中一个用户可能同时拥有多种角色,而一个角色又包含了很多个用户。那么用户与角色之间又是典型的多对多关系。

4)一个标准的权限系统包括哪些表呢?

刚才我们提到了用户、角色、权限,这就是三张表。用户与角色的关系是多对多,对于多对多关系,我们通常会使用中间表来存储它们的关系。那么对应的角色与权限的关系,也会有中间表。因此,权限系统涉及的表就有5个了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、代码实现

1、访问http://localhost:8080/erp/role.html,添加一些管理员

在这里插入图片描述

2、建立多对多关联关系

(1)修改erp_entity下的Role类

在这里插入图片描述

@JSONField(serialize=false)
	private List<Menu> menus;// 角色下的菜单权限
	public List<Menu> getMenus() {
    
    
		return menus;
	}
	public void setMenus(List<Menu> menus) {
    
    
		this.menus = menus;
	}

(2)修改role.hbm.xml

在这里插入图片描述

<!-- 多对多关联配置,角色权限中间表role_menu -->
		<bag name="menus" order-by="menuuuid"  table="role_menu" >
			<key column="roleuuid"> </key>
			<many-to-many class="com.itzheng.erp.entity.Menu" column="menuuuid"></many-to-many>
		</bag>

(3)修改Emp类:用户下所有拥有的角色集合

在这里插入图片描述

@JSONField(serialize = false)
	public List<Role> roles;//用户下所有拥有的角色集合

	public List<Role> getRoles() {
    
    
		return roles;
	}

	public void setRoles(List<Role> roles) {
    
    
		this.roles = roles;
	}

(4 )修改emp.hbm.xml

在这里插入图片描述

<!-- 多对多关联:用户角色中间表 -->
		<bag name="roles" order-by="roleuuid" table="emp_role" >
			<key column="empuuid"></key>
			<many-to-many class="com.itzheng.erp.entity.Role" column="roleuuid" ></many-to-many>
		</bag>

3、角色权限设置

(1)需求分析

在这里插入图片描述

(2)tree控件(树形结构)

a、在wabapp下创建roleMenuSet.html文件

在当前文件夹当中引入roleMenuSet.js
在这里插入图片描述

b、在wabapp下的js下创建roleMenuSet.js文件

在这里插入图片描述
认识tree控件
在这里插入图片描述

扫描二维码关注公众号,回复: 12426730 查看本文章

(3)代码实现

01、Tree控件显示菜单
1)在emp_entity构建实体类tree

在这里插入图片描述

package com.itzheng.erp.entity;

import java.util.List;

/*
 * 树形菜单数据实体
 */
public class Tree {
    
    
	/*
	 * id:节点ID,对加载远程数据很重要。 
	 * text:显示节点文本。 
	 * checked:表示该节点是否被选中。 
	 * children:一个节点数组声明了若干节点。
	 */
	private String id;// 菜单ID
	private String text;// 菜单名称
	private boolean checked;// 是否被选中
	private List<Tree> children;// 被选中

	public String getId() {
    
    
		return id;
	}

	public void setId(String id) {
    
    
		this.id = id;
	}

	public String getText() {
    
    
		return text;
	}

	public void setText(String text) {
    
    
		this.text = text;
	}

	public boolean isChecked() {
    
    
		return checked;
	}

	public void setChecked(boolean checked) {
    
    
		this.checked = checked;
	}

	public List<Tree> getChildren() {
    
    if (null == children) {
    
    
		if (null == children) {
    
    
			//确保调用添加二级菜单出现空指针异常
			children = new ArrayList<Tree>();
		}
		return children;
	}

	public void setChildren(List<Tree> children) {
    
    
		this.children = children;
	}
	@Override
	public String toString() {
    
    
		return "Tree [id=" + id + ", text=" + text + ", checked=" + checked + ", children=" + children + "]";
	}
}
2)业务层实现

在IRoleBiz下添加方法,并在RoleBiz实现类当中实现该方法
在这里插入图片描述
IRoleBiz

package com.itzheng.erp.biz.impl;

import java.util.ArrayList;
import java.util.List;

import com.itzheng.erp.biz.IRoleBiz;
import com.itzheng.erp.dao.IMenuDao;
import com.itzheng.erp.dao.IRoleDao;
import com.itzheng.erp.entity.Menu;
import com.itzheng.erp.entity.Role;
import com.itzheng.erp.entity.Tree;

/**
 * 角色业务逻辑类
 * 
 * @author Administrator
 *
 */
public class RoleBiz extends BaseBiz<Role> implements IRoleBiz {
    
    
	private IRoleDao roleDao;
	private IMenuDao menuDao;
	public void setMenuDao(IMenuDao menuDao) {
    
    
		this.menuDao = menuDao;
	}
	public void setRoleDao(IRoleDao roleDao) {
    
    
		this.roleDao = roleDao;
		setBaseDao(roleDao);
	}
	@Override
	public List<Tree> readRoleMenus() {
    
    
		List<Tree> treeList = new ArrayList<Tree>();
		//查询出所有的菜单
		Menu root = menuDao.get("0");
		Tree t1 = null;
		Tree t2 = null;
		//一级菜单
		for(Menu m:root.getMenus()) {
    
    
			t1 = new Tree();
			t1.setId(m.getMenuid());
			t1.setText(m.getMenuname());
			//二级菜单
			for(Menu m2 : m.getMenus()) {
    
    
				t2 = new Tree();
				t2.setId(m2.getMenuid());
				t2.setText(m2.getMenuname());
				t1.getChildren().add(t2);
			}
			treeList.add(t1);
		}
		
		return treeList;
	}

}

设置对应的配置文件applicationContext_biz.xml
在这里插入图片描述

<property name="menuDao" ref="menuDao"></property>
3)Action实现RoleAction

在这里插入图片描述

package com.itzheng.erp.action;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.itzheng.erp.biz.IRoleBiz;
import com.itzheng.erp.entity.Role;
import com.itzheng.erp.entity.Tree;
/**
 * 角色Action
 * 
 * @author Administrator
 *
 */
public class RoleAction extends BaseAction<Role> {
    
    
	private IRoleBiz roleBiz;
	public void setRoleBiz(IRoleBiz roleBiz) {
    
    
		this.roleBiz = roleBiz;
		setBaseBiz(roleBiz);
	}
	/*
	 * 获取角色菜单权限
	 */
	public void readRoleMenus() {
    
    
		List<Tree> menus = roleBiz.readRoleMenus();
		write(JSON.toJSONString(menus));
	}
}
4)修改readRoleMenu.js

在这里插入图片描述

$(function(){
    
    
	$('#tree').tree({
    
    
		url:'role_readRoleMenus',
		animate:true,
		checkbox:true
		
	})
});
5)访问页面

http://localhost:8080/erp/roleMenuSet.html
在这里插入图片描述

02、设置菜单参数设置选中与未选中
1)修改IRoleBiz和RoleBiz

IRoleBiz
在这里插入图片描述
RoleBiz
在这里插入图片描述

//查询出所有的菜单
		Menu root = menuDao.get("0");
		Tree t1 = null;
		Tree t2 = null;
		//一级菜单
		for(Menu m:root.getMenus()) {
    
    
			t1 = new Tree();
			t1.setId(m.getMenuid());
			t1.setText(m.getMenuname());
			//二级菜单
			for(Menu m2 : m.getMenus()) {
    
    
				t2 = new Tree();
				t2.setId(m2.getMenuid());
				t2.setText(m2.getMenuname());
				//如果角色下包含有这个权限菜单,让其勾选
				if(roleMenus.contains(m2)) {
    
    
					t2.setChecked(true);
				}
				t1.getChildren().add(t2);
			}
			treeList.add(t1);
		}
2)修改RoleAction

在这里插入图片描述

/*
	 * 获取角色菜单权限
	 */
	public void readRoleMenus() {
    
    
		List<Tree> menus = roleBiz.readRoleMenus(getId());
		write(JSON.toJSONString(menus));

	}
3)修改roleMenuSet.js

在这里插入图片描述

$(function(){
    
    
	$('#tree').tree({
    
    
		url:'role_readRoleMenus?id=1',
		animate:true,
		checkbox:true
	})
});

再次访问
在这里插入图片描述

03、级联显示角色菜单
1)修改roleMenuSet.html

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>角色权限设置</title>
<link rel="stylesheet" type="text/css"
	href="ui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
<script type="text/javascript" src="ui/jquery.min.js"></script>
<script type="text/javascript" src="ui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="ui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="ui/jquery.serializejson.min.js"></script>
<script type="text/javascript" src="js/roleMenuSet.js"></script>

</head>
<body class="easyui-layout">
	<div data-options="region:'west',title:'角色列表'" style="padding: 4px;width: 300px; ">
		<table id="grid"></table>
	</div>
	<div data-options="region:'center',title:'权限设置'" style="padding: 4px">
		<ul id="tree"></ul>
	</div>
</body>
</html>
2)修改roleMenuSet.js

在这里插入图片描述

$(function(){
    
    
	$('#tree').tree({
    
    
		animate:true,
		checkbox:true
	})
	$('#grid').datagrid({
    
    
		url:'role_list',
		columns:[[
			{
    
    field:'uuid',title:'编号',width:'100'},
			{
    
    field:'name',title:'名称',width:'100'}
		]],
		singleSelect:true,
		onClickRow:function(rowIndex,rowData){
    
    
			$('#tree').tree({
    
    
				url:'role_readRoleMenus?id='+rowData.uuid,
				animate:true,
				checkbox:true
				
			})
		}
	})
});
04、角色菜单提交保存
1)修改IRoleBiz和RoleBiz

IRoleBiz
在这里插入图片描述

package com.itzheng.erp.biz;
import java.util.List;
import com.itzheng.erp.entity.Role;
import com.itzheng.erp.entity.Tree;
/**
 * 角色业务逻辑层接口
 * @author Administrator
 *
 */
public interface IRoleBiz extends IBaseBiz<Role>{
    
    
	//获取角色菜单权限
	//uuid 角色编号
	List<Tree> readRoleMenus(Long uuid);
	
	/*
	 * 更新角色权限
	 * uuid角色编号
	 * checkedStr 勾选中的菜单ID字符串,以逗号分隔
	 */
	public void updateRoleMenus(Long uuid,String checkedStr);
}

RoleBiz
在这里插入图片描述

/*
	 * 更新角色权限
	 * uuid角色编号
	 * checkedStr 勾选中的菜单ID字符串,以逗号分隔
	 */
	public void updateRoleMenus(Long uuid,String checkedStr) {
    
    
		//得到角色信息,进入持久化状态,后的对对象的操作都会保存到数据库当中
		Role role = roleDao.get(uuid);
		//清除角色下的菜单权限(delete from role_menu where roleuuid=?)
		role.setMenus(new ArrayList<Menu>());
		
		String[] ids = checkedStr.split(",");
		Menu menu = null;
		for (String id : ids) {
    
    
			menu = menuDao.get(id);
			//保存角色下的菜单权限:insert into role_menu
			role.getMenus().add(menu);
		}
	}
2)修改RoleAction

在这里插入图片描述

private String checkedStr;//勾选中的菜单ID字符串,以逗号分隔

	public String getCheckedStr() {
    
    
		return checkedStr;
	}

	public void setCheckedStr(String checkedStr) {
    
    
		this.checkedStr = checkedStr;
	}
	/*
	 * 更新角色权限
	 * uuid角色编号
	 * checkedStr 勾选中的菜单ID字符串,以逗号分隔
	 */
	public void updateRoleMenus() {
    
    
		
		try {
    
    
			roleBiz.updateRoleMenus(getId(), checkedStr);
			write(ajaxReturn(true, "更新成功"));
		} catch (Exception e) {
    
    
			write(ajaxReturn(false, "更新失败"));
			// TODO: handle exception
			e.printStackTrace();
		}
		
	}
3)roleMenuSet.html

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>角色权限设置</title>
<link rel="stylesheet" type="text/css"
	href="ui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
<script type="text/javascript" src="ui/jquery.min.js"></script>
<script type="text/javascript" src="ui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="ui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="ui/jquery.serializejson.min.js"></script>
<script type="text/javascript" src="js/roleMenuSet.js"></script>

</head>
<body class="easyui-layout">
	<div data-options="region:'west',title:'角色列表'" style="padding: 4px;width: 300px; ">
		<table id="grid"></table>
	</div>
	<div data-options="region:'center',title:'权限设置'" style="padding: 4px">
		<ul id="tree"></ul>
		<button id="btnSave">保存</button>
	</div>
</body>
</html>
3)roleMenuSet.js

在这里插入图片描述

$('#btnSave').bind('click',function(){
    
    
		var nodes = $('#tree').tree('getChecked');
		var ids = new Array();
		$.each(nodes,function(i, node){
    
    
			ids.push(node.id);
		});
		//[1,2,3,4] => "1,2,3,4"
		var checkedStr = ids.join(',');//把数组里的每个元都拼接上逗号
		//构建提交数据
		var formdata = {
    
    };
		//id赋值
		formdata.id= $('#grid').datagrid('getSelected').uuid;
		//选中的菜单ID
		formdata.checkedStr=checkedStr;
		//alert(JSON.stringify(formdata));
		$.ajax({
    
    
			url: 'role_updateRoleMenus',
			data:formdata,
			type:'post',
			dataType: 'json',
			success:function(rtn){
    
    
				$.messager.alert('提示',rtn.message,'info');
			}
		});
	});

4、用户角色设置

(1)需求分析

一个用户可以指定多个角色,实现思路与角色权限设置相同

(2)代码实现

1)业务层实现
a、修改IEmpBiz和EmpBiz

IEmpBiz
在这里插入图片描述
EmpBiz
在这里插入图片描述
EmpBiz
在这里插入图片描述

// 获取用户角色权限
	public List<Tree> readEmpRoles(Long uuid) {
    
    
		List<Tree> treeList = new ArrayList<Tree>();
		//获取用户信息
		Emp emp = empDao.get(uuid);
		//获取用户下的角色列表
		List<Role> empRoles = emp.getRoles();
		//获取所有的角色列表
		List<Role> rolesList = roleDao.getList(null, null, null);
		Tree t1 = null;
		for(Role role : rolesList) {
    
    
			t1 = new Tree();
			//转换为String类型
			t1.setId(String.valueOf( role.getUuid()));
			t1.setText(role.getName());
			//判断其是否需要选中,用户是否拥有这个角色
			if(empRoles.contains(role)) {
    
    
				t1.setChecked(true);
			}
			treeList.add(t1);
		}
		return treeList;
	}
	// 更新用户角色
	public void updateEmpRoles(Long uuid, String checkedStr) {
    
    
		Emp emp = empDao.get(uuid);
		//清空该用户下的所有角色
		emp.setRoles(new ArrayList<Role>());
		String[] ids = checkedStr.split(",");
		Role role = null;
		for (String id : ids) {
    
    
			role = roleDao.get(Long.valueOf(id));
			//设置用户的角色
			emp.getRoles().add(role);
		}
	}
b、 修改applicationContext_biz.xml

在这里插入图片描述

2)修改EmpAction

在这里插入图片描述

3)用户角色的设置前端页面,创建empRolesSet.html,和empRolesSet.js
empRolesSet.html

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户角色设置</title>
<link rel="stylesheet" type="text/css"
	href="ui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
<script type="text/javascript" src="ui/jquery.min.js"></script>
<script type="text/javascript" src="ui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="ui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="ui/jquery.serializejson.min.js"></script>
<script type="text/javascript" src="js/empRoleSet.js"></script>
</head>
<body class="easyui-layout">
	<div data-options="region:'west',title:'用户列表'" style="padding: 4px;width: 300px; ">
		<table id="grid"></table>
	</div>
	<div data-options="region:'center',title:'角色设置'" style="padding: 4px">
		<ul id="tree"></ul>
		<button id="btnSave">保存</button>
	</div>
</body>
</html>
empRolesSet.js

在这里插入图片描述

$(function(){
    
    
	$('#tree').tree({
    
    
		animate:true,
		checkbox:true
	});
	$('#grid').datagrid({
    
    
		url:'emp_list',
		columns:[[
			{
    
    field:'uuid',title:'编号',width:'100'},
			{
    
    field:'name',title:'名称',width:'100'}
		]],
		singleSelect:true,
		onClickRow:function(rowIndex,rowData){
    
    
			$('#tree').tree({
    
    
				url:'emp_readEmpRoles?id='+rowData.uuid,
				animate:true,
				checkbox:true
			});
		}
	});
	$('#btnSave').bind('click',function(){
    
    
		var nodes = $('#tree').tree('getChecked');
		var ids = new Array();
		$.each(nodes,function(i, node){
    
    
			ids.push(node.id);
		});
		//[1,2,3,4] => "1,2,3,4"
		var checkedStr = ids.join(',');//把数组里的每个元素都拼接上逗号
		//构建提交数据
		var formdata = {
    
    };
		//id赋值
		formdata.id= $('#grid').datagrid('getSelected').uuid;
		//选中角色ID
		formdata.checkedStr=checkedStr;
		//alert(JSON.stringify(formdata));
		$.ajax({
    
    
			url: 'emp_upateEmpRoles',
			data:formdata,
			type:'post',
			dataType: 'json',
			success:function(rtn){
    
    
				$.messager.alert('提示',rtn.message,'info');
			}
		});
	});
});
4)测试访问:http://localhost:8080/erp/empRolesSet.html

在这里插入图片描述

5、显示权限菜单

(1)需要与实现思路

要求:用户登陆后只显示他拥有的菜单,多对多关联查询:
涉及到的实体类:
用户 角色 菜单
5个表的查询:
根据用户ID查询该用户所拥有的菜单,多对多关联查询:
用户(EMP) => 角色(ROLE)=> 菜单(MENU)
HQL:

select m from Emp e join e.roles r join r.menus m where e.uuid=?

在这里插入图片描述

(2)代码实现

根据用户编号查询菜单列表

1)修改IEmpDao和EmpDao创建getMenusByEmpuuid

IEmpDao
在这里插入图片描述
EmpDao
在这里插入图片描述

2)业务层

IEmpBiz
在这里插入图片描述
EmpBiz
在这里插入图片描述

@Override
	public List<Menu> getMenusByEmpuuid(Long uuid) {
    
    
		
		return empDao.getMenusByEmpuuid(uuid);
	}
3)EmpAction层

在这里插入图片描述

	/*
	 * 获取用户的菜单权限
	 */
	public void getMenusByEmpuuid() {
    
    
		if (null != getLoginUser()) {
    
    
			List<Menu> menuList = empBiz.getMenusByEmpuuid(getLoginUser().getUuid());
			write(JSON.toJSONString(menuList));
		}
	}

测试访问http://localhost:8080/erp/emp_getMenusByEmpuuid
返回如下结果
在这里插入图片描述
数据为数组,且全部是二级菜单,这种数据格式无法在页面加载成菜单

4)根据权限显示菜单

思路分析:
菜单clone,只复制该用户下所拥有的菜单,如果有二级菜单的话,必须复制其上级菜单
在这里插入图片描述

a、在IEmpBiz和EmpBiz当中添加readMenusByEmpuuid方法

IEmpBiz
在这里插入图片描述
EmpBiz
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

修改applicationContext_biz.xml
在这里插入图片描述

b、修改MenuAction

在这里插入图片描述

c、修改applicationContext_action.xml

在这里插入图片描述

e、测试

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_44757034/article/details/112097626