一、权限管理需求描述
不同角色的用户登录后台管理系统拥有不同的菜单权限与功能权限,权限管理包含三个功能模块:菜单管理、角色管理和用户管理
1、菜单管理
(1)菜单列表:使用树形结构显示菜单列表
(2)添加菜单:点击添加菜单,弹框进行添加
(3)修改菜单
(4)删除菜单
2、角色管理
(1)角色列表:实现角色的条件查询带分页功能
(2)角色添加
(3)角色修改
点击修改按钮
数据回显,进行修改
(4)角色删除
普通删除
批量删除
(5)角色分配菜单
点击分配按钮
给角色分配菜单
3、用户管理
(1)用户列表
(2)用户添加
(3)用户修改
(4)用户删除
普通删除和批量删除
(5)用户分配角色
二、权限管理表结构关系
创建权限管理相关的表
三、创建权限管理服务
1、在service模块下创建子模块service-acl
2、在service_acl模块中引入依赖
<dependencies>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<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、application.yml
#服务端口
server:
port: 8008
#服务名
spring:
application:
name: service-acl
#服务地址
cloud:
nacos:
discovery:
# server-addr: 47.108.14.246:8848
server-addr: 127.0.0.1:8848
#环境设置: dev、test、prod
profiles:
active: dev
# mysql数据库连接
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.108.14.246:3306/guli?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: $Panghl0
#返回json的全局时间格式
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
#Redis配置
redis:
host: 127.0.0.1
port: 6379
database: 0
timeout: 1800000
lettuce:
pool:
max-active: 20
max-wait: -1
#最大阻塞等待时间(负数表示没有限制)
max-idle: 5
min-idle: 0
#mybatis日志
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:com/atguigu/aclservice/mapper/xml/*Mapper.xml
type-aliases-package: com.atguigu.aclservice.entity
#开启熔断机制
feign:
hystrix:
enabled: true
# 设置hystrix超时时间,默认1000ms
#hystrix:
# command:
# default:
# execution:
# isolation:
# thread:
# timeoutInMilliseconds: 6000
4、启动类
package com.atguigu.aclservice;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
/**
* @Author panghl
* @Date 2021/1/31 15:13
* @Description TODO
**/
@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(basePackages = {"com.atguigu"})
@MapperScan("com.atguigu.aclservice.mapper")
public class AclApplication {
public static void main(String[] args) {
SpringApplication.run(AclApplication.class,args);
}
}
5、复制权限管理接口代码
6、复制整合Spring Security代码
(1)在common模块下创建子模块spring_security
四、开发权限管理接口
1、获取所有菜单
(1)controller
@ApiOperation(value = "查询所有菜单")
@GetMapping
public R indexAllPermission() {
List<Permission> list = permissionService.queryAllMenuGuli();
return R.ok().data("children",list);
}
(2) service
/**
* 获取全部菜单
*
* @return
*/
@Override
public List<Permission> queryAllMenuGuli() {
//1.查询菜单表所有数据
QueryWrapper<Permission> qw = new QueryWrapper<>();
qw.orderByDesc("id");
List<Permission> permissionList = baseMapper.selectList(qw);
//2.把查询所有菜单list集合按照要求进行封装
List<Permission> resultList = buildPremission(permissionList);
return resultList;
}
/**
* 把返回所有菜单list集合进行封装的方法
*
* @return
*/
public static List<Permission> buildPremission(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里面
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) {
//判断id和pid是否相同
if (permissionNode.getId().equals(it.getPid())) {
//把父菜单的level的值+1
it.setLevel(permissionNode.getLevel()+1);
//如果children为空,将对象初始化
if (permissionNode.getChildren() == null){
permissionNode.setChildren(new ArrayList<Permission>());
}
//把查询出来的子菜单放到父菜单里面
permissionNode.getChildren().add(selectChildren(it,permissionList));
}
}
return permissionNode;
}
( 3 ) 在Permission实体类添加属性
@ApiModelProperty(value = "层级")
@TableField(exist = false)
private Integer level;
@ApiModelProperty(value = "下级")
@TableField(exist = false)
private List<Permission> children;
@ApiModelProperty(value = "是否选中")
@TableField(exist = false)
private boolean isSelect;
swagger测试:
2、递归删除菜单
(1)controller
@ApiOperation(value = "递归删除菜单")
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id) {
permissionService.removeChildByIdGuli(id);
return R.ok();
}
(2)service
/**
* 递归删除菜单
* @param id
*/
@Override
public void removeChildByIdGuli(String id) {
//1.创建list集合,用于封装所有删除菜单id值
List<String> idList = new ArrayList<>();
//2.向idList集合设置删除菜单id
this.selectPermissionChildById(id,idList);
//3.把当前id封装到list里面
idList.add(id);
baseMapper.deleteBatchIds(idList);
}
/**
* 根据当前菜单id,查询菜单里面子菜单id,封装到list集合
* @param id
*/
private void selectPermissionChildById(String id,List<String> idList) {
QueryWrapper<Permission> qw = new QueryWrapper<>();
qw.select("id");
qw.eq("pid",id);
List<Permission> childList = baseMapper.selectList(qw);
//把childList里面菜单id值获取出来,封装idList里面,做递归查询
childList.stream().forEach(item->{
//封装idList里面
idList.add(item.getId());
//递归查询
selectPermissionChildById(item.getId(),idList);
});
}
3、给角色分配权限
(1)controller
@ApiOperation(value = "给角色分配权限")
@PostMapping("/doAssign")
public R doAssign(String roleId,String[] permissionId) {
permissionService.saveRolePermissionRealtionShipGuli(roleId,permissionId);
return R.ok();
}
(2)service
/**
* 给角色分配权限
* @param roleId
* @param permissionId
*/
@Override
public void saveRolePermissionRealtionShipGuli(String roleId, String[] permissionId) {
//1.创建list集合,用于封装添加数据
List<RolePermission> rolePermissionList = new ArrayList<>();
for (String perId: permissionId) {
//RolePermission对象
RolePermission rolePermission = new RolePermission();
rolePermission.setRoleId(roleId);
rolePermission.setPermissionId(perId);
//封装到list集合
rolePermissionList.add(rolePermission);
}
//添加到角色菜单关系表
rolePermissionService.saveBatch(rolePermissionList);
}