今天來和小夥伴們聊一聊流程的挂起和激活。
這塊實際上涉及到兩部分内容:
- 流程定義的挂起和激活。
- 流程執行個體的挂起和激活。
一個定義好的流程,如果挂起了,那麼就無法據此建立新的流程。
一個流程執行個體如果挂起了,那麼就無法執行流程中的任務。
小夥伴們注意區分這兩個概念(看了前面幾篇文章的小夥伴,應該對于這兩個概念不在話下了)。
我們分别來看。
1. 流程定義的挂起與激活
1.1 查詢是否挂起
對于一個定義好的流程,我們可以通過如下方法來檢視這個流程是否挂起:
@Test
void test05() {
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition processDefinition : list) {
String id = processDefinition.getId();
boolean suspended = repositoryService.isProcessDefinitionSuspended(id);
if (suspended) {
logger.info("流程定義 {} 已挂起",processDefinition.getName());
}else{
logger.info("流程定義 {} 未挂起",processDefinition.getName());
}
}
}
這個查詢 SQL 涉及到的表是
ACT_RE_PROCDEF
,該表中有一個名為
SUSPENSION_STATE_
的字段,該字段表示這個流程是否挂起。如下圖:

1 表示流程沒有挂起。
1.2 挂起
執行如下方法,可以挂起一個流程定義,如下:
@Test
void test06() {
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition pd : list) {
repositoryService.suspendProcessDefinitionById(pd.getId());
}
}
挂起的原理其實很簡單,就是去
ACT_RE_PROCDEF
表中,将
SUSPENSION_STATE_
字段的值設定為 2,就表示這個流程定義挂起了,我們可以看下流程定義挂起時執行的 SQL:
從這個執行的 SQL 中我們可以清晰的看到,操作的表是
ACT_RE_PROCDEF
,修改的字段就是
SUSPENSION_STATE_
,将該字段的值修改為 2(樂觀鎖相關的 REV_ 字段不考慮)。
對于一個已經挂起的流程定義,如果我們想據此啟動一個流程,如下:
@Test
void test01() {
identityService.setAuthenticatedUserId("wangwu");
ProcessInstance pi = runtimeService.startProcessInstanceByKey("leave");
logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}
此時就會抛出如下異常:
這個異常說的很明白了,流程定義被挂起了,無法開啟一個新的流程執行個體。
1.3 激活
已經挂起的流程定義,還可以激活,方式如下:
@Test
void test07() {
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition pd : list) {
repositoryService.activateProcessDefinitionById(pd.getId());
}
}
激活的原理也很簡單,,就是去
ACT_RE_PROCDEF
表中,将
SUSPENSION_STATE_
字段的值設定為 1,就表示這個流程定義激活了,我們可以看下流程定義激活時執行的 SQL:
大家注意看操作的表、字段以及對應的參數。
2. 流程執行個體的挂起與激活
第一小節搞懂了,第二小節就容易多了。
2.1 挂起
挂起一個流程執行個體的方式如下:
@Test
void test08() {
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition pd : list) {
repositoryService.suspendProcessDefinitionById(pd.getId(), true, null);
}
}
小夥伴們看到,其實還是剛才上面的那個方法,隻不過這裡多了兩個參數:
- 第二個參數 true 表示是否要挂起這個流程定義對應的所有的流程執行個體,true 表示挂起。
- 第三個參數 null 表示流程挂起的具體時間,如果該參數為 null,則流程會被立馬挂起,如果該參數是一個具體的日期,則到期之後流程才會被挂起,但是這個需要 job executor 的支援,關于 job executor,松哥後面再單獨發文章和小夥伴們介紹。
執行完成之後,這個流程執行個體就被挂起了。流程執行個體被挂起,涉及到兩個地方:
- 流程的執行執行個體被挂起。
- 流程的 Task 被挂起。
也就是首先
ACT_RU_EXECUTION
表中對應的流程執行個體會被挂起:
最後一列兩個 2 就說明這兩個執行執行個體被挂起了。
同時,流程執行個體的 Task 其實也被挂起了,即
ACT_RU_TASK
表中與之對應的任務被挂起了,如下:
可以看到,
SUSPENSION_STATE_
字段的值為 2,表示這 Task 也被挂起了。
我們來看看挂起流程執行個體時執行的 SQL:
注意,流程定義本身也被挂起了。
對于處于挂起狀态的流程執行個體,是無法繼續執行的,如果強行執行,如下:
@Test
void test03() {
List<Task> list = taskService.createTaskQuery().taskAssignee("wangwu").list();
for (Task task : list) {
taskService.complete(task.getId());
}
}
則會抛出異常,如下:
這個異常也說的很清楚了,無法完成一個處于挂起狀态的 Task。
2.2 激活
處于挂起狀态的流程執行個體,可以通過如下方式激活:
@Test
void test09() {
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition pd : list) {
repositoryService.activateProcessDefinitionById(pd.getId(), true, null);
}
}
一共三個參數:
- 流程定義的 ID。
- 是否激活流程定義對應的流程執行個體。
- 激活流程執行個體的時間,null 表示立馬激活,如果是一個具體的時間,則到期激活,不過和之前的一樣,這裡也需要 job executor 的支援。
激活就是反向操作,将
ACT_RU_EXECUTION
、
ACT_RU_TASK
以及
ACT_RE_PROCDEF
表中的
SUSPENSION_STATE_
字段值再改為 1。對應的 SQL 如下: