前面的文章我們一起玩了 Flowable 中的 ServiceTask,今天我們再來看看 Flowable 中的腳本任務。
1. 腳本任務
個人感覺腳本任務和我們前面説的 ServiceTask 很像,都是流程走到這個節點的時候自動做一些事情,不同的是,在 ServiceTask 中,流程在這個節點中所做的事情是用 Java 代碼寫的,在腳本任務中,流程在這個節點中所做的事情則是用其他一些腳本語言如 JavaScript、Groovy、Juel 等寫的。
腳本任務的圖標如下圖所示:
2. 實踐
寫一個簡單的例子我們來一起看下。
2.1 JavaScript 腳本
我們先來看用 JavaScript 寫這個腳本。
假設我有如下流程圖:
中間這個節點就是一個腳本任務。
選中該節點,我們先配置腳本語言是 JavaScript,如下圖:
這裏也可以使用簡寫的 js。
然後再點擊右邊的腳本,配置腳本,如下圖:
上面這裏我寫了兩行 JavaScript 腳本:
- 第一行表示流程執行到這裏的時候,需要做一個簡單的加法運算,a 和 b 兩個變量則需要流程傳入進來。
- 第二行表示往流程中存儲一個名為 sum 的變量,變量值就是前面計算的結果,其中 execution 是一個內置變量。這個就類似於我們啓動流程時候傳入的變量一樣。
在 ES6 中我們常用的 let 關鍵字這裏並不支持,這個地方小夥伴們要注意。
配置完成之後,我們下載這個腳本來看下對應的 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-8D88DFF6-0F37-42FA-9F94-29FE30536094"></sequenceFlow>
<endEvent id="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></endEvent>
<sequenceFlow id="sid-0698809E-0A6C-4B92-A167-AE96A8CB75F2" sourceRef="sid-8D88DFF6-0F37-42FA-9F94-29FE30536094" targetRef="sid-A5F11956-15EA-4574-98D0-29A4E3DB5495"></sequenceFlow>
<scriptTask id="sid-8D88DFF6-0F37-42FA-9F94-29FE30536094" scriptFormat="JavaScript" flowable:autoStoreVariables="false">
<script><![CDATA[var sum=a+b;
execution.setVariable("sum",sum);]]></script>
</scriptTask>
</process>
小夥伴們看到,scriptTask 中內嵌了一個 script 節點,裏邊就是我們自己寫的腳本內容。
好啦,接下來小夥伴們就可以部署並啓動這個流程了,啓動代碼如下:
@Test
void test01() {
Map<String, Object> variables = new HashMap<>();
variables.put("a", 99);
variables.put("b", 98);
ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01", variables);
logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}
大家注意啓動的時候傳遞 a 和 b 兩個變量。這個流程啓動之後,直接就執行結束了,因為流程到達 scriptTask 並不會停止。
不過我們可以在 ACT_HI_VARINST 表中查看流程運行信息:
可以看到,相關的變量和變量值都保存着。
2.2 Groovy 腳本
看懂了 JavaScript 腳本,Groovy 就好懂了。不過 JavaScript 腳本估計大部分搞 Java 的小夥伴都懂,但是 Groovy 可能會比較陌生,我簡單介紹下:
Groovy 是 Apache 旗下的一門基於 JVM 平台的動態/敏捷編程語言,在語言的設計上它吸納了 Python、Ruby 和 Smalltalk 語言的優秀特性,語法非常簡練和優美,開發效率也非常高(編程語言的開發效率和性能是相互矛盾的,越高級的編程語言性能越差,因為意味着更多底層的封裝,不過開發效率會更高,需結合使用場景做取捨)。並且,Groovy 可以與 Java 語言無縫對接,在寫 Groovy 的時候如果忘記了語法可以直接按 Java 的語法繼續寫,也可以在 Java 中調用 Groovy 腳本,都可以很好的工作,這有效的降低了 Java 開發者學習 Groovy 的成本。Groovy 也並不會替代 Java,而是相輔相成、互補的關係,具體使用哪門語言這取決於要解決的問題和使用的場景。
如果我們想要在流程中使用 Groovy 腳本,那麼首先設置腳本格式為 Groovy:
然後設置腳本內容如下:
這段腳本表示流程執行到這個節點的時候輸出一個 "hello groovy"(如果你熟悉 Groovy 腳本的話,就知道這段腳本其實也可以直接寫 Java 代碼,也能執行)。
另外説一句,使用 Groovy 腳本,千萬別忘了加 Groovy 依賴,如下:
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>3.0.13</version>
</dependency>
2.3 Juel 腳本
Juel是Java Unified Expression Language的簡稱,它具有高性能,插件式緩存,小體積,支持方法調用和多參數調用,可插拔等多種特性,它是 JSP2.1 標準 (JSR-245) 中定義的一部分。儘管 EL 表達式是伴隨着 JSP 而生,但現在已經可以在非 JS P應用中使用,相關的 API 放在 javax.el 包裏面。
其實像我們之前寫的 ${xxx} 這種表達式,其實就是 Juel 了。
來一個簡單的例子看下。假設我們想在流程中使用 juel,首先設置腳本格式為 juel:
然後就可以設置具體的腳本內容了,如下:
這段腳本就表示調用一個名為 myServiceTask2 的 Bean 中的 hello 方法。
好啦,Flowable 中支持的三種常見腳本任務就和小夥伴們説完啦,感興趣的小夥伴歡迎留言討論~