天天看點

Flowable 服務任務執行的三種方式

作者:江南一點雨

前面和小夥伴們分别聊了 Flowable 中的 ReceiveTask 和 UserTask,今天我們來看看另外一個比較常見的 Task --> ServiceTask。

1. ServiceTask

ServiceTask 從名字上看就是服務任務,它的圖示一般是像下面這樣:

Flowable 服務任務執行的三種方式

ServiceTask 一般由系統自動完成,當流程走到這一步的時候,不會自動停下來,而是會去執行我們提前在 ServiceTask 中配置好的方法。

2. 實踐

我們通過一個簡單的例子來看一下 ServiceTask 要怎麼玩。

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

Flowable 服務任務執行的三種方式

中間這個就是一個 ServiceTask。

當流程執行到 ServiceTask 的時候,具體要做哪些事情?有三種不同的方式來設定這裡的任務,我們分别來看。

2.1 監聽類

首先我們可以設定一個監聽類,這個監聽類有一個硬性規定就是需要實作 JavaDelegate 接口,像下面這樣:

public class MyServiceTask implements JavaDelegate {
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("========MyServiceTask==========");
    }
}
           

在這個監聽類中我們可以完成一些操作,通過這個 execution 也可以擷取到在流程節點之間傳輸的變量。

這個類定義好之後,接下來我們在流程定義的時候,配置這個類的全路徑即可,如下圖:

Flowable 服務任務執行的三種方式

這個配置對應的 XML 内容如下:

<process id="demo01" name="測試流程" isExecutable="true">
    <documentation>測試流程</documentation>
    <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
    <sequenceFlow id="sid-33A78082-C2FD-48BE-8B87-99FB20F0B331" sourceRef="startEvent1" targetRef="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8"></sequenceFlow>
    <serviceTask id="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8" flowable:class="org.javaboy.flowableidm.MyServiceTask"></serviceTask>
    <endEvent id="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></endEvent>
    <sequenceFlow id="sid-0698809E-0A6C-4B92-A167-AE96A8CB75F2" sourceRef="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8" targetRef="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></sequenceFlow>
  </process>
           

小夥伴們看到,在 ServiceTask 标簽中的 flowable:class="org.javaboy.flowableidm.MyServiceTask" 就表示 ServiceTask 執行的服務類。

配置完成後,我們可以部署并啟動這個流程,由于這個流程除了開始和結束,就這一個節點,是以流程一啟動就自動結束了。不過在這個過程中,我們可以看到控制台列印出來了日志,說明這個 ServiceTask 确實是執行了。

2.2 委托表達式

我們也可以配置委托表達式。

委托表達式是指将一個實作了 JavaDelegate 接口的類注冊到 Spring 容器中,然後我們在流程節點的配置中不用寫完整的類名了,隻需要寫 Spring 容器中的 Bean 名稱即可。

像下面這樣:

@Component
public class MyServiceTask implements JavaDelegate {
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("========MyServiceTask==========");
    }
}
           

這個類注冊到 Spring 容器中的預設名稱是類名首字母小寫,即 myServiceTask。

現在我們在流程圖中,可以按照如下方式進行配置:

Flowable 服務任務執行的三種方式

對應的 XML 檔案如下:

<process id="demo01" name="測試流程" isExecutable="true">
  <documentation>測試流程</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <sequenceFlow id="sid-33A78082-C2FD-48BE-8B87-99FB20F0B331" sourceRef="startEvent1" targetRef="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8"></sequenceFlow>
  <serviceTask id="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8" flowable:delegateExpression="${myServiceTask}"></serviceTask>
  <endEvent id="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></endEvent>
  <sequenceFlow id="sid-0698809E-0A6C-4B92-A167-AE96A8CB75F2" sourceRef="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8" targetRef="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></sequenceFlow>
</process>
           

可以看到,flowable:delegateExpression="${myServiceTask}" 就表示執行的一個表達式。

測試過程同 2.1 小節,我就不再贅述了。

最後總結一下,委托表達式,一定是 JavaDelegate 接口的實作類,将這個實作類注冊到 Spring 容器中,然後在使用的時候,根據 Bean 的名稱從 Spring 容器中查找即可。

2.3 表達式

我們也可以使用表達式。

表達式就是一個普通類的普通方法,将這個普通類注冊到 Spring 容器中,然後表達式中還可以執行這個類中的方法,類似下面這樣,任意定義一個 Java 類:

@Component
public class MyServiceTask2 {
    public void hello() {
        System.out.println("========MyServiceTask2==========");
    }
}
           

然後在流程圖中按照如下方式進行配置:

Flowable 服務任務執行的三種方式

表達式中有一部分内容隐藏了,完整的表達式是 ${myServiceTask2.hello()}。

對應的 XML 檔案如下:

<process id="demo01" name="測試流程" isExecutable="true">
  <documentation>測試流程</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <sequenceFlow id="sid-33A78082-C2FD-48BE-8B87-99FB20F0B331" sourceRef="startEvent1" targetRef="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8"></sequenceFlow>
  <serviceTask id="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8" flowable:expression="${myServiceTask2.hello()}"></serviceTask>
  <endEvent id="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></endEvent>
  <sequenceFlow id="sid-0698809E-0A6C-4B92-A167-AE96A8CB75F2" sourceRef="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8" targetRef="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></sequenceFlow>
</process>
           

可以看到,表達式的内容是 flowable:expression="${myServiceTask2.hello()}。

測試方式同 2.1 小節,這裡我不再贅述。

3. 類中字段

可能有小夥伴注意到,我們在繪制流程圖的時候,還可以為類設定一個字段。

例如我想給 ServiceTask 的執行類設定一個 username 字段,如下:

Flowable 服務任務執行的三種方式
Flowable 服務任務執行的三種方式

設定完成後,對應的 XML 如下:

<process id="demo01" name="測試流程" isExecutable="true">
  <documentation>測試流程</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <sequenceFlow id="sid-33A78082-C2FD-48BE-8B87-99FB20F0B331" sourceRef="startEvent1" targetRef="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8"></sequenceFlow>
  <serviceTask id="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8" flowable:delegateExpression="${myServiceTask}">
    <extensionElements>
      <flowable:field name="username">
        <flowable:string><![CDATA[javaboy]]></flowable:string>
      </flowable:field>
    </extensionElements>
  </serviceTask>
  <endEvent id="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></endEvent>
  <sequenceFlow id="sid-0698809E-0A6C-4B92-A167-AE96A8CB75F2" sourceRef="sid-6FA66E2A-F8E6-4F10-8FA2-6450408E17D8" targetRef="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></sequenceFlow>
</process>
           

可以看到,這裡通過 extensionElements 節點描述了額外的資訊。

接下來,我們就可以在 Java 類中通路到這個變量了,如下:

@Component
public class MyServiceTask implements JavaDelegate {
    Expression username;
    @Override
    public void execute(DelegateExecution execution) {
        System.out.println("username.getExpressionText() = " + username.getExpressionText());
        System.out.println("username.getValue(execution) = " + username.getValue(execution));
        System.out.println("========MyServiceTask==========");
    }
}
           

想要擷取到 username 對應的值,上面這段代碼中,松哥給大家示範了兩種方式。

不過需要注意,這種設定類中字段的方式,适用于 2.1 和 2.2 小節的情況,不适用于 2.3 小節的情況。

好啦,今天和小夥伴們介紹了 ServiceTask 執行的三種情況,這些内容我将來也會錄制成視訊放在 TienChin 項目中,感興趣的小夥伴可以試試啦~

繼續閱讀