博客 / 詳情

返回

Flowable 設置任務處理人的四種方式

@[toc]
上篇文章鬆哥和大家分享了 Flowable 中的 ReceiveTask,這只是流程中任務的一種,今天我們就一起來看另外一個更為常見的 Task--UserTask。

UserTask 看名字就知道,需要人工干預,而人工處理的方式有很多種,我們可以設置節點是由哪個用户處理,也可以設置是由哪個用户組來處理(相當於是由哪個角色來處理),今天這篇文章我主要和大家分享設置用户的三種方式,至於如何設置用户組,這個咱們下篇文章再聊。

現在,假設我有如下一個簡單的流程圖:

那麼我該如何設置這個用户節點的處理人呢?

1. 指定具體用户

第一種方式,是我們在繪製流程圖的時候,可以選中這個節點,然後直接設置流程的處理人,像下面這樣:

然後在打開的窗口中選擇固定值,設置具體分配的用户是 javaboy,如下圖:

好了,現在這個節點就固定的由一個名為 javaboy 的用户去處理了。

對應的 XML 文件如下:

<process id="demo01" name="demo01" isExecutable="true">
  <documentation>demo01</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:assignee="javaboy" flowable:formFieldValidation="true">
    <extensionElements>
      <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
  <endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
  <sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>

在上面這段 XML 中,小夥伴們看到 UserTask 節點中有一個 flowable:assignee="javaboy",這句話就是設置這個 UserTask 的處理人。

接下來,我們部署並啓動這個流程(具體的部署啓動方式可以參考本系列之前的文章),啓動之後,我們可以在數據庫的 ACT_RU_TASK 表中看到,這個 UserTask 的處理人是 javaboy,如下圖:

現在我們可以通過 Java 代碼去查詢 javaboy 需要處理的 UserTask 了,如下:

@Autowired
TaskService taskService;
@Test
void test11() {
    List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
    for (Task task : list) {
        logger.info("id:{},name:{}",task.getId(),task.getName());
    }
}

這個查詢,本質上其實就是去 ACT_RU_TASK 表中查詢的,我們來看看執行的 SQL:

查詢到這個任務之後,javaboy 有兩種選擇:

  1. 將這個任務指定給另外一個人,例如 zhangsan。
  2. 自己處理。

1.1 重新指定任務處理人

假設 javaboy 查詢到自己的任務之後,想把這個任務交給 zhangsan 去處理,方式如下:

@Autowired
TaskService taskService;
@Test
void test11() {
    List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
    for (Task task : list) {
        taskService.setAssignee(task.getId(),"zhangsan");
    }
}

這行代碼執行完成後,我們看數據庫中的 ACT_RU_TASK 表,還是剛才那條記錄,但是處理人變了,變成了 zhangsan:

小夥伴們看到,版本號從 1 變為 2 了,説明這條記錄被更新過了,處理人則從 javaboy 變為了 zhangsan。

最後我們再來看下這個操作所執行的 SQL,來驗證一下我們前面的結論:

小夥伴們注意看這裏執行的 SQL,以及對應的參數,説明我們上面的分析是沒有問題的。

1.2 自己處理

如果 javaboy 想自己處理這個任務也是可以的,方式如下:

@Autowired
TaskService taskService;
@Test
void test11() {
    List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
    for (Task task : list) {
        taskService.complete(task.getId());
    }
}

處理完成後,ACT_RU_TASK 表中的記錄也會被自動刪除掉(執行過的 UserTask 會被自動刪除)。

這種方式是指定了具體的用户,很顯然這種硬編碼的方式使用起來很不方便,我們需要的是能夠動態指定任務處理人的方式。

2. 通過變量設置

如果想動態指定 UserTask 的處理人,則可以通過變量來實現,具體方式如下:

在繪製流程圖的時候,還是指定流程的具體處理人,但是在指定的時候,使用變量代替,如下圖:

這裏的 #{manager} 表示這個 UserTask 由一個名為 manager 的變量來指定,此時的 XML 文件則是下面這樣:

<process id="demo01" name="demo01" isExecutable="true">
  <documentation>demo01</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:assignee="#{manager}" flowable:formFieldValidation="true">
    <extensionElements>
      <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
  <endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
  <sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>

小夥伴們看到,UserTask 節點中的 flowable:assignee="#{manager}" 就表示這個 UserTask 的處理人由 manager 變量指定。

對於這樣的流程,我們在上一個節點處就需要指定下一個節點的處理人,對於當前案例來説,當然是要在流程啓動的時候,指定這個 UserTask 的處理人,方式如下:

@Test
void test01() {
    Map<String, Object> variables = new HashMap<>();
    variables.put("manager", "javaboy");
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01",variables);
    logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}

當流程啓動成功之後,大家去查看 ACT_RU_TASK 表,就可以看到,有一個待處理的 UserTask,處理人是 javaboy,如下圖:

能看到這條記錄,就説明這個 UserTask 的處理人我們已經設置成功了。

接下來具體的處理邏輯,則參考 1.1 和 1.2 小節。

3. 通過監聽器設置

當然,我們也可以通過監聽器來設置任務的處理人。具體方式如下:

首先我們在繪製流程圖的時候,不需要給 UserTask 分配用户,如下圖:

然後我們為這個 UserTask 設置一個任務監聽器,步驟如下:

首先點擊 + 號,然後選擇 CREATE 事件,最後再給出事件對應的實體類,如下:

當然這個實體類是我們項目中真實存在的一個類,如下:

public class MyTaskListener implements TaskListener {
    @Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.setAssignee("javaboy");
    }
}

當這個 UserTask 創建的時候,就會觸發這個監聽器,為該 UserTask 設置處理人。

我們來看看這個流程圖對應的 XML 文件是什麼樣子的:

<process id="demo01" name="demo01" isExecutable="true">
  <documentation>demo01</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:formFieldValidation="true">
    <extensionElements>
      <flowable:taskListener event="create" class="org.javaboy.flowableidm.MyTaskListener"></flowable:taskListener>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
  <endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
  <sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>

小夥伴們看到,event="create" class="org.javaboy.flowableidm.MyTaskListener" 就是我們設置的內容了。

現在我們部署並啓動這個流程,當我們流程啓動後,就可以在 ACT_RU_TASK 表中看到一條 javaboy 待處理的任務了。

4. 其他情況

最後再來説説一種特殊情況,就是這個 UserTask 由任務的發起人處理,任務是誰發起的,誰來處理人這個 UserTask。

這個首先需要在流程啓動事件上設置任務的發起人變量名,如下,流程的啓動節點,然後設置任務的發起人:

接下來,在給 UserTask 設置處理人的時候,設置處理人和任務的發起人的變量是同一個,如下圖:

好啦,這就可以了。來看看對應的 XML 文件:

<process id="demo01" name="demo01" isExecutable="true">
  <documentation>demo01</documentation>
  <startEvent id="startEvent1" flowable:initiator="INITATOR" flowable:formFieldValidation="true"></startEvent>
  <userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:assignee="#{INITATOR}" flowable:formFieldValidation="true">
    <extensionElements>
      <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
  <endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
  <sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>

startEvent 中有一個 flowable:initiator="INITATOR" 表示設置流程發起人的變量為 INITATOR。後續在 UserTask 中使用該變量即可。

將這個流程部署成功之後,按照如下方式啓動流程:

@Test
void test01() {
    Authentication.setAuthenticatedUserId("javaboy");
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01");
    logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}

Authentication.setAuthenticatedUserId("javaboy"); 表示設置流程的發起人為 javaboy。

好啦,今天的文章就和小夥伴們介紹瞭如何給 UserTask 設置處理人,後面鬆哥再和大家分享如何給 UserTask 設置候選人和候選組。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.