SpringBoot整合Sa-Token:實現RBAC權限模型

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);}
}

4.4.5 權限列表編輯

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907237.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907237.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907237.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

工商業儲能的“智慧大腦”:解密 Acrel-2000ES EMS 的核心功能與價值

安科瑞電氣顧強 市場背景&#xff1a;工商業儲能加速崛起 2022年中國已并網的儲能項目中&#xff0c;用戶側并網占比為8.36%&#xff0c;其中工商業儲能占據了用戶側高達98.6%的份額。驅動這一市場發展的關鍵因素日益顯著&#xff1a; 1.峰谷價差擴大&#xff1a; 全國各省市…

vue+threeJs 根據屏幕調整gltf模型的大小、重心、并更換騎車整體顏色

嗨&#xff0c;我是小路。今天主要和大家分享的主題是“vuethreeJs 根據屏幕調整gltf模型的大小、重心、并更換騎車整體顏色”。 項目案例示意圖 1.整體更換gltf模型的顏色 定義&#xff1a;整體代碼如下。顏色是事先設定的 const colorAry reactive(["rgb(21…

03 基于 java udp 做一個dns服務器 和 一個dns代理服務器

前言 這個也是 來自于一個朋友的需求 最終的目的是實現一個 dns 代理服務器, 當然 這本質也是一個 dns 服務器 并且 dns 代理服務器是依賴于 一個 dns 服務器的, 因此 順便給一個 dns 服務器的 demo 這里 主要是 基于 udp 的一個 dns 請求, 響應數據的交互 dns 服務器 …

【HITCSAPP 哈工大計算機系統期末大作業】 程序人生-Hello’s P2P

計算機系統 大作業 題 目 程序人生-Hello’s P2P 專 業 計算機與電子通信類 學   號 2023112915 班   級 23L0505 學 生 楊昕彥 指 導 教 師 劉宏偉 計算機科學…

第十周作業

一、CSRF 1、DVWA-High等級 2、使用Burp生成CSRF利用POC并實現攻擊 二、SSRF&#xff1a;file_get_content實驗&#xff0c;要求獲取ssrf.php的源碼 三、RCE 1、 ThinkPHP 2、 Weblogic 3、Shiro

PTA刷題筆記(難度預警!!!有詳解)

7-18 二分法求多項式單根 代碼如下&#xff1a; ? #include <stdio.h> #include <math.h>// 定義多項式函數 double polynomial(double x, double a3, double a2, double a1, double a0) {return a3 * x * x * x a2 * x * x a1 * x a0; }// 二分法求根函數 do…

打破傳統范式,線上 3D 畫展彰顯多元亮點

&#xff08;一&#xff09;沉浸式體驗&#xff0c;身臨其境賞畫? 線上 3D 畫展運用先進的 3D 建模和虛擬現實&#xff08;VR&#xff09;技術&#xff0c;高度還原了真實的展廳環境 。展廳內的布局、燈光&#xff0c;甚至墻壁的質感都被完美復刻&#xff0c;讓觀眾仿佛置身于…

Docker架構詳解

一,Docker的四大要素&#xff1a;Dockerfile、鏡像(image)、容器(container)、倉庫(repository) 1.dockerfile&#xff1a;在dockerfile文件中寫構建docker的命令,通過dockerbuild構建image 2.鏡像&#xff1a;就是一個只讀的模板&#xff0c;鏡像可以用來創建docker容器&…

【工具類】常用的工具類——CollectionUtil

目錄 cn.hutool.core.collection.CollectionUtil集合創建集合清空集合判空集合去重集合過濾集合轉換集合合并集合交集集合差集集合是否包含元素集合是否包含指定元素&#xff08;自定義條件&#xff09;集合分頁集合分組集合轉字符串元素添加元素刪除根據屬性轉Map獲取元素獲取…

從零起步搭建基于華為云構建碳排放設備管理系統的產品設計

目錄 &#x1f33f; 華為云 IoT&#xff1a;輕松上手碳排放設備管理系統搭建 &#x1f30d; 逐步搭建搭建規劃 &#x1f680; 一、系統藍圖&#xff1a;5大核心模塊&#xff0c;循序漸進 1?? 設備管理與數據采集層 2?? 數據傳輸與協議轉換層 3?? 數據處理與分析層…

華為OD機試真題—— 小明減肥(2025B卷:100分)Java/python/JavaScript/C/C++/GO最佳實現

2025 B卷 100分 題型 本專欄內全部題目均提供Java、python、JavaScript、C、C++、GO六種語言的最佳實現方式; 并且每種語言均涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、3個測試用例以及綜合分析; 本文收錄于專欄:《2025華為OD真題目錄+全流程解析+備考攻略+經驗分…

數據結構 -- 插入排序(直接插入排序和希爾排序)

插入排序 算法思想 每次將?個待排序的記錄按其關鍵字大小插入到前面已排好序的子序列中&#xff0c;直到全部記錄插入完成。 代碼實現 void InsertSort(int A[],int n){int i,j,temp;for(i 1;i<n;i){if(A[i]<A[i-1]){temp A[i]; //用temp暫存A[i]for(ji-1;j>…

word中表格拉不動以及插入圖片有間距

word中的表格寬度和高度怎么調整都改不了&#xff0c;可以將選中表格—右鍵—段落—取消勾選下圖中的兩項。 word中表格插入圖片始終有間隙&#xff0c;怎么也消除不了間隙&#xff0c;可以在表布局—單元格邊距—修改上下左右邊距為0即可

網絡抓包命令tcpdump及分析工具wireshark使用

文章目錄 環境文檔用途詳細信息 環境 系統平臺&#xff1a;Linux x86-64 Red Hat Enterprise Linux 8,Linux x86-64 Red Hat Enterprise Linux 7,Linux x86-64 SLES 12,銀河麒麟 &#xff08;鯤鵬&#xff09;,銀河麒麟 &#xff08;X86_64&#xff09;,銀河麒麟&#xff08;龍…

Eigen矩陣存儲順序以及轉換

一、Eigen矩陣存儲順序 在矩陣運算和線性代數中,"行優先"(Row-major)和"列優先"(Column-major)是兩種不同的存儲方式,它們決定了多維數組(如矩陣)在內存中的布局順序。 1. 行優先(Row-major) 定義:矩陣按行順序存儲在內存中,即第一行的所有元…

快速部起一個Openwhisk平臺,使用telego k8s服務部署能力內網部署

Telego 簡介與 OpenWhisk 部署實踐 概述 Telego 是一個用于便攜式 Kubernetes 部署的工具&#xff0c;旨在解決容器鏡像拉取中的網絡代理問題。本文檔描述了如何通過 Telego 將 Apache OpenWhisk&#xff08;一個 Serverless 計算平臺&#xff09;部署到 Kubernetes 集群&…

LockSupport與Condition解析

本章我們介紹兩個Java 并發包中用于線程協作的工具--LockSupport和Condition LockSupport&#xff1a; Java 并發包&#xff08;java.util.concurrent.locks&#xff09;提供了基于許可&#xff08;permit&#xff09;的線程阻塞和喚醒機制--LockSupport 對于LockSupport是通…

【機器學習基礎】機器學習入門核心算法:邏輯回歸(Decision Tree)

機器學習入門核心算法&#xff1a;邏輯回歸&#xff08;Decision Tree&#xff09; 一、算法邏輯1.1 基本概念1.2 算法流程 二、算法原理與數學推導2.1 特征選擇指標信息熵&#xff08;ID3算法&#xff09;信息增益&#xff08;Information Gain&#xff09;信息增益率&#xf…

網絡編程3

管道的性質 讀緩沖區為空&#xff0c;read阻塞寫緩沖區為空&#xff0c;write阻塞一端先close&#xff0c;另一端繼續read&#xff0c;read不阻塞&#xff0c;立刻返回0一端先close&#xff0c;另一端繼續write&#xff0c;write會觸發SIGPIPE信號&#xff0c;進程異常終止 soc…

influxdb時序數據庫

以下概念及操作均來自influxdb2 官方文檔 InfluxDB2 is the platform purpose-built to collect, store, process and visualize time series data. Time series data is a sequence of data points indexed in time order. Data points typically consist of successive meas…