Flowable-8.流程实例系列
Flowable框架学习笔记-08-流程实例系列
RuntimeService
概念说明
RuntimeService
用于启动流程定义的新流程实例。流程定义中定义了流程中不同步骤的结构与行为。流程实例则是流程定义的实际执行过程。
RuntimeService
派生类:ProcessInstanceBuilder可用于启动流程实例的相关参数
启动流程实例的方式:startProcessInstanceByXXX
流程定义、执行实例、流程实例说明:
流程定义:类似Java类,约定一系列规则
执行实例:流程执行的每个节点
流程实例ProcessInstance(执行实例根节点):代表流程定义的执行实例,一个流程实例包括所有的运行节点,其表示一个流程从开始到结束的最大 的流程分支,一个流程中流程实例只有一个
Execution的含义就是一个流程实例(ProcessInstance)具体要执行的过程对象
启动流程的时候会先创建流程实例,然后创建执行实例,当所有的执行实例按照指定规则执行完毕,则流程实例随之结束
当两个执行实例执行结束后汇聚到同一个网关才会继续往下执行
RuntimeService
RuntimeService
- 启动流程及对流程数据对控制
- 流程实例(ProcessInstance)与执行流(Execution)查询
- 触发流程操作、接收消息和信号
RuntimeService启动流程变量管理
- 启动流程的常用方式(id,key,message)
- 启动流程可选参数(businesskey,variables,tenantId)
- 变量(variables)的设置和获取
流程实例与执行流
- 流程实例(ProcessInstance)表示一次工作流业务的数据实体
- 执行流(Execution)表示流程实例中具体的执行路径
- 流程实例接口继承与执行流
流程触发
- 使用trigger触发ReceiveTask节点
- 触发信号捕获事件signalEvenReceived
- 触发消息捕获事件messageEventReceived
方法 | 含义 |
---|---|
runtimeService.startProcessInstanceByKey (String processDefinitionKey, Map<String, Object> variables) | 根据部署流程key启动一个流程 |
runtimeService.startProcessInstanceById (String processDefinitionId, Map<String, Object> variables) | 根据部署流程id启动一个流程 |
runtimeService.createProcessInstanceBuilder() .businessKey("businessKey001") .processDefinitionKey(String processDefinitionKey) .variables( Map<String, Object> variables) .start() | 根据processInstanceBuilder启动流程 |
runtimeService.getVariables(processInstance.getId()) | 根据流程实例id获取传参 |
runtimeService.setVariable(processInstance.getId(),"key3","value3") | 新增或修改参数 |
runtimeService.createProcessInstanceQuery() .processInstanceId(processInstance.getId()) | 根据流程id获取流程实例 |
runtimeService.createExecutionQuery() | 获取流程执行对象 |
TaskService
TaskService
- 对用户任务(UserTask)管理和流程控制
- 设置用户任务(UserTask)对权限信息(拥有者,候选人,办理人)
- 针对用户任务添加任务附件、任务;评价和事件记录
TaskService对Task管理与流程控制
- Task对象对创建,删除
- 查询Task,并驱动Task节点完成执行
- Task相关参数变量(variable)设置
方法 | 含义 |
---|---|
taskService.createTaskQuery().list() | 查询所有任务 |
taskService.setVariable("任务id","键","值") | 设置普通变量 |
taskService.setVariableLocal("任务id","键","值") | 设置本地变量 |
taskService.getVariables("任务id") | 获取普通变量 |
taskService.getVariablesLocal(("任务id") | 获取本地变量 |
runtimeService.getVariables(task.getExecutionId()) | 通过流获取变量 |
taskService.complete("任务id","传值Map") | 到下一个节点 |
TaskService设置Task权限信息
- 候选用户(candidateUser)和候选组(candidateGroup)
- 指定拥有人(Owner)和办理人(Assignee)
- 通过claim设置办理人
方法 | 含义 |
---|---|
taskService.setOwner("taskId","user") | 设置流程发起人 |
taskService.claim(""taskId"","user") | 指定代办人 |
taskService.addCandidateUser("user") | 添加候选人 |
taskService.addCandidateGroup("group") | 添加候选组 |
taskService.createTaskQuery().taskCandidateUser("user").taskUnassigned().list() | 查询候选人列表有user但是没指定代办人任务 |
taskService.createTaskQuery().taskCandidateUser("user").taskUnassigned().list() | 查询候选人列表有我但是没指定代办人任务 |
taskService.createTaskQuery().taskAssignee("user").list() | 查询代办人为user的任务 |
taskService.getIdentityLinksForTask("taskId") | 查询任务与人员之间的关系 |
TaskService设置Task附加信息
- 任务附件(Attachment)创建与查询
- 任务评价(Comment)创建与查询
方法 | 含义 |
---|---|
taskService.createAttachment ("类型","任务id","流程Id","附件名称","附件描述","流或者url) | 上传附件 |
taskService.getTaskAttachments("任务id") | 上传附件 |
taskService.addComment("任务id","流程id","批注1") | 添加审批批注 |
taskService.getTaskComments("任务id") | 查询审批批注 |
taskService.getTaskEvents("任务id") | 查询任务日志记录 |
数据表结构分析
ACT_RU_EXECUTION(运行时流程执行实例表核心表)
字段 | 字段名称 | 数据类型 | 字段长度 | 键 | 备注 |
---|---|---|---|---|---|
ID_ | 主键 | varchar | 64 | PRI | |
REV_ | 版本号 | int | NULL | 数据库表更新次数 | |
PROC_INST_ID_ | 流程实例ID | varchar | 64 | MUL (ACT_RU_EXECUTION) | 一个流程实例不管有多少条分支实例,这个ID都是一致的 |
BUSINESS_KEY_ | 业务标识 | varchar | 255 | MUL | 业务主键:主流程才会使用业务主键,这个业务主键字段在表中有唯一约束 |
PARENT_ID_ | 父级ID | varchar | 64 | MUL (ACT_RU_EXECUTION) | 父实例ID:同步节点会产生两条执行记录,这两条记录的父ID为主线的ID |
PROC_DEF_ID_ | 流程定义ID | varchar | 64 | MUL (ACT_RE_PROCDEF) | 流程定义ID |
SUPER_EXEC_ | 父流程实例中对应的 执行 | varchar | 64 | MUL (ACT_RU_EXECUTION) | |
ACT_ID_ | 节点ID | varchar | 255 | 流程运行到的节点 | |
IS_ACTIVE_ | 是否激活 | tinyint | NULL | ||
IS_CONCURRENT_ | 是否分支(并行) | tinyint | NULL | 是否为并行(true/false) | |
IS_SCOPE_ | 是否处于多实例或环 节嵌套状态 | tinyint | NULL | ||
IS_EVENT_SCOPE_ | 是否激活状态 | tinyint | NULL | ||
SUSPENSION_STATE_ | 挂起状态 | int | NULL | 暂停状态 1激活 2暂停 | |
CACHED_ENT_STATE_ | 缓存状态 | int | NULL | 缓存的状态, 1 事件 监听 2 人工任务 3 异 步作业 | |
TENANT_ID_ | 租户ID | varchar | 255 | 租户ID:针对多租户设计 | |
NAME_ | 名称 | varchar | 255 | ||
LOCK_TIME_ | 锁定时间 | timestamp | NULL |
ACT_RU_TASK(运行时任务节点表核心表)
字段 | 字段名称 | 数据类 | 字段长度 | 键 | 备注 |
---|---|---|---|---|---|
ID_ | 主键 | varchar | 64 | PRI | |
REV_ | 版本号 | int | NULL | version | |
EXECUTION_ID_ | 执行实例ID | varchar | 64 | MUL (ACT_RU_EXECUTION) | |
PROC_INST_ID_ | 流程实例ID | varchar | 64 | MUL (ACT_RU_EXECUTION) | |
PROC_DEF_ID_ | 流程定义ID | varchar | 64 | MUL (ACT_RE_PROCDEF) | |
NAME_ | 名称 | varchar | 255 | ||
PARENT_TASK_ID_ | 父任务ID | varchar | 64 | ||
DESCRIPTION_ | 描述 | varchar | 4000 | ||
TASK_DEF_KEY_ | 人物定义标识 | varchar | 255 | ||
OWNER_ | 被代理人 | varchar | 255 | (一般情况下为空,只有在委托时才有值) | |
ASSIGNEE_ | 经办人 | varchar | 255 | 签收人或者委托人 | |
DELEGATION_ | 委托状态 | varchar | 64 | 委托状态 PENDING 委托中, RESOLVED已处理 | |
PRIORITY_ | 优先级 | int | NULL | ||
CREATE_TIME_ | 创建时间 | timestamp | NULL | MUL | |
DUE_DATE_ | 截止时间 | datetime | NULL | ||
CATEGORY_ | 分类 | varchar | 255 | ||
SUSPENSION_STATE_ | 挂起状态 | int | NULL | 暂停状态 1激活 2暂停 | |
TENANT_ID_ | 租户ID | varchar | 255 | ||
FORM_KEY_ | 表单标识 | varchar | 255 |
ACT_HI_PROCINST(流程实例历史核心表)
字段 | 字段名称 | 数据类 | 字段长度 | 键 | 备注 |
---|---|---|---|---|---|
ID_ | 主键 | varchar | 64 | PRI | |
PROC_INST_ID_ | 流程实例ID | varchar | 64 | UNI | |
BUSINESS_KEY_ | 业务标识 | varchar | 255 | MUL | 业务主键,业务表单的ID |
PROC_DEF_ID_ | 流程实例ID | varchar | 64 | ||
START_TIME_ | 开始时间 | datetime | NULL | ||
END_TIME_ | 结束时间 | datetime | NULL | MUL | |
DURATION_ | 耗时 | bigint | NULL | ||
START_USER_ID_ | 流程发起人ID | varchar | 255 | ||
START_ACT_ID_ | 开始节点ID | varchar | 255 | ||
END_ACT_ID_ | 结束节点ID | varchar | 255 | ||
SUPER_PROCESS_INSTANCE_ID_ | 父流程实例ID | varchar | 64 | ||
DELETE_REASON_ | 删除原因 | varchar | 4000 | ||
TENANT_ID_ | 租户ID | varchar | 255 | ||
NAME_ | 名称 | varchar | 255 | ||
历史流程实例表:存放历史的流程实例;设计历史流程实例表的初衷之一就是为了使得运行时库数据量尽可能小,效率最优
ACT_HI_ACTINST(历史节点表)
字段 | 字段名称 | 数据类 | 字段长度 | 键 | 备注 |
---|---|---|---|---|---|
ID_ | 主键 | varchar | 64 | PRI | |
PROC_DEF_ID_ | 流程定义ID | varchar | 64 | ||
PROC_INST_ID_ | 流程实例ID | varchar | 64 | MUL | |
ACT_ID_ | 节点ID | varchar | 255 | ||
TASK_ID_ | 任务ID | varchar | 64 | 任务实例ID 其他节点类型实例ID在这里为空 | |
CALL_PROC_INST_ID_ | 调用外部的流程实例ID | varchar | 64 | ||
ACT_NAME_ | 节点名称 | varchar | 255 | ||
ACT_TYPE_ | 节点类型 | varchar | 255 | 如startEvent、userTask | |
ASSIGNEE_ | 签收人 | varchar | 255 | 经办人 | |
START_TIME_ | 开始时间 | datetime | NULL | MUL | |
END_TIME_ | 结束时间 | datetime | NULL | MUL | |
DURATION_ | 耗时 | bigint | NULL | 毫秒值 | |
TENANT_ID_ | 多租户 | varchar | 255 | ||
说明:历史活动信息-记录流程流转过的所有节点,与HI_TASKINST不同的是,taskinst只记录usertask内容。
运行案例分析
数据表说明
ACT_RU_EXECUTION:正在执行的信息 ACI_HI_PORINST:已经执行完的历史流程实例信息 ACT_HI_ACTINST:存放历史所有完成的活动 ACT_RU_TASK:正在执行的任务信息 ACT_HI_TASKINST:已经执行完的历史任务信息
流程定义
流程设计
提交申请:指定分配人;审批[主管]:指定分配人;审批[经理]:指定分配人
部署流程
此处使用classpath方式部署流程
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource(xmlName)
.deploy();
// 一个流程定义对应多个流程实例
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deployment.getId())
.singleResult();
分析流程实例
启动流程实例
操作数据库是ACT_RU_EXECTION表,如果是用户任务节点,同时也会在ACT_RU_TASK表中添加记录
ASSIGNEE_:指定分配人
流程实例的PARENT_ID字段为空,执行实例的PARENT_ID不为空
// 将JSONObject对象转化为Map<String,Object>,其中taskCustomManager为客户经理信息
Map<String, Object> params = JSONObject.parseObject(jsonObject.toJSONString(),
new TypeReference<Map<String, Object>>() {});
// 启动任务实例,并存储临时变量
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("apply", params);
执行实例走到任务节点的时候,会暂时处于等待状态,需要完成这个节点,执行实例才可以开始运转
任务说明
a.查询个人任务:
借助TaskService获取任务查询对象
指定查询分页排序等过滤条件,使用taskAssignee
指定任务的办理者(查询指定用户的待办任务)
调用list
方法执行查询,返回指定用户的任务列表
从act_ru_task可查询任务ID、名称、班里人、创建时间等属性
如果指定assignee属性查询结果为空,则说明当前指定用户并没有参与该流程或者是流程目前只是到了某个阶段但后面的任务还没有执行,因此当前数据库中没有指定用户可以办理的任务,故返回结果为空
一个Task节点和Execution节点是一对一的情况,在task对象中使用Execution_来关联
@RequestMapping("/getTask")
public void getTask(String userId,String defKey) {
List<Task> list = taskService.createTaskQuery()
.taskAssignee(userId)
.processDefinitionKey(defKey)
.list();
for(Task t : list){
System.out.println(t.getId()+" "+t.getName()+" "+t.getTaskDefinitionKey());
}
}
访问:http://localhost:8090/sbf-demo/apply/getTask?userId=common_user&defKey=apply
可以看到当前流程节点在‘提交申请’这部分,指定分配完成任务的是‘common_user’
b.完成个人任务
借助TaskService执行complete方法,完成当前指定任务
可以看到,完成任务是以任务id为参考的,在完成任务的时候不需要指定完成者,ASSIGNEE_属性的填充是以业务为导向的
@RequestMapping("/completeTask")
public void completeTask(String taskId) {
taskService.complete(taskId);
}
当执行完上述操作,再以员工common_user
的身份查询任务则发现并没有数据,因为正在执行中的任务中没有数据
对于执行完的任务,Flowable会将其从ACT_RU_TASK表中删除,并将下一个任务插入(两个操作在同一个事务)
因此,当执行完指定任务时,可以看到common_user的任务已经结束了,流程进入下一节点"审批[主管]"
以此类推,每次执行办理任务代码都会按照这种模式调整数据库
再次执行‘办理任务’代码,此次执行id为当前节点的taskId,则可看到流程进入下一节点"审批[经理]"
当前节点进入"审批[经理]"为最后一个节点,因此当这个节点完成之后则流程实例和相应的执行实例也相应结束,可以看到ACT_RU_EXECUTION对应的流程和执行数据被清理
流程状态(流行实例状态获取)
根据RuntimeService创建流程实例查询对象(设置实例ID作为过滤参数)
判断指定ID的实例是否存在,如果为null则表示流程结束(实例正在执行的执行对象表中已删除,转换为历史数据)
@RequestMapping("/getProcessInstanceState")
public AjaxResult getProcessInstanceState(String processInstanceId) {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
if(processInstance!=null){
return AjaxResultUtil.success("当前流程实例正在运行");
}else{
return AjaxResultUtil.success("当前流程实例已经结束");
}
}
# SQL语句分析:流程实例PARENT_ID为null
SELECT DISTINCT
RES.*,
P .KEY_ AS ProcessDefinitionKey,
P .ID_ AS ProcessDefinitionId,
P .NAME_ AS ProcessDefinitionName,
P .VERSION_ AS ProcessDefinitionVersion,
P .DEPLOYMENT_ID_ AS DeploymentId
FROM
ACT_RU_EXECUTION RES
INNER JOIN ACT_RE_PROCDEF P ON RES.PROC_DEF_ID_ = P .ID_
WHERE
RES.PARENT_ID_ IS NULL
AND RES.ID_ = ?
AND RES.PROC_INST_ID_ = ?
ORDER BY
RES.ID_ ASC
由于一个流程实例ID只对应一个实例,使用singleResult执行查询返回一个唯一的结果,但是如果返回结果数量大于1则会抛出异常
在流程执行的过程中,创建的流程实例ID在整个过程中都不会变,当流程结束之后,流程实例将会在正在执行的执行对象表(ACT_RU_EXECUTION)被删除
执行实例与流程实例的查询结果对比
流程实例本身就是一个执行实例
/** 查询执行实例 **/
@RequestMapping("/getExecution")
public void getExecution() {
List<Execution> executionList = runtimeService.createExecutionQuery().list();
for(Execution execution : executionList){
System.out.println(execution.getId());
}
}
历史数据
历史数据查询-历史流程实例数据查询(ACT_HI_PROCINST)
借助HistoryService创建查询对象(ACT_HI_XX相关表),指定过滤条件
历史流程实例和流程实例是一一对应的关系
/** 历史数据查询:历史流程实例数据查询 **/
@RequestMapping("getHistoryProcessInstance")
public AjaxResult getHistoryProcessInstance(String processInstanceId) {
HistoricProcessInstance historicProcessInstance = historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
if(historicProcessInstance!=null){
Map<String,Object> map = new HashMap<>();
map.put("流程定义ID",historicProcessInstance.getProcessDefinitionId());
map.put("流程实例ID",historicProcessInstance.getId());
map.put("流程开始节点",historicProcessInstance.getStartActivityId());
map.put("流程结束节点",historicProcessInstance.getEndActivityId());
map.put("流程开始时间",historicProcessInstance.getStartTime());
map.put("流程结束时间",historicProcessInstance.getEndTime());
return AjaxResultUtil.success(map);
}else{
return AjaxResultUtil.success("指定历史流程实例不存在");
}
}
{
"errCode": 0,
"errMsg": "[响应成功]",
"extend": {
"流程开始时间": "2020-06-17T01:26:06.953+0000",
"流程实例ID": "846c363d-b039-11ea-8b34-3cf01168e588",
"流程结束时间": null,
"流程开始节点": "startEvent1",
"流程定义ID": "apply:1:aa9b17ad-afdf-11ea-824b-3cf01168e588",
"流程结束节点": null
}
}
# 执行SQL
SELECT DISTINCT
RES.*,
DEF.KEY_ AS PROC_DEF_KEY_,
DEF.NAME_ AS PROC_DEF_NAME_,
DEF.VERSION_ AS PROC_DEF_VERSION_,
DEF.DEPLOYMENT_ID_ AS DEPLOYMENT_ID_
FROM
ACT_HI_PROCINST RES
LEFT OUTER JOIN ACT_RE_PROCDEF DEF ON RES.PROC_DEF_ID_ = DEF.ID_
WHERE
RES.PROC_INST_ID_ = ?
ORDER BY
RES.ID_ ASC
流程实例和历史实例是一一对应的关系,因此针对判断流程实例是否已经结束可采用如下思路:
获取所有的历史实例,判断对应历史实例对应数据的END_TIME字段是否为空(如果为空,则表示当前流程还没有结束),亦或是判断当前指定的ID在ACT_RU_EXECUTION表中是否存在相应的流程实例,如果存在说明流程实例还没有结束,如果不存在则说明流程实例已经结束
历史数据查询-历史活动数据查询(ACT_HI_ACTINST)
/**
* 历史数据查询:历史活动数据查询
**/
@RequestMapping("getHistoryActivityInstance")
public AjaxResult getHistoryActivityInstance(String processInstanceId) {
List<HistoricActivityInstance> historyActivityInstanceList = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId).list();
List<Map<String, Object>> list = new ArrayList<>();
for (HistoricActivityInstance historyActivityInstance : historyActivityInstanceList) {
Map<String, Object> map = new HashMap<>();
map.put("流程定义ID", historyActivityInstance.getProcessDefinitionId());
map.put("活动ID", historyActivityInstance.getId());
map.put("活动开始时间", historyActivityInstance.getStartTime());
map.put("活动结束时间", historyActivityInstance.getEndTime());
map.put("间隔时间", historyActivityInstance.getDurationInMillis());
list.add(map);
}
return AjaxResultUtil.success("list", list);
}
{
"errCode": 0,
"errMsg": "[响应成功]",
"extend": {
"list": [
{
"间隔时间": 3,
"活动ID": "846cab6f-b039-11ea-8b34-3cf01168e588",
"流程定义ID": "apply:1:aa9b17ad-afdf-11ea-824b-3cf01168e588",
"活动开始时间": "2020-06-17T01:26:06.956+0000",
"活动结束时间": "2020-06-17T01:26:06.959+0000"
},
{
"间隔时间": 0,
"活动ID": "846d20a0-b039-11ea-8b34-3cf01168e588",
"流程定义ID": "apply:1:aa9b17ad-afdf-11ea-824b-3cf01168e588",
"活动开始时间": "2020-06-17T01:26:06.959+0000",
"活动结束时间": "2020-06-17T01:26:06.959+0000"
},
{
"间隔时间": null,
"活动ID": "846d47b1-b039-11ea-8b34-3cf01168e588",
"流程定义ID": "apply:1:aa9b17ad-afdf-11ea-824b-3cf01168e588",
"活动开始时间": "2020-06-17T01:26:06.960+0000",
"活动结束时间": null
}
]
}
}
历史数据查询-历史任务数据查询(ACT_HI_TASKINST)
历史任务表的数据是跟运行任务表的数据一起插入数据库中的,并且在一个运行事务里面执行
ACT_HI_TASKINST表中的END_TIME_有值则说明任务完成,反之任务还没结束
ACT_HI_TASKINST表存储任务节点的数据,其他节点的数据不会存储在这个表中
/**
* 历史数据查询:历史任务数据查询
**/
@RequestMapping("getHistoryTaskInstance")
public void getHistoryTaskInstance() {
List<HistoricTaskInstance> historicTaskInstanceList = historyService
.createHistoricTaskInstanceQuery().list();
System.out.println(historicTaskInstanceList);
}
流程实例启动配置
流程实例启动人配置
ACT_RU_EXECUTION:START_USER_ID_字段指定
ACT_HI_PROCINST:START_USER_ID_字段指定
@RequestMapping("/startFlowByUser")
public void startFlowByUser(String userId) {
// 方式1:通过IdentityService指定流程启动人
identityService.setAuthenticatedUserId(userId);
// 方式2:通过Authentication指定启动人
// Authentication.setAuthenticatedUserId(userId);
// 启动任务实例,并存储临时变量
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("apply");
}
initiator结合流程实例启动人使用
调整流程定义内容,选中开始节点,设定initiator属性
流程定义配置完成需要重新进行部署,随后启动流程
ACT_RU_VARIABLE:TYPE_ \ TEXT_ 字段
如果启动流程的时候没有指定启动人则数据不会填充(即无意义)
在需要设置申请用户才能办理的任务上设置activiti:assginee=${shareniuapplyUserId}
属性
public void startProcessInstanceByKey() {
// 设置当前的用户ID,需要和activiti:initiator配合使用
identityService.setAuthenticatedUserId("xxx");
runtimeService.startProcessInstanceByKey("apply");
}
在启动流程的时候会判断有没有activiti:initiator属性,如果有把属性activiti:initiator的值作为一个变量添加到流程实例中,例如此处变量为shareniuInitiator,在ACT_RU_VARIABLE相应填充属性:
NAME_=shareniuInitiator、TEXT_=XXX(指定的流程启动人id)
如果使用${key}作为activiti:initiator的值,引擎会在创建任务的使用用变量key进行替换
流程相关操作-dataObject使用
在流程设计中设定dataObject属性(无需选中节点),点击数据对象配置
dataObject定义的元素可以直接转化为流程变量使用,在process中配置的 dataObject元素值可以作为全局的变量进行使用,支持的类型如下:
xsd:string、xsd:boolean、xsd:datetime、xsd:double
xsd:int、xsd:long、xsd:datetime
@RequestMapping("/getDataObject")
public void getDataObject(String executionId,String dataObject) {
// 根据实例id和变量值获取dataObject
DataObject object = runtimeService.getDataObject(executionId,dataObject);
// 获取指定流程实例所有dataObject:
Map<String, DataObject> dataObjectMap = runtimeService.getDataObjects(executionId);
if(object!=null){
System.out.println(object.getDataObjectDefinitionKey());
System.out.println(object.getDescription());
System.out.println(object.getExecutionId());
System.out.println(object.getName());
System.out.println(object.getValue());
System.out.println(object.getType());
}
}
SELECT
*
FROM
ACT_RU_VARIABLE
WHERE
EXECUTION_ID_ = ?
AND NAME_ = ?
AND TASK_ID_ IS NULL
流程实例相关操作
流程实例相关操作-删除流程实例
@RequestMapping("/delProcessInstance")
public void delProcessInstance(String processInstanceId) {
runtimeService.deleteProcessInstance(processInstanceId,"删除流程实例");
}
测试的时候分别传入流程实例ID和执行实例ID,可以看到关联的流程数据都被清理(默认删除操作会保留历史记录数据)
流程实例相关操作-级联删除流程操作
通过引擎配置类级联删除操作
/** 级联删除流程实例 **/
@RequestMapping("/delProcessInstanceCascade")
public void delProcessInstanceCascade(String processInstanceId) {
// 级联删除流程实例没有提供封装好的API调用,可通过ProcressEngine
ProcessEngineConfigurationImpl config = (ProcessEngineConfigurationImpl)
processEngine.getProcessEngineConfiguration();
config.getExecutionEntityManager()
.deleteProcessInstance(processInstanceId,"级联删除流程实例",true);
}
直接执行删除代码会报如下错误,需要自定义一个命令类然后将代码封装成一个方法进行调用
a.自定义CustomCmd实现Command<方法返回类型>,封装执行方法和参数
public class CustomCmd implements Command<Object> {
String processInstanceId = null;
String deleteReason = "级联删除操作";
public CustomCmd(String processInstanceId, String deleteReason) {
this.processInstanceId = processInstanceId;
this.deleteReason = deleteReason;
}
@Override
public Object execute(CommandContext commandContext) {
AbstractEngineConfiguration currentEngineConfiguration =
commandContext.getCurrentEngineConfiguration();
if(currentEngineConfiguration!=null){
ProcessEngineConfigurationImpl config =
(ProcessEngineConfigurationImpl) currentEngineConfiguration;
config.getExecutionEntityManager()
.deleteProcessInstance(processInstanceId,deleteReason,true);
}
return null;
}
}
b.在接口中借助ManagementService调用方法
managementService.executeCommand(new CustomCmd(processInstanceId,deleteReason));
流程实例相关操作-流程实例获取运行的活动节点
/** 流程实例获取运行的活动节点 **/
@RequestMapping("/getActivityInstance")
public void getActivityInstance(String processInstanceId) {
List<ActivityInstance> activityInstanceList = runtimeService
.createActivityInstanceQuery()
.processInstanceId(processInstanceId).list();
System.out.println(activityInstanceList);
}
# 必须指定为流程实例ID PROC_INST_ID_
SELECT
RES.*
FROM
ACT_RU_ACTINST RES
WHERE
RES.PROC_INST_ID_ = ?
ORDER BY
RES.ID_ ASC
流程实例相关操作-流程启动
startProcessInstanceByKey:根据流程定义key启动流程(以最新版本的流程定义为参考),部分方法还提供了其他参数
参数说明:
processDefinitionKey:流程定义key值
businessKey:业务标识
variables:流程变量
启动流程和业务关联区别:
对于自定义表单来说启动的时候会传入businessKey作为业务和流程的关联属性
对于动态表单来说不需要使用businessKey关联,因为所有的数据都保存在引擎的表中
对于外部表单来说businessKey是可选的,但是一般不会为空,和自定义表单类似
startProcessInstanceByKeyAndTenantId:
需要部署相应的流程资源并指定tenantId,流程启动方能指定tenantId进行启动
tenantId:在上述方法的基础上引入‘租户标识’概念,类似区分不同子系统的流程概念
startProcessInstanceById
startProcessInstanceWithForm
.......
以此类推,结合方法理解
流程实例相关操作-自定义流程实例创建类(待定)
流程实例的激活和挂起
某些场景下可能由于流程变更需要将当前运行的流程暂停而不是直接删除,流程挂起后将不会继续执行
/**
* 全部流程实例挂起与激活(针对的是在挂起/激活流程定义的时候设置级联操作)
*/
// 1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.得到RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3.查询流程定义的对象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("holiday").singleResult();
// 4.得到当前流程定义的实例是否都为暂停状态
boolean suspended = processDefinition.isSuspended();
String processDefinitionId = processDefinition.getId();
// 5.判断
if(suspended){
//说明是暂停,就可以激活操作
repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
System.out.println("流程定义:"+processDefinitionId+"激活");
}else{
repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
System.out.println("流程定义:"+processDefinitionId+"挂起");
}
/**
* 单个流程实例挂起与激活
*/
// 1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.得到RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 3.查询流程实例对象
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId("2501").singleResult();
// 4.得到当前流程定义的实例是否都为暂停状态
boolean suspended = processInstance.isSuspended();
String processInstanceId = processInstance.getId();
// 5.判断
if(suspended){
//说明是暂停,就可以激活操作
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程:"+processInstanceId+"激活");
}else{
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程定义:"+processInstanceId+"挂起");
}