Java系列文章
文章目录
前言
本文将介绍SpringBoot结合sa-token实现RBAC权限模型。
一、基础概念
1.1 RBAC模型核心概念
- 用户(User)、角色(Role)、权限(Permission)的关系。
- 模型分层:用户-角色-权限的三层结构。
- RBAC的基本思想是,对系统操作的各种权限不是直接授予具体的用户,而是在用户集合与权限集合之间建立一个角色集合。每一种角色对应一组相应的权限。一旦用户被分配了适当的角色后,该用户就拥有此角色的所有操作权限。
1.2 Sa-Token核心功能
- 登录认证(StpUtil)、权限校验、会话管理、踢人下线等。
- 关键注解:@SaCheckLogin、@SaCheckRole、@SaCheckPermission。
1.3 环境准备
- JDK 1.8+、Maven、SpringBoot 2.x。
- 初始化SpringBoot项目(可通过Spring Initializr生成)。
- Mysql5.x/8.x
二、表结构设计
2.1 ER图示例
2.2 数据库表设计
2.2.1 用户表
CREATE TABLE `tb_user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '用户名',
`password` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '密码',
`open_id` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '长期授权字符串',
`photo` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '头像网址',
`name` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '姓名',
`sex` enum('男','女') CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '性别',
`tel` char(11) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '手机号码',
`email` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '邮箱',
`hiredate` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '入职日期',
`role` json DEFAULT NULL COMMENT '角色',
`root` tinyint(1) DEFAULT '0' COMMENT '是否是超级管理员',
`dept_id` int DEFAULT NULL COMMENT '部门编号',
`status` tinyint DEFAULT NULL COMMENT '状态',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=72 DEFAULT CHARSET=utf8mb3 COMMENT='用户表';
2.2.2 角色表
CREATE TABLE `tb_role` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`role_name` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '角色名称',
`permissions` json NOT NULL COMMENT '权限集合',
`desc` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '描述',
`default_permissions` json DEFAULT NULL COMMENT '系统角色内置权限',
`systemic` int DEFAULT '0' COMMENT '是否为系统内置角色',
`echo` json DEFAULT NULL COMMENT '权限回显集合',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb3 COMMENT='角色表';
2.2.3 部门表
CREATE TABLE `tb_dept` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`dept_name` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '部门名称',
`tel` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '部门电话',
`email` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '部门邮箱',
`desc` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3 COMMENT='部门表';
2.2.4 权限表
CREATE TABLE `tb_permission` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`parent_id` int DEFAULT NULL COMMENT '父级id',
`permission_name` varchar(200) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '权限',
`module_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '模块名称',
`menu_type` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '菜单类型',
`icon` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '菜单图标',
`path` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '菜单路由',
`create_time` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建时间',
`sort` varchar(255) DEFAULT NULL COMMENT '菜单排序',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `unq_permission` (`permission_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=166 DEFAULT CHARSET=utf8mb3 COMMENT='权限表';
三、SpringBoot整合Sa-Token
3.1 sa-token基础配置
3.1.1 Maven配置
<!--SaToken-->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.34.0</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-aop</artifactId>
<version>1.34.0</version>
</dependency>
3.1.2 application.yml
sa-token:
# token 名称(同时也是 cookie 名称)
token-name: token
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
is-share: false
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
token-style: uuid
# 是否输出操作日志
is-log: false
3.1.3 StpUtil鉴权工具类
StpUtil.login(10001); // 会话登录
StpUtil.login(10001, "APP"); // 会话登录,并指定设备类型
StpUtil.getTokenValueByLoginId(10001); // 获取指定账号id的tokenValue
StpUtil.getTokenValueByLoginId(10001, "PC"); // 获取指定账号id指定设备类型端的tokenValue
StpUtil.getPermissionList(); // 获取:当前账号的权限集合
StpUtil.getPermissionList(10001); // 获取:指定账号的权限集合
StpUtil.logout(); // 会话注销
StpUtil.logout(10001); // 会话注销,根据账号id
StpUtil.logout(10001, "PC"); // 会话注销,根据账号id 和 设备类型
3.1.4 编写鉴权类
提示:鉴权类是需要我们自己实现的,必须要扩展StpInterface接口才可以。
@Component
class StpInterfaceImpl implements StpInterface {
@Resource
private UserDao userDao;
/**
* 返回一个用户所拥有的权限集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
List<String> list = new ArrayList<>();
int userId = Integer.parseInt(loginId.toString());
Set<String> set = userDao.searchUserPermissions(userId);
list.addAll(set);
return list;
}
/**
* 返回一个用户所拥有的角色标识集合
*/
@Override
public List<String> getRoleList(Object loginId, String loginKey) {
ArrayList<String> list = new ArrayList();
return list;
}
}
四、RBAC模型设计与实现
4.1 用户管理及登陆实现
4.1.1 定义UserDao类实现接口
**
* @author lenovo
* @description 针对表【tb_user(用户表)】的数据库操作Mapper
* @createDate 2025-02-06 10:28:09
* @Entity com.example.his.api.db.pojo.UserEntity
*/
public interface UserDao {
// 查询用户权限集合
public Set<String> searchUserPermissions(int userId);
// 查询用户路由限集合
public ArrayList<HashMap> searchUserRouterPermissions(int userId);
// 查询指定用户
public int searchUserById(Map param);
// 用户管理-查询分页
public ArrayList<HashMap> searchUserByPage(Map param);
// 用户管理-新增
public int insertUser(Map param);
// 用户管理-编辑
public int updateUser(Map param);
// 用户管理-删除
public int deleteUserById(Map param);
}
4.1.2 配置UserDao.xml映射信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.his.api.db.dao.UserDao">
<resultMap id="BaseResultMap" type="com.example.his.api.db.pojo.UserEntity">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="username" column="username" jdbcType="VARCHAR"/>
<result property="password" column="password" jdbcType="VARCHAR"/>
<result property="openId" column="open_id" jdbcType="VARCHAR"/>
<result property="photo" column="photo" jdbcType="VARCHAR"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="sex" column="sex" jdbcType="OTHER"/>
<result property="tel" column="tel" jdbcType="CHAR"/>
<result property="email" column="email" jdbcType="VARCHAR"/>
<result property="hiredate" column="hiredate" jdbcType="VARCHAR"/>
<result property="role" column="role" jdbcType="OTHER"/>
<result property="root" column="root" jdbcType="TINYINT"/>
<result property="deptId" column="dept_id" jdbcType="INTEGER"/>
<result property="status" column="status" jdbcType="TINYINT"/>
<result property="createTime" column="create_time" jdbcType="VARCHAR"/>
</resultMap>
<!-- 查询用户权限集合 -->
<select id="searchUserPermissions" parameterType="int" resultType="String">
SELECT DISTINCT p.permission_name
FROM tb_user u
JOIN tb_role r ON JSON_CONTAINS(u.role, CAST(r.id AS CHAR))
JOIN tb_permission p ON JSON_CONTAINS(r.permissions, CAST(p.id AS CHAR))
WHERE u.id = #{userId}
AND u.`status` = 1
</select>
<!-- 查询用户权限列表 -->
<select id="searchUserRouterPermissions" parameterType="arraylist" resultType="hashmap">
SELECT DISTINCT p.module_name as name, p.path, p.icon
FROM tb_user u
JOIN tb_role r ON JSON_CONTAINS(u.role, CAST(r.id AS CHAR))
JOIN tb_permission p ON JSON_CONTAINS(r.permissions, CAST(p.id AS CHAR))
WHERE u.id = #{userId}
AND u.`status` = 1
</select>
<!-- 查询指定用户 -->
<select id="searchUserById" parameterType="Map" resultType="integer">
select id
from tb_user
where username = #{username}
and password = #{password}
limit 1;
</select>
<!-- 用户管理-查询分页 -->
<select id="searchUserByPage" parameterType="arraylist" resultType="HashMap">
SELECT DISTINCT u.id,
u.name,
u.sex,
u.tel,
u.email,
d.dept_name AS dept,
d.id AS deptId,
u.role AS roleId,
DATE_FORMAT(u.hiredate,"%Y-%m-%d") AS hiredate,
u.root,
u.status,
(
SELECT GROUP_CONCAT( role_name )
FROM tb_role
WHERE JSON_CONTAINS ( u.role, CONVERT (id, CHAR) )
) AS roles
FROM tb_user u
JOIN tb_role r ON JSON_CONTAINS ( u.role, CONVERT (r.id, CHAR) )
LEFT JOIN tb_dept d ON u.dept_id = d.id
<where>
<if test="searchKeyWord != null and searchKeyWord != ''">
OR d.dept_name LIKE '%${searchKeyWord}%'
</if>
<if test="searchKeyWord != null and searchKeyWord != ''">
OR u.name LIKE '%${searchKeyWord}%'
</if>
<if test="searchKeyWord != null and searchKeyWord != ''">
OR u.status LIKE '%${searchKeyWord}%'
</if>
<if test="searchKeyWord != null and searchKeyWord != ''">
OR u.sex LIKE '%${searchKeyWord}%'
</if>
<if test="searchKeyWord != null and searchKeyWord != ''">
OR u.tel LIKE '%${searchKeyWord}%'
</if>
<if test="searchKeyWord != null and searchKeyWord != ''">
OR u.email LIKE '%${searchKeyWord}%'
</if>
</where>
ORDER BY u.id ASC
</select>
<!-- 用户管理-新增 -->
<insert id="insertUser">
insert into tb_user
SET
username=#{username},
password=#{password},
name=#{name},
sex=#{sex},
tel=#{tel},
email=#{email},
status=#{status},
dept_id=#{deptId},
hiredate=#{hiredate},
role=#{role}
<if test="openId!=null">
,`openId`=#{openId}
</if>
<if test="photo!=null">
,`photo`=#{photo}
</if>
<if test="root!=null">
,`root`=#{root}
</if>
</insert>
<!-- 用户管理-编辑 -->
<update id="updateUser">
update tb_user
SET
name=#{name},
sex=#{sex},
tel=#{tel},
email=#{email},
status=#{status},
dept_id=#{deptId},
hiredate=#{hiredate},
role=#{role}
<if test="username!=null">
,`username`=#{username}
</if>
<if test="password!=null">
,`password`=#{password}
</if>
<if test="openId!=null">
,`openId`=#{openId}
</if>
<if test="photo!=null">
,`photo`=#{photo}
</if>
<if test="root!=null">
,`root`=#{root}
</if>
where id = #{id}
</update>
<!-- 用户管理-删除 -->
<delete id="deleteUserById">
delete from tb_user where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
4.1.3 Service 业务层
@Service
public class UserService {
@Resource
private UserDao userMapper;
// 用户管理-查询id
public int searchUserById(Map param) {
return userMapper.searchUserById(param);
}
// 用户管理-查询分页
public PageInfo<HashMap> searchUserByPage(Map param) {
PageHelper.startPage(MapUtil.getInt(param, "pageNum"), MapUtil.getInt(param, "pageSize"));
ArrayList<HashMap> list = userMapper.searchUserByPage(param);
PageInfo<HashMap> pageInfo = new PageInfo<>(list);
return pageInfo;
}
// 用户管理-新增
public int insertUser(Map param) {
return userMapper.insertUser(param);
}
// 用户管理-更新
public int updateUser(Map param) {
return userMapper.updateUser(param);
}
// 用户管理-删除
public int deleteUserById(Map param) {
return userMapper.deleteUserById(param);
}
// 查询用户路由限集合
public ArrayList<HashMap> searchUserRouterPermissions(int userId) {
ArrayList<HashMap> routerList = userMapper.searchUserRouterPermissions(userId);
ArrayList<HashMap> newRouterList = new ArrayList<>();
routerList.forEach(item -> {
if(!ObjectUtil.isEmpty(item.get("path"))) {
newRouterList.add(item);
}
});
return newRouterList;
}
}
4.1.4 Controller Web层
@RestController
@RequestMapping("/admin")
public class UserController {
@Resource
private UserService userService;
@Resource
private UserDao userDao;
/**
* 用户登录
* @param form
* @return
*/
@PostMapping("/user/login")
public R login(@RequestBody @Valid UserLoginForm form) {
Map param = BeanUtil.beanToMap(form);
Integer userId = userService.searchUserById(param);
if (userId != null) {
StpUtil.logout(userId, "Web");
// 通过会话对象,向SaToken传递userId
StpUtil.login(userId, "Web");
// 生成新的令牌字符串,标记该令牌是给Web端用户使用的
String token = StpUtil.getTokenValueByLoginId(userId, "Web");
// 获取用户的权限列表
List<String> permissionNames = StpUtil.getPermissionList();
// 使用 Collections.sort() 排序
Collections.sort(permissionNames);
// 查询用户路由限集合
ArrayList<HashMap> routerList = userService.searchUserRouterPermissions(userId);
HashMap map = new HashMap<>();
map.put("token", token);
map.put("permissionNames", permissionNames);
map.put("routerList", routerList);
return R.success(map);
}
return R.error();
}
/**
* 用户管理-查询分页
* @param form
* @return
*/
@PostMapping("/user/searchUserByPage")
@SaCheckPermission(value = {"SYSTEM:USER:SELECT"}, mode = SaMode.OR)
public R searchUserByPage(@RequestBody @Valid UserSearchForm form) {
Map param = BeanUtil.beanToMap(form);
PageInfo<HashMap> list = userService.searchUserByPage(param);
return R.success(list);
}
/**
* 用户管理-编辑
* @param form
* @return
*/
@PostMapping("/user/edittUser")
@SaCheckPermission(value = {"SYSTEM:USER:EDIT"}, mode = SaMode.OR)
public R edittUser(@RequestBody @Valid UserEditForm form) {
Map param = BeanUtil.beanToMap(form);
param.replace("role", JSONUtil.parseArray(form.getRole()).toString());
int rows;
if (ObjectUtil.isAllEmpty(param.get("id"))) {
rows = userService.insertUser(param);
} else {
rows = userService.updateUser(param);
}
return R.success(rows);
}
/**
* 用户管理-删除
* @param form
* @return
*/
@PostMapping("/user/deleteUserById")
@SaCheckPermission(value = {"SYSTEM:USER:DELETE"}, mode = SaMode.OR)
public R deleteUserById(@RequestBody @Valid UserDeleteForm form) {
Map param = BeanUtil.beanToMap(form);
int rows = userService.deleteUserById(param);
return R.success(rows);
}
}
4.1.5 登录返回权限列表
用户登陆,会根据当前用户id去关联角色表和权限表,查询对应的权限集合列表。
4.1.6 用户分配角色
用户管理增删改查实现,并对用户分配不同角色
4.2 角色管理实现
4.2.1 定义RoleDao类实现接口
/**
* @author lenovo
* @description 针对表【tb_role(角色表)】的数据库操作Mapper
* @createDate 2025-02-06 10:35:25
* @Entity com.example.his.api.db.pojo.RoleEntity
*/
public interface RoleDao {
// 角色管理-查询全部
public ArrayList<HashMap> searchRoleAll();
// 角色管理-查询分页
public ArrayList<HashMap> searchRoleByPage(Map param);
// 角色管理-新增
public int insertRole(Map param);
// 角色管理-更新
public int updateRole(Map param);
// 角色管理-删除
public int deleteRole(Map param);
}
4.2.2 配置RoleDao.xml映射信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.his.api.db.dao.RoleDao">
<resultMap id="BaseResultMap" type="com.example.his.api.db.pojo.RoleEntity">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="roleName" column="role_name" jdbcType="VARCHAR"/>
<result property="permissions" column="permissions" jdbcType="OTHER"/>
<result property="desc" column="desc" jdbcType="VARCHAR"/>
<result property="defaultPermissions" column="default_permissions" jdbcType="OTHER"/>
<result property="systemic" column="systemic" jdbcType="INTEGER"/>
<result property="echo" column="echo" jdbcType="OTHER"/>
</resultMap>
<!-- 角色管理-查询全部 -->
<select id="searchRoleAll" parameterType="arraylist" resultType="hashmap">
SELECT id,role_name AS roleName FROM tb_role ORDER BY id
</select>
<!-- 角色管理-查询分页 -->
<select id="searchRoleByPage" parameterType="arraylist" resultType="hashmap">
SELECT
r.id,
r.role_name AS roleName,
COUNT( u.id ) AS users,
JSON_LENGTH ( r.permissions ) AS permissionsLength,
r.permissions,
r.desc,
r.systemic,
r.echo
FROM tb_role r
LEFT JOIN tb_user u ON JSON_CONTAINS ( u.role, CONVERT ( r.id, CHAR ) )
<where>
<if test="searchKeyWord != null and searchKeyWord != ''">
AND r.role_name LIKE '%${searchKeyWord}%'
</if>
</where>
GROUP BY r.id
ORDER BY r.id
</select>
<!-- 角色管理-新增 -->
<insert id="insertRole">
insert into tb_role
SET
role_name=#{roleName},
permissions=#{permissions},
echo=#{echo}
<if test="desc!=null">
,`desc`=#{desc}
</if>
</insert>
<!-- 角色管理-更新 -->
<update id="updateRole">
update tb_role set
`role_name` = #{roleName},
`permissions` = #{permissions},
`echo` = #{echo}
<if test="desc!=null">
,`desc`=#{desc}
</if>
<if test="systemic!=null">
,`systemic`=#{systemic}
</if>
where id = #{id}
</update>
<!-- 角色管理-删除 -->
<delete id="deleteRole">
delete from tb_role where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
4.2.3 Service 业务层
@Service
public class RoleService {
@Resource
private RoleDao roleDao;
// 角色管理-查询全部
public ArrayList<HashMap> searchRoleAll(){
return roleDao.searchRoleAll();
}
// 角色管理-查询分页
public PageInfo<HashMap> searchRoleByPage(Map param) {
PageHelper.startPage(MapUtil.getInt(param, "pageNum"), MapUtil.getInt(param, "pageSize"));
ArrayList<HashMap> roleList = roleDao.searchRoleByPage(param);
PageInfo<HashMap> pageInfo = new PageInfo<>(roleList);
return pageInfo;
}
// 角色管理-新增
public int insertRole(Map param) {
return roleDao.insertRole(param);
}
// 角色管理-更新
public int updateRole(Map param) {
return roleDao.updateRole(param);
}
// 角色管理-删除
public int deleteRole(Map param) {
return roleDao.deleteRole(param);
}
}
4.2.4 Controller Web层
@RestController
@RequestMapping("/admin")
public class RoleController {
@Resource
private RoleService roleService;
/**
* 角色管理-查询全部
* @return
*/
@GetMapping("/role/searchRoleAll")
@SaCheckPermission(value = {"SYSTEM:ROLE:SELECT"}, mode = SaMode.OR)
public R searchRoleAll() {
ArrayList<HashMap> roleList = roleService.searchRoleAll();
return R.success(roleList);
}
/**
* 角色管理-分页查询
* @param form
* @return
*/
@PostMapping("/role/searchRoleByPage")
@SaCheckPermission(value = {"SYSTEM:ROLE:SELECT"}, mode = SaMode.OR)
public R searchRoleByPage(@RequestBody @Valid RoleSearchForm form) {
Map param = BeanUtil.beanToMap(form);
PageInfo<HashMap> roleList = roleService.searchRoleByPage(param);
return R.success(roleList);
}
/**
* 角色管理-编辑
* @param form
* @return
*/
@PostMapping("/role/editRole")
@SaCheckPermission(value = {"SYSTEM:ROLE:EDIT"}, mode = SaMode.OR)
public R editRole(@RequestBody @Valid RoleEditForm form) {
Map param = BeanUtil.beanToMap(form);
param.replace("permissions", JSONUtil.parseArray(form.getPermissions()).toString());
param.replace("echo", JSONUtil.parseArray(form.getEcho()).toString());
int rows;
if(ObjectUtil.isEmpty(param.get("id"))) {
rows = roleService.insertRole(param);
}else {
rows = roleService.updateRole(param);
}
return R.success(rows);
}
/**
* 角色管理-删除
* @param form
* @return
*/
@PostMapping("/role/deleteRole")
@SaCheckPermission(value = {"SYSTEM:ROLE:DELETE"}, mode = SaMode.OR)
public R deleteRole(@RequestBody @Valid RoleDeleteForm form) {
Map param = BeanUtil.beanToMap(form);
int rows = roleService.deleteRole(param);
return R.success(rows);
}
}
4.2.5 角色分配权限
4.3 部门管理实现
4.31 定义DeptDao类实现接口
/**
* @author lenovo
* @description 针对表【tb_dept(部门表)】的数据库操作Mapper
* @createDate 2025-02-10 08:57:44
* @Entity com.example.his.api.db.pojo.DeptEntity
*/
public interface DeptDao {
// 部门列表查询
public ArrayList<HashMap> searchAllDept();
public ArrayList<HashMap> searchDept(Map param);
public HashMap searchDeptById(Integer id);
// 部门列表新增和编辑
public int insertDept(Map param);
public int updateDept(Map param);
public int deleteBatchDept(Map param);
}
4.3.2 配置DeptDao.xml映射信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.his.api.db.dao.DeptDao">
<resultMap id="BaseResultMap" type="com.example.his.api.db.pojo.DeptEntity">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="deptName" column="dept_name" jdbcType="VARCHAR"/>
<result property="tel" column="tel" jdbcType="VARCHAR"/>
<result property="email" column="email" jdbcType="VARCHAR"/>
<result property="desc" column="desc" jdbcType="VARCHAR"/>
</resultMap>
<!-- 部门列表查询全部 -->
<select id="searchAllDept" resultMap="BaseResultMap">
select * from tb_dept
</select>
<!-- 部门列表分页查询 -->
<select id="searchDept" resultType="HashMap">
select
d.id,
d.dept_name as deptName,
d.tel,
d.email,
d.desc,
COUNT(u.id) AS emps from tb_dept d left join tb_user u on u.dept_id = d.id
<where>
<if test="searchKeyWord != null and searchKeyWord != ''">
1 = 1
AND d.dept_name like "%${searchKeyWord}%"
OR d.tel = #{searchKeyWord}
OR d.email = #{searchKeyWord}
OR d.desc like "%${searchKeyWord}%"
</if>
</where>
GROUP BY d.id
</select>
<!-- 部门列表查询id -->
<select id="searchDeptById" resultType="HashMap">
select * from tb_dept where id = #{id}
</select>
<!-- 部门列表新增 -->
<insert id="insertDept">
insert into tb_dept values(#{id},#{deptName},#{tel},#{email},#{desc})
</insert>
<!-- 部门列表更新 -->
<update id="updateDept">
update tb_dept
set `dept_name` = #{deptName},
`tel` = #{tel},
`email` = #{email},
`desc` = #{desc}
where `id` = #{id}
</update>
<!-- 部门列表批量删除 -->
<delete id="deleteBatchDept">
delete from tb_dept where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
4.3.3 Service 业务层
@Service
public class DeptService {
@Resource
private DeptDao deptDao;
//部门列表-查询全部
public ArrayList<HashMap> searchAllDept() {
ArrayList<HashMap> list = deptDao.searchAllDept();
return list;
}
//部门列表-分页查询
public PageInfo<HashMap> searchDept(Map param) {
PageHelper.startPage(MapUtil.getInt(param,"pageNum"), MapUtil.getInt(param,"pageSize"));
ArrayList<HashMap> list = deptDao.searchDept(param);
PageInfo<HashMap> pageInfo = new PageInfo<>(list);
return pageInfo;
}
//部门列表-查询id
public HashMap searchDeptById(Integer id) {
HashMap map = deptDao.searchDeptById(id);
return map;
}
//部门列表-新增
public int insertDept(Map param) {
return deptDao.insertDept(param);
}
//部门列表-更新
public int updateDept(Map param) {
return deptDao.updateDept(param);
}
//部门列表-批量删除
public int deleteBatchDept(Map param) {
return deptDao.deleteBatchDept(param);
}
}
4.3.4 Controller Web层
@RestController
@RequestMapping("/admin")
public class DeptController {
@Resource
private DeptService deptService;
/**
* 部门管理-查询全部
* @return
*/
@GetMapping("/dept/searchAllDept")
@SaCheckPermission(value = {"SYSTEM:DEPT:SELECT"}, mode = SaMode.OR)
public R searchAllDept() {
ArrayList<HashMap> list = deptService.searchAllDept();
return R.success(list);
}
/**
* 部门管理-分页查询
* @param deptSearchReq
* @return
*/
@PostMapping("/dept/searchDeptByPage")
@SaCheckPermission(value = {"SYSTEM:DEPT:SELECT"}, mode = SaMode.OR)
public R searchDept(@Valid @RequestBody DeptSearchForm deptSearchReq) {
Map param = BeanUtil.beanToMap(deptSearchReq);
PageInfo<HashMap> list = deptService.searchDept(param);
return R.success(list);
}
/**
* 部门管理-查询id
* @param id
* @return
*/
@GetMapping("/dept/searchDeptById")
@SaCheckPermission(value = {"SYSTEM:DEPT:SELECT"}, mode = SaMode.OR)
public R searchDeptById(@RequestParam(value = "id") Integer id) {
HashMap map = deptService.searchDeptById(id);
if(ObjectUtil.isEmpty(map)) {
return R.success("200","id不存在");
}
return R.success(map);
}
/**
* 部门管理-编辑
* @param deptEditReq
* @return
*/
@PostMapping("/dept/editDept")
@SaCheckPermission(value = {"SYSTEM:DEPT:EDIT"}, mode = SaMode.OR)
public R insertDept(@Valid @RequestBody DeptEditForm deptEditReq) {
Map param = BeanUtil.beanToMap(deptEditReq);
if(ObjectUtil.isEmpty(deptEditReq.getId())) {
deptService.insertDept(param);
}else {
deptService.updateDept(param);
}
return R.success();
}
/**
* 部门管理-批量删除
* @param deptDeleteReq
* @return
*/
@PostMapping("/dept/deleteBatchDept")
@SaCheckPermission(value = {"SYSTEM:DEPT:DELETE"}, mode = SaMode.OR)
public R deleteBatchDept(@Valid @RequestBody DeptDeleteForm deptDeleteReq) {
Map param = BeanUtil.beanToMap(deptDeleteReq);
int rows = deptService.deleteBatchDept(param);
return R.success(rows);
}
}
4.3.5 部门页面编辑
4.4 权限管理实现
4.4.1 定义PermissionDao类实现接口
/**
* @author lenovo
* @description 针对表【tb_permission(权限表)】的数据库操作Mapper
* @createDate 2025-02-06 10:35:25
* @Entity com.example.his.api.db.pojo.PermissionEntity
*/
public interface PermissionDao {
// 查询递归菜单权限
public ArrayList<PermissionMenuResp> searchPermissions();
// 权限管理-编辑
public int insertPermission(Map param);
public int updatePermission(Map param);
// 权限管理-批量删除
public int deleteBatchPermission(Map param);
}
4.4.2 配置PermissionDao.xml映射信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.his.api.db.dao.PermissionDao">
<resultMap id="PermissionMenu" type="com.example.his.api.resp.PermissionMenuResp">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="parentId" column="parent_id" jdbcType="INTEGER"/>
<result property="permissionName" column="permission_name" jdbcType="VARCHAR"/>
<result property="moduleName" column="module_name" jdbcType="VARCHAR"/>
<result property="menuType" column="menu_type" jdbcType="VARCHAR"/>
<result property="icon" column="icon" jdbcType="VARCHAR"/>
<result property="path" column="path" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="VARCHAR"/>
</resultMap>
<!-- <sql id="Base_Column_List">-->
<!-- id,parent_id,permission_name,-->
<!-- module_name,menu_type,icon,-->
<!-- path,create_time-->
<!-- </sql>-->
<!-- 查询用户现有权限 -->
<select id="searchPermissions" resultMap="PermissionMenu">
select * from tb_permission order by sort asc
</select>
<!-- 权限管理-新增 -->
<insert id="insertPermission">
insert into tb_permission values(#{id},#{parentId},#{permissionName},#{moduleName},#{menuType},#{icon},#{path},#{createTime})
</insert>
<!-- 权限管理-更新 -->
<update id="updatePermission">
update tb_permission
set `parent_id` = #{parentId},
`permission_name` = #{permissionName},
`module_name` = #{moduleName},
`menu_type` = #{menuType},
`icon` = #{icon},
`path` = #{path},
`create_time` = #{createTime}
where id = #{id}
</update>
<!-- 权限管理-批量删除 -->
<delete id="deleteBatchPermission">
delete from tb_permission where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</delete>
</mapper>
4.4.3 Service 业务层
@Service
public class PermissionService {
@Resource
private PermissionDao permissionDao;
// 权限管理-递归菜单
public ArrayList<PermissionMenuResp> searchPermissions() {
return deepTree(permissionDao.searchPermissions());
}
// 权限管理-编辑
public int insertPermission(Map param) {
return permissionDao.insertPermission(param);
}
public int updatePermission(Map param) {
return permissionDao.updatePermission(param);
}
// 权限管理-批量删除
public int deleteBatchPermission(Map param) {
return permissionDao.deleteBatchPermission(param);
}
/**
* 转换树形结构
* @param menuList
* @return
*/
public ArrayList<PermissionMenuResp> deepTree(ArrayList<PermissionMenuResp> menuList) {
//创建list集合,用于数据最终封装
ArrayList<PermissionMenuResp> finalNode = new ArrayList<>();
for (PermissionMenuResp menus : menuList) {
Integer topId = 0;
//判断Pid是否等于0 0是最高的节点 将查询出的数据放进list集合
if (topId.equals(menus.getParentId())) {
finalNode.add(selectTree(menus, menuList));
}
}
// 递归设置节点层级
for (PermissionMenuResp menu : finalNode) {
setNodeLevel(menu,1);
}
return finalNode;
}
public PermissionMenuResp selectTree(PermissionMenuResp m1, ArrayList<PermissionMenuResp> menuList) {
//因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化
m1.setChildren(new ArrayList<PermissionMenuResp>());
//遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同
for (PermissionMenuResp m2 : menuList) {
//判断 id和pid值是否相同
if (m1.getId().equals(m2.getParentId())) {
//如果children为空,进行初始化操作
if (m1.getChildren() == null) {
m1.setChildren(new ArrayList<PermissionMenuResp>());
}
//把查询出来的子菜单放到父菜单里面
m1.getChildren().add(selectTree(m2, menuList));
}
}
return m1;
}
// 递归设置节点层级
public void setNodeLevel(PermissionMenuResp node, int level) {
node.setLevel(level);
node.setKey(node.getId());
for (PermissionMenuResp child : node.getChildren()) {
setNodeLevel(child, level + 1);
}
}
}
4.4.4 Controller Web层
@RestController
@RequestMapping("/admin")
public class PermissionController {
@Resource
private PermissionService permissionService;
/**
* 权限管理-递归菜单
* @return
*/
@GetMapping("/permissions/searchPermissions")
@SaCheckPermission(value = {"SYSTEM:PERMISSION:SELECT"}, mode = SaMode.OR)
public R searchPermissions() {
ArrayList<PermissionMenuResp> permissions = permissionService.searchPermissions();
return R.success(permissions);
}
/**
* 权限管理-编辑
* @param permissionEditReq
* @return
*/
@PostMapping("/permissions/editPermissions")
@SaCheckPermission(value = {"SYSTEM:PERMISSION:EDIT"}, mode = SaMode.OR)
public R editPermissions(@Valid @RequestBody PermissionEditReq permissionEditReq) {
Map param = BeanUtil.beanToMap(permissionEditReq);
if(ObjectUtil.isEmpty(permissionEditReq.getId())) {
permissionService.insertPermission(param);
}else {
permissionService.updatePermission(param);
}
return R.success();
}
/**
* 权限管理-批量删除
* @param permissionDeleteReq
* @return
*/
@PostMapping("/permissions/deleteBatchPermission")
@SaCheckPermission(value = {"SYSTEM:PERMISSION:DELETE"}, mode = SaMode.OR)
public R deleteBatchPermission(@Valid @RequestBody PermissionDeleteReq permissionDeleteReq) {
Map param = BeanUtil.beanToMap(permissionDeleteReq);
Integer rows = permissionService.deleteBatchPermission(param);
return R.success(rows);
}
}