Activiti原理分析(三)用户管理

简介: Activiti 原理分析系列文章的第三篇。这篇主要研究 Activiti 内置的用户管理系统,以及受理人,候选人等概念。

Activiti 自带一套用户管理系统,维护了用户和用户组的对应关系,通过 identityService 可以对它们进行增删改查。当你在 UserTask 中指定了用户组时,Activiti 就会使用它维护的这个关系寻找用户了。

但是这也为 Activiti 的使用带来了困难,因为一般应用都有一套自建的用户管理,不可能去使用 Activiti 这一套,就不得不花一些成本来对接,而且对接方法都比较 hack,个人觉得这是 Activiti 设计得不太好的地方。

受理人与候选人

一个 UserTask 可以设置一个受理人(Assignee),或者多个候选人。

受理人就是负责完成该任务的人,在审批场景下就可以理解成审批人,只能有一个,如果要有多个的话则应该使用上一篇文章提到的多实例任务。

<!--kermit就是受理人的 id--><userTaskid="theTask"name="my task"activiti:assignee="kermit"/>

候选人可以有一个或者多个,他们都是受理人的“候选”,他们要“抢”任务,谁先调用了 taskService.claim(taskId, userId);,谁就变成了任务的受理人。

<!--两个候选人 kermit与gonzo--><userTaskid="theTask"name="my task"activiti:candidateUsers="kermit,gonzo"/>


<!--management用户组的所有用户作为候选人--><userTaskid="theTask"name="my task"activiti:candidateGroups="management"/>


内置的用户管理

Activiti 中的用户模型非常简单,就是用户和用户组之间的多对多关系,所以只涉及三张表:

  • ACT_ID_USER:用户信息
  • ACT_ID_GROUP:用户组信息
  • ACT_ID_MEMBERSHIP:存储用户和用户组之间的多对多关联


image-20201129122719757.png


流程运行时用户信息

在应用中一般会调用下面的方法查询某个用户的 task:


// 查询所有候选 userId 的任务List<Task>tasks=taskService.createTaskQuery()
                    .taskCandidateUser(userId).list();
// 查询所有 userId 受理的任务List<Task>tasks=taskService.createTaskQuery()
                    .taskAssignee(userId).list();
// 查询所有 userId候选或者受理的任务List<Task>tasks=taskService.createTaskQuery()
                    .taskCandidateOrAssigned(userId).list();


受理人查询

ACT_RU_TASK 表中本来就有一个 ASSIGNEE_ 字段表示受理人,所有当你使用 taskAssignee(userId) 查询时,直接就是用的 ASSIGNEE_=userIdACT_RU_TASK 表中去查的。

候选人查询

在流程运行时还会有一张 ACT_RU_IDENTITYLINK 表,用来记录流程运行时相关的人员信息,比如流程发起人,参与人,Task 的候选人等信息:


image-20201129124614947.png

其中 TYPE_ 有以下几种取值:

  • starter: 流程发起人
  • participant: 流程参与人,当前的受理人就会被记录在这里
  • candidate: Task 对应的候选人或者候选用户组

因为这是一张运行时表,所以里面数据是会随着流程运转不断增删改的。

当你使用 taskCandidateUser(userId) 条件查询时其实就是去这张表里根据 TYPE_='candidate' AND USER_ID_=userId 找到用户候选的 Task

候选用户组

假如你将 UserTask 配置成 activiti:candidateGroups="management" ,如果 userId 属于 manangement 用户组,那么使用 taskCandidateUser(userId) 条件查询,也是能查出该 UserTask 的。

此时就需要用到上一小节提到的用户管理相关表了。Activiti 如果会去 ACT_ID_MEMBERSHIP 中找到该用户的  groupId,然后去 ACT_RU_IDENTITYLINK 中根据 GROUP_ID_ 查。

Activiti 如何与已有用户管理系统对接?

从上面的分析可以看到,Activiti 只有在你配置了 candidateGroups 才可能去查询内置的用户管理信息,所以个人建议是就不要使用 candidateGroups 配置了,全部使用 candidateUsersassignee,然后在 userId 里加入一些特征区分用户组或者别的业务相关的东西,比如加个前缀 GROUP-groupId,之后就全部用自己业务系统里的 id 去查 Task。不用担心这些ID在 Activiti 内置的用户管理系统中没有,Activiti 根本不会去校验这个。

当然也有人研究过一些更加麻烦的对接方法,列出如下,也可以参考:

  • 往 Activiti 内置的用户表中,同步自己业务的用户数据。个人感觉比较麻烦,而且也容易出各种问题
  • 将 Activiti 用户相关存储类用自己的实现类换掉。听起来很复杂,但是因为 Activiti 6 所采用的可插拔的存储层设计,其实只要替换两类就可以了,后面我有空会再研究一下它的存储层设计。而且如果要搞分库分表的话,存储层本来就是要重新弄的,顺手就可以把用户管理换掉。
  • 用业务用户数据的视图替换掉 Activiti 内置用户管理的这三张表。感觉不一定所有的业务用户数据都可以映射到 Activiti 的用户模型,所有通用性有限

参考


相关文章
|
6月前
|
移动开发 前端开发
基于jeecg-boot的flowable流程跳转功能实现
基于jeecg-boot的flowable流程跳转功能实现
131 0
|
5月前
|
缓存 安全 Java
【权限管理系统】Spring security(三)---认证过程(原理解析,demo)
【权限管理系统】Spring security(三)---认证过程(原理解析,demo)
|
6月前
|
SQL Java 数据库连接
一文带你快速学会SpringBoot工程下MaBatis对数据的增删改查功能!
在SpringBoot项目中,已配置好Mybatis和Lombok,数据库tb_user有四条初始数据。需求是按ID删除用户。首先在UserMapper接口添加@Delete注解的删除方法,然后在单元测试类中测试此方法,成功删除ID为4的用户。删除方法可选返回影响的记录数,此处用void。参数名在#{...}内可自定义。通过配置mybatis日志在控制台显示SQL操作。
|
6月前
|
前端开发 JavaScript Java
基于Springboot+SpringSecurity+Activiti7实现的工作流系统可方便二次开发(附完整源码)
基于Springboot+SpringSecurity+Activiti7实现的工作流系统可方便二次开发(附完整源码)
191 0
|
6月前
|
存储 Java 关系型数据库
SpringSecurity入门案例——基本功能讲解
SpringSecurity入门案例——基本功能讲解
34 0
|
SQL Java 关系型数据库
Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.0
Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.0
198 0
|
存储 SQL 数据库
SpringSecurity基础-记住我功能实现
Remember me(记住我)记住我,当用户发起登录勾选了记住我,在一定的时间内再次访问该网站会默认登录成功,即使浏览器退出重新打开也是如此,这个功能需要借助浏览器的cookie实现,具体流程如下
78 0
|
存储 SQL 数据库
七.SpringSecurity基础-记住我功能实现
SpringSecurity基础-记住我功能实现
|
XML 数据可视化 Java
activiti框架搭建及问题记录
activiti框架搭建及问题记录
129 0
|
SQL Java 数据库连接
【Spring】作业记录:spring项目从创建、配置到功能实现、测试
【Spring】作业记录:spring项目从创建、配置到功能实现、测试
102 0
【Spring】作业记录:spring项目从创建、配置到功能实现、测试