微服务模块的请求链路分析与权限设计
在这篇博客中,我们将探讨一个微服务模块中用户、角色、菜单和权限之间的对应关系,并详细分析其核心请求链路。通过清晰的结构和时序图,我们将展示系统的设计逻辑和实现细节。
用户/角色/菜单/权限的对应关系
在权限设计中,我们定义了以下关系:
- 用户和角色: 多对多关系(M:N)。一个用户可以拥有多个角色,一个角色可以被多个用户拥有。
- 角色和权限: 多对多关系(M:N)。一个角色可以关联多个权限,一个权限可以被多个角色使用。
- 权限和菜单: 多对一关系(M:1)。一个权限对应一个菜单,但一个菜单可以拥有多个权限。
这种设计允许灵活的权限分配,同时确保菜单与权限之间的明确映射。以下是一个简单的关系示意图:
用户 ↔ (M:N) 角色 ↔ (M:N) 权限 → (M:1) 菜单
这种结构支持复杂的权限管理需求,例如一个菜单可能需要多个权限才能访问,而这些权限可以动态分配给不同的角色。
微服务模块的请求链路分析
在这个微服务模块中,我们识别出三个核心请求链路:
- 菜单管理相关的请求链路
- 菜单权限相关的请求链路
- 角色管理相关的请求链路
下面我们将逐一分析这些链路的实现细节。
1. 菜单管理的请求链路
1.1 获取路由菜单
MenuController.route()
-> MenuService.listBySysType()
-> MenuMapper.listBySysType()
- 用户访问
/menu/route
接口。 MenuController.route()
方法被调用。MenuService.listBySysType()
查询当前用户有权限访问的菜单列表。MenuMapper.listBySysType()
从数据库中获取菜单数据。
1.2 获取单个菜单
MenuController.getByMenuId()
-> MenuService.getByMenuId()
-> MenuMapper.getByMenuId()
- 用户访问
/menu?menuId={id}
接口。 MenuController.getByMenuId()
方法被调用。MenuService.getByMenuId()
查询指定菜单详情。MenuMapper.getByMenuId()
从数据库中获取数据。
1.3 保存菜单
MenuController.save()
-> MenuService.save()
-> MenuMapper.save()
- 用户通过
/menu
接口发起 POST 请求。 MenuController.save()
方法被调用。MenuService.save()
保存菜单数据。MenuMapper.save()
将数据插入数据库。
1.4 更新菜单
MenuController.update()
-> MenuService.update()
-> MenuMapper.update()
- 用户通过
/menu
接口发起 PUT 请求。 MenuController.update()
方法被调用。MenuService.update()
更新菜单数据。MenuMapper.update()
将数据更新到数据库。
1.5 删除菜单
MenuController.delete()
-> MenuService.deleteById()
-> MenuMapper.deleteById()
- 用户访问
/menu?menuId={id}
接口发起 DELETE 请求。 MenuController.delete()
方法被调用。MenuService.deleteById()
删除指定菜单。MenuMapper.deleteById()
从数据库中删除数据。
2. 菜单权限的请求链路
2.1 获取菜单下的权限列表
MenuPermissionController.listByMenuId()
-> MenuPermissionService.listByMenuId()
-> MenuPermissionMapper.listByMenuId()
- 用户访问
/menu_permission/list_by_menu?menuId={id}
接口。 MenuPermissionController.listByMenuId()
方法被调用。MenuPermissionService.listByMenuId()
查询权限列表。MenuPermissionMapper.listByMenuId()
从数据库中获取数据。
2.2 获取单个菜单权限
MenuPermissionController.getByMenuPermissionId()
-> MenuPermissionService.getByMenuPermissionId()
-> MenuPermissionMapper.getByMenuPermissionId()
- 用户访问
/menu_permission?menuPermissionId={id}
接口。 MenuPermissionController.getByMenuPermissionId()
方法被调用。MenuPermissionService.getByMenuPermissionId()
查询权限详情。MenuPermissionMapper.getByMenuPermissionId()
从数据库中获取数据。
2.3 保存菜单权限
MenuPermissionController.save()
-> MenuPermissionService.save()
-> MenuPermissionMapper.save()
- 用户通过
/menu_permission
接口发起 POST 请求。 MenuPermissionController.save()
方法被调用。MenuPermissionService.save()
保存权限数据。MenuPermissionMapper.save()
将数据插入数据库。
2.4 更新菜单权限
MenuPermissionController.update()
-> MenuPermissionService.update()
-> MenuPermissionMapper.update()
- 用户通过
/menu_permission
接口发起 PUT 请求。 MenuPermissionController.update()
方法被调用。MenuPermissionService.update()
更新权限数据。MenuPermissionMapper.update()
将数据更新到数据库。
2.5 删除菜单权限
MenuPermissionController.delete()
-> MenuPermissionService.deleteById()
-> MenuPermissionMapper.deleteById()
- 用户访问
/menu_permission?menuPermissionId={id}
接口发起 DELETE 请求。 MenuPermissionController.delete()
方法被调用。MenuPermissionService.deleteById()
删除指定权限。MenuPermissionMapper.deleteById()
从数据库中删除数据。
3. 角色管理的请求链路
3.1 分页获取角色列表
RoleController.page()
-> RoleService.page()
-> RoleMapper.list()
- 用户访问
/role/page
接口。 RoleController.page()
方法被调用。RoleService.page()
查询角色分页数据。RoleMapper.list()
从数据库中获取角色列表。
3.2 获取单个角色
RoleController.getByRoleId()
-> RoleService.getByRoleId()
-> RoleMapper.getByRoleId()
-> RoleMenuMapper.getByRoleId()
- 用户访问
/role?roleId={id}
接口。 RoleController.getByRoleId()
方法被调用。RoleService.getByRoleId()
查询角色详情。RoleMapper.getByRoleId()
从数据库中获取角色数据。RoleMenuMapper.getByRoleId()
获取关联的菜单和权限ID。
3.3 保存角色
RoleController.save()
-> RoleService.save()
-> RoleMapper.save()
-> RoleMenuMapper.insertBatch()
- 用户通过
/role
接口发起 POST 请求。 RoleController.save()
方法被调用。RoleService.save()
保存角色数据。RoleMapper.save()
将角色数据插入数据库。RoleMenuMapper.insertBatch()
保存角色与菜单/权限的关联。
3.4 更新角色
RoleController.update()
-> RoleService.update()
-> RoleMapper.update()
-> RoleMenuMapper.deleteByRoleId()
-> RoleMenuMapper.insertBatch()
- 用户通过
/role
接口发起 PUT 请求。 RoleController.update()
方法被调用。RoleService.update()
更新角色数据。RoleMapper.update()
将角色数据更新到数据库。RoleMenuMapper.deleteByRoleId()
删除旧的关联关系。RoleMenuMapper.insertBatch()
保存新的关联关系。
3.5 删除角色
RoleController.delete()
-> RoleService.deleteById()
-> RoleMapper.deleteById()
-> RoleMenuMapper.deleteByRoleId()
-> UserRoleMapper.deleteByRoleId()
- 用户访问
/role?roleId={id}
接口发起 DELETE 请求。 RoleController.delete()
方法被调用。RoleService.deleteById()
删除指定角色。RoleMapper.deleteById()
从数据库中删除角色数据。RoleMenuMapper.deleteByRoleId()
删除角色与菜单/权限的关联。UserRoleMapper.deleteByRoleId()
删除用户与角色的关联。
请求链路时序图
以下是整个模块核心请求链路的 Mermaid 时序图:
sequenceDiagram
participant Client
participant MenuController
participant MenuService
participant MenuMapper
participant MenuPermissionController
participant MenuPermissionService
participant MenuPermissionMapper
participant RoleController
participant RoleService
participant RoleMapper
participant RoleMenuMapper
participant UserRoleMapper
Client->>MenuController: GET /menu/route
MenuController->>MenuService: listBySysType()
MenuService->>MenuMapper: listBySysType()
MenuMapper-->>MenuService: 菜单列表
MenuService-->>MenuController: 菜单列表
Client->>MenuPermissionController: GET /menu_permission/list_by_menu
MenuPermissionController->>MenuPermissionService: listByMenuId()
MenuPermissionService->>MenuPermissionMapper: listByMenuId()
MenuPermissionMapper-->>MenuPermissionService: 权限列表
MenuPermissionService-->>MenuPermissionController: 权限列表
Client->>RoleController: GET /role/page
RoleController->>RoleService: page()
RoleService->>RoleMapper: list()
RoleMapper-->>RoleService: 角色分页列表
RoleService-->>RoleController: 角色分页列表
Client->>RoleController: GET /role
RoleController->>RoleService: getByRoleId()
RoleService->>RoleMapper: getByRoleId()
RoleMapper-->>RoleService: 角色详情
RoleService->>RoleMenuMapper: getByRoleId()
RoleMenuMapper-->>RoleService: 关联菜单权限ID
RoleService-->>RoleController: 角色详情
Client->>RoleController: POST /role
RoleController->>RoleService: save()
RoleService->>RoleMapper: save()
RoleMapper-->>RoleService: 保存角色
RoleService->>RoleMenuMapper: insertBatch()
RoleMenuMapper-->>RoleService: 保存角色菜单权限关系
Client->>RoleController: PUT /role
RoleController->>RoleService: update()
RoleService->>RoleMapper: update()
RoleMapper-->>RoleService: 更新角色
RoleService->>RoleMenuMapper: deleteByRoleId()
RoleMenuMapper-->>RoleService: 删除旧菜单权限关系
RoleService->>RoleMenuMapper: insertBatch()
RoleMenuMapper-->>RoleService: 保存新菜单权限关系
Client->>RoleController: DELETE /role
RoleController->>RoleService: deleteById()
RoleService->>RoleMapper: deleteById()
RoleMapper-->>RoleService: 删除角色
RoleService->>RoleMenuMapper: deleteByRoleId()
RoleMenuMapper-->>RoleService: 删除角色菜单权限关系
RoleService->>UserRoleMapper: deleteByRoleId()
UserRoleMapper-->>RoleService: 删除用户角色关系
总结
通过以上分析,我们可以看到:
- 职责清晰:Controller 负责请求处理,Service 实现业务逻辑,Mapper 负责数据库操作。
- 事务管理:在保存或更新角色等复杂操作中,Service 层通过事务控制确保数据一致性。
- 灵活性与可维护性:M:N 和 M:1 的关系设计支持动态权限分配,同时模块化的请求链路便于扩展和优化。
这份分析为后续的功能开发和性能优化提供了坚实的基础,同时也展示了微服务架构下权限管理的典型实现方式。