01-权限管理需求描述
一、权限管理需求描述
不同角色的用户登录后台管理系统拥有不同的菜单权限与功能权限,权限管理包含三个功能模块:菜单管理、角色管理和用户管理
1、菜单管理
(1)菜单列表:使用树形结构显示菜单列表
(2)添加菜单:点击添加菜单,弹框进行添加
(3)修改菜单
(4)删除菜单
2、角色管理
(1)角色列表:实现角色的条件查询带分页功能
(2)角色添加
(3)角色修改
点击修改按钮
数据回显,进行修改
(4)角色删除
普通删除
批量删除
(5)角色分配菜单
点击分配按钮
给角色分配菜单
3、用户管理
(1)用户列表
(2)用户添加
(3)用户修改
(4)用户删除
普通删除和批量删除
(5)用户分配角色
02-开发权限管理接口
一、创建权限管理服务
1、在service模块下创建子模块service_acls
2、在service_acl模块中引入依赖
<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>spring_security</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
3、创建权限管理相关的表
4、复制权限管理接口代码
5、复制整合Spring Security代码
(1)在common模块下创建子模块spring_security
6、编写service_acl中的application.properties配置文件
# 服务端口
server.port=8009
# 服务名
spring.application.name=service-acl
# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
#最小空闲
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/atguigu/aclservice/mapper/xml/*.xml
# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
二、开发权限管理接口
#########递归查询原则:先找到查询的入口,本案例中的入口是一层菜单。############
1、获取所有菜单
(1)PermissionController
@RestController
@RequestMapping("/admin/acl/permission")
//@CrossOrigin
public class PermissionController {
@Autowired
private PermissionService permissionService;
//获取全部菜单
@ApiOperation(value = "查询所有菜单")
@GetMapping
public R indexAllPermission() {
List<Permission> list = permissionService.queryAllMenuGuli();
return R.ok().data("children",list);
}
}
@RequestMapping("/admin/acl/permission")因此需要过滤。
(2)在Permission实体类添加属性
@ApiModelProperty(value = "层级")
@TableField(exist = false)
private Integer level;
@ApiModelProperty(value = "下级")
@TableField(exist = false)
private List children;
@ApiModelProperty(value = "是否选中")
@TableField(exist = false)
private boolean isSelect;
(3)PermissionServiceImpl
//========================递归查询所有菜单================================================
//获取全部菜单
@Override
public List<Permission> queryAllMenuGuli() {
//1 查询菜单表所有数据
QueryWrapper<Permission> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
List<Permission> permissionList = baseMapper.selectList(wrapper);
//2 把查询所有菜单list集合按照要求进行封装
List<Permission> resultList = bulidPermission(permissionList);
return resultList;
}
bulidPermission方法:完成递归操作。这个方法可以写到工具类中,也可以写在当前里面。
//把返回所有菜单list集合进行封装的方法
public static List<Permission> bulidPermission(List<Permission> permissionList) {
//创建list集合,用于数据最终封装
List<Permission> finalNode = new ArrayList<>();
//把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level是1
for(Permission permissionNode : permissionList) {
//得到顶层菜单 pid=0菜单
if("0".equals(permissionNode.getPid())) {
//设置顶层菜单的level是1
permissionNode.setLevel(1);
//根据顶层菜单,向里面进行查询子菜单,封装到finalNode里面
//两个参数,permissionNode一级菜单节点,permissionList所有集合
finalNode.add(selectChildren(permissionNode,permissionList));
}
}
return finalNode;
}
private static Permission selectChildren(Permission permissionNode, List<Permission> permissionList) {
//1 因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化
permissionNode.setChildren(new ArrayList<Permission>());
//2 遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同
for(Permission it : permissionList) {
//判断一级permissionNode的id和二级it的pid值是否相同
if(permissionNode.getId().equals(it.getPid())) {
//把父菜单的level值+1
int level = permissionNode.getLevel()+1;
it.setLevel(level);
//如果children为空,进行初始化操作
if(permissionNode.getChildren() == null) {
permissionNode.setChildren(new ArrayList<Permission>());
}
//把查询出来的子菜单(it)放到父菜单(即permissionNode一级)里面
permissionNode.getChildren().add(selectChildren(it,permissionList));
}
}
return permissionNode;
}
测试:
2、递归删除菜单
比如删除id=11菜单,把11值和11菜单里面子菜单所有id都获取到。
(1)PermissionController
@ApiOperation(value = "递归删除菜单")
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id) {
permissionService.removeChildByIdGuli(id);
return R.ok();
}
(2)PermissionServiceImpl
//============递归删除菜单==================================
@Override
public void removeChildByIdGuli(String id) {
//1 创建list集合,用于封装所有删除菜单id值
List<String> idList = new ArrayList<>();
//2 向idList集合设置删除菜单id,根据id在进行查询,然后把所有id封装到idList
this.selectPermissionChildById(id,idList);
//把当前id封装到list里面
idList.add(id);
baseMapper.deleteBatchIds(idList);
}
//2 根据当前菜单id,查询菜单里面子菜单id,封装到list集合
private void selectPermissionChildById(String id, List<String> idList) {
//查询菜单里面子菜单id
QueryWrapper<Permission> wrapper = new QueryWrapper<>();
wrapper.eq("pid",id);
wrapper.select("id"); //查出指定列的值
List<Permission> childIdList = baseMapper.selectList(wrapper);
//把childIdList里面菜单id值获取出来,封装idList里面,做递归查询
childIdList.stream().forEach(item -> {
//封装idList里面
idList.add(item.getId());
//递归查询
this.selectPermissionChildById(item.getId(),idList);
});
}
测试:
3、给角色分配权限
(1)PermissionController
//roleId角色id,permissionId菜单id,角色一个但是菜单多个
@ApiOperation(value = "给角色分配权限")
@PostMapping("/doAssign")
public R doAssign(String roleId,String[] permissionId) {
permissionService.saveRolePermissionRealtionShipGuli(roleId,permissionId);
return R.ok();
}
(2)PermissionServiceImpl
//=========================给角色分配菜单=======================
@Override
//roleId角色id
//permissionId菜单id 数组形式
public void saveRolePermissionRealtionShipGuli(String roleId, String[] permissionIds) {
//1 创建list集合,用于封装添加数据
List<RolePermission> rolePermissionList = new ArrayList<>();
//遍历所有菜单数组
for(String perId : permissionIds) {
//RolePermission对象
RolePermission rolePermission = new RolePermission();
rolePermission.setRoleId(roleId); // 角色id
rolePermission.setPermissionId(perId);//菜单id
//封装到list集合
rolePermissionList.add(rolePermission);
}
//添加到角色菜单关系表
rolePermissionService.saveBatch(rolePermissionList);
}
(3)在实体类中添加填充注解
测试: