Java系列文章
文章目录
- Java系列文章
- 前言
- 一、基础概念
- 1.1 RBAC模型核心概念
- 1.2 Sa-Token核心功能
- 1.3 环境准备
- 二、表结构设计
- 2.1 ER图示例
- 2.2 数据库表设计
- 2.2.1 用户表
- 2.2.2 角色表
- 2.2.3 部门表
- 2.2.4 权限表
- 三、SpringBoot整合Sa-Token
- 3.1 sa-token基础配置
- 3.1.1 Maven配置
- 3.1.2 application.yml
- 3.1.3 StpUtil鉴权工具类
- 3.1.4 编写鉴权类
- 四、RBAC模型设计与实现
- 4.1 用户管理及登陆实现
- 4.1.1 定义UserDao类实现接口
- 4.1.2 配置UserDao.xml映射信息
- 4.1.3 Service 业务层
- 4.1.4 Controller Web层
- 4.1.5 登录返回权限列表
- 4.1.6 用户分配角色
- 4.2 角色管理实现
- 4.2.1 定义RoleDao类实现接口
- 4.2.2 配置RoleDao.xml映射信息
- 4.2.3 Service 业务层
- 4.2.4 Controller Web层
- 4.2.5 角色分配权限
- 4.3 部门管理实现
- 4.31 定义DeptDao类实现接口
- 4.3.2 配置DeptDao.xml映射信息
- 4.3.3 Service 业务层
- 4.3.4 Controller Web层
- 4.3.5 部门页面编辑
- 4.4 权限管理实现
- 4.4.1 定义PermissionDao类实现接口
- 4.4.2 配置PermissionDao.xml映射信息
- 4.4.3 Service 业务层
- 4.4.4 Controller Web层
- 4.4.5 权限列表编辑
前言
本文将介绍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 {@Resourceprivate UserDao userDao;/*** 返回一个用户所拥有的权限集合*/@Overridepublic 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;}/*** 返回一个用户所拥有的角色标识集合*/@Overridepublic 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 mapperPUBLIC "-//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_nameFROM tb_user uJOIN 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.iconFROM tb_user uJOIN 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 idfrom tb_userwhere 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_roleWHERE JSON_CONTAINS ( u.role, CONVERT (id, CHAR) )) AS rolesFROM tb_user uJOIN 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_userSETusername=#{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_userSETname=#{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 {@Resourceprivate UserDao userMapper;// 用户管理-查询idpublic 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 {@Resourceprivate UserService userService;@Resourceprivate 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传递userIdStpUtil.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 mapperPUBLIC "-//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">SELECTr.id,r.role_name AS roleName,COUNT( u.id ) AS users,JSON_LENGTH ( r.permissions ) AS permissionsLength,r.permissions,r.desc,r.systemic,r.echoFROM tb_role rLEFT 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.idORDER BY r.id</select><!-- 角色管理-新增 --><insert id="insertRole">insert into tb_roleSETrole_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 {@Resourceprivate 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 {@Resourceprivate 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 mapperPUBLIC "-//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">selectd.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 = 1AND 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_deptset `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 {@Resourceprivate 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;}//部门列表-查询idpublic 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 {@Resourceprivate 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 mapperPUBLIC "-//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_permissionset `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 {@Resourceprivate 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 {@Resourceprivate 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);}
}