欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flowable流程引擎API與服務(wù)

 更新時(shí)間:2023年10月01日 09:56:02   作者:吳聲子夜歌  
這篇文章主要介紹了Flowable流程引擎API與服務(wù),引擎API是與Flowable交互的最常用手段,總?cè)肟邳c(diǎn)是ProcessEngine,使用ProcessEngine,可以獲得各種提供工作流或BPM方法的服務(wù),下面我們來詳細(xì)了解

1、流程引擎API與服務(wù)

引擎API是與Flowable交互的最常用手段???cè)肟邳c(diǎn)是ProcessEngine。使用ProcessEngine,可以獲得各種提供工作流/BPM方法的服務(wù)。ProcessEngine與服務(wù)對(duì)象都是線程安全的,因此可以在服務(wù)器中保存并共用同一個(gè)引用。

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();

在ProcessEngines.getDefaultProcessEngine()第一次被調(diào)用時(shí),將初始化并構(gòu)建流程引擎,之后的重復(fù)調(diào)用都會(huì)返回同一個(gè)流程引擎??梢酝ㄟ^ProcessEngines.init()創(chuàng)建流程引擎,并由ProcessEngines.destroy()關(guān)閉流程引擎。

ProcessEngines會(huì)掃描flowable.cfg.xml與flowable-context.xml文件。對(duì)于flowable.cfg.xml文件,流程引擎會(huì)以標(biāo)準(zhǔn)Flowable方式構(gòu)建引擎:ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine()。對(duì)于flowable-context.xml文件,流程引擎會(huì)以Spring的方式構(gòu)建:首先構(gòu)建Spring應(yīng)用上下文,然后從該上下文中獲取流程引擎。

所有的服務(wù)都是無狀態(tài)的。這意味著你可以很容易的在集群環(huán)境的多個(gè)節(jié)點(diǎn)上運(yùn)行Flowable,使用同一個(gè)數(shù)據(jù)庫,而不用擔(dān)心上一次調(diào)用實(shí)際在哪臺(tái)機(jī)器上執(zhí)行。不論在哪個(gè)節(jié)點(diǎn)執(zhí)行,對(duì)任何服務(wù)的任何調(diào)用都是冪等(idempotent)的。

1.1、RepositoryService

RepositoryService很可能是使用Flowable引擎要用的第一個(gè)服務(wù)。這個(gè)服務(wù)提供了管理與控制部署(deployments)與流程定義(process definitions)的操作。在這里簡單說明一下,流程定義是BPMN 2.0流程對(duì)應(yīng)的Java對(duì)象,體現(xiàn)流程中每一步的結(jié)構(gòu)與行為。部署是Flowable引擎中的包裝單元,一個(gè)部署中可以包含多個(gè)BPMN 2.0 XML文件及其他資源。開發(fā)者可以決定在一個(gè)部署中包含的內(nèi)容,可以是單個(gè)流程的BPMN 2.0 XML文件,也可以包含多個(gè)流程及其相關(guān)資源(如’hr-processes’部署可以包含所有與人力資源流程相關(guān)的的東西)。RepositoryService可用于部署這樣的包。部署意味著將它上傳至引擎,引擎將在儲(chǔ)存至數(shù)據(jù)庫之前檢查與分析所有的流程。在部署操作后,可以在系統(tǒng)中使用這個(gè)部署包,部署包中的所有流程都可以啟動(dòng)。

此外,這個(gè)服務(wù)還可以:

  • 查詢引擎現(xiàn)有的部署與流程定義。
  • 暫?;蚣せ畈渴鹬械哪承┝鞒蹋蛘麄€(gè)部署。暫停意味著不能再對(duì)它進(jìn)行操作,激活剛好相反,重新使它可以操作。
  • 獲取各種資源,比如部署中保存的文件,或者引擎自動(dòng)生成的流程圖。
  • 獲取POJO版本的流程定義。它可以用Java而不是XML的方式查看流程。

1.2、RuntimeService

RuntimeService用于啟動(dòng)流程定義的新流程實(shí)例。前面介紹過,流程定義中定義了流程中不同步驟的結(jié)構(gòu)與行為。流程實(shí)例則是流程定義的實(shí)際執(zhí)行過程。同一時(shí)刻,一個(gè)流程定義通常有多個(gè)運(yùn)行中的實(shí)例。RuntimeService也用于讀取與存儲(chǔ)流程變量。流程變量是流程實(shí)例中的數(shù)據(jù),可以在流程的許多地方使用(例如排他網(wǎng)關(guān)經(jīng)常使用流程變量判斷流程下一步要走的路徑)。RuntimeService還可以用于查詢流程實(shí)例與執(zhí)行(Execution)。執(zhí)行也就是BPMN 2.0中 ‘token’ 的概念。通常執(zhí)行是指向流程實(shí)例當(dāng)前位置的指針。最后,還可以在流程實(shí)例等待外部觸發(fā)時(shí)使用RuntimeService,使流程可以繼續(xù)運(yùn)行。流程有許多等待狀態(tài)(wait states),RuntimeService服務(wù)提供了許多操作用于“通知”流程實(shí)例:已經(jīng)接收到外部觸發(fā),流程實(shí)例可以繼續(xù)運(yùn)行。

1.3、TaskService

所有任務(wù)相關(guān)的東西都組織在TaskService中,例如:

  • 查詢分派給用戶或組的任務(wù)
  • 創(chuàng)建獨(dú)立運(yùn)行(standalone)任務(wù)。這是一種沒有關(guān)聯(lián)到流程實(shí)例的任務(wù)。
  • 決定任務(wù)的執(zhí)行用戶(assignee),或者將用戶通過某種方式與任務(wù)關(guān)聯(lián)。
  • 認(rèn)領(lǐng)(claim)與完成(complete)任務(wù)。認(rèn)領(lǐng)是指某人決定成為任務(wù)的執(zhí)行用戶,也即他將會(huì)完成這個(gè)任務(wù)。完成任務(wù)是指“做這個(gè)任務(wù)要求的工作”,通常是填寫某個(gè)表單。

1.4、IdentityService

它用于管理(創(chuàng)建,更新,刪除,查詢……)組與用戶。請(qǐng)注意,F(xiàn)lowable實(shí)際上在運(yùn)行時(shí)并不做任何用戶檢查。例如任務(wù)可以分派給任何用戶,而引擎并不會(huì)驗(yàn)證系統(tǒng)中是否存在該用戶。這是因?yàn)镕lowable有時(shí)要與LDAP、Active Directory等服務(wù)結(jié)合使用。

1.5、FormService

FormService是可選服務(wù)。也就是說Flowable沒有它也能很好地運(yùn)行,而不必犧牲任何功能。這個(gè)服務(wù)引入了開始表單(start form)與任務(wù)表單(task form)的概念。 開始表單是在流程實(shí)例啟動(dòng)前顯示的表單,而任務(wù)表單是用戶完成任務(wù)時(shí)顯示的表單。Flowable可以在BPMN 2.0流程定義中定義這些表單。表單服務(wù)通過簡單的方式暴露這些數(shù)據(jù)。再次重申,表單不一定要嵌入流程定義,因此這個(gè)服務(wù)是可選的。

1.6、HistoryService

HistoryService暴露Flowable引擎收集的所有歷史數(shù)據(jù)。當(dāng)執(zhí)行流程時(shí),引擎會(huì)保存許多數(shù)據(jù)(可配置),例如流程實(shí)例啟動(dòng)時(shí)間、誰在執(zhí)行哪個(gè)任務(wù)、完成任務(wù)花費(fèi)的事件、每個(gè)流程實(shí)例的執(zhí)行路徑,等等。這個(gè)服務(wù)主要提供查詢這些數(shù)據(jù)的能力。

1.7、ManagementService

ManagementService通常在用Flowable編寫用戶應(yīng)用時(shí)不需要使用。它可以讀取數(shù)據(jù)庫表與表原始數(shù)據(jù)的信息,也提供了對(duì)作業(yè)(job)的查詢與管理操作。Flowable中很多地方都使用作業(yè),例如定時(shí)器(timer),異步操作(asynchronous continuation),延時(shí)暫停/激活(delayed suspension/activation)等等。后續(xù)會(huì)詳細(xì)介紹這些內(nèi)容。

1.8、DynamicBpmnService

DynamicBpmnService可用于修改流程定義中的部分內(nèi)容,而不需要重新部署它。例如可以修改流程定義中一個(gè)用戶任務(wù)的辦理人設(shè)置,或者修改一個(gè)服務(wù)任務(wù)中的類名。

2、異常策略

Flowable的異?;愂莖rg.flowable.engine.FlowableException,這是一個(gè)非受檢異常(unchecked exception)。在任何API操作時(shí)都可能會(huì)拋出這個(gè)異常,javadoc提供了每個(gè)方法可能拋出的異常。例如,從TaskService中摘錄:

/**
 * 當(dāng)任務(wù)成功執(zhí)行時(shí)調(diào)用。
 * @param taskId 需要完成的任務(wù)id,不能為null。
 * @throws FlowableObjectNotFoundException 若給定id找不到任務(wù)。
 */
 void complete(String taskId);

在上例中,如果所用的id找不到任務(wù),就會(huì)拋出異常。并且,由于javadoc中明確要求taskId不能為null,因此如果傳遞了null值,會(huì)拋出FlowableIllegalArgumentException異常。

盡管我們想避免過大的異常層次結(jié)構(gòu),但在特定情況下仍然會(huì)拋出下述異常子類。所有流程執(zhí)行與API調(diào)用中發(fā)生的錯(cuò)誤,如果不符合下面列出的異常,會(huì)統(tǒng)一拋出FlowableExceptions。

  • FlowableWrongDbException: 當(dāng)Flowable引擎檢測(cè)到數(shù)據(jù)庫表結(jié)構(gòu)版本與引擎版本不匹配時(shí)拋出。
  • FlowableOptimisticLockingException: 當(dāng)對(duì)同一數(shù)據(jù)實(shí)體的并發(fā)訪問導(dǎo)致數(shù)據(jù)存儲(chǔ)發(fā)生樂觀鎖異常時(shí)拋出。
  • FlowableClassLoadingException: 當(dāng)需要載入的類(如JavaDelegate, TaskListener, …?)無法找到,或載入發(fā)生錯(cuò)誤時(shí)拋出。
  • FlowableObjectNotFoundException: 當(dāng)請(qǐng)求或要操作的對(duì)象不存在時(shí)拋出。
  • FlowableIllegalArgumentException: 當(dāng)調(diào)用Flowable API時(shí)使用了不合法的參數(shù)時(shí)拋出??赡苁且媾渲弥械牟缓戏ㄖ担蛘呤茿PI調(diào)用傳遞的不合法參數(shù),也可能是流程定義中的不合法值。
  • FlowableTaskAlreadyClaimedException: 當(dāng)對(duì)已被認(rèn)領(lǐng)的任務(wù)調(diào)用taskService.claim(…?)時(shí)拋出。

3、查詢API

從引擎中查詢數(shù)據(jù)有兩種方式:查詢API與原生(native)查詢。查詢API可以使用鏈?zhǔn)紸PI,通過編程方式進(jìn)行類型安全的查詢。你可以在查詢中增加各種條件(所有條件都用做AND邏輯),也可以明確指定排序方式。下面是示例代碼:

List<Task> tasks = taskService.createTaskQuery()
    .taskAssignee("kermit")
    .processVariableValueEquals("orderId", "0815")
    .orderByDueDate().asc()
    .list();

有時(shí)需要更復(fù)雜的查詢,例如使用OR操作符查詢,或者使用查詢API不能滿足查詢條件要求。我們?yōu)檫@種需求提供了可以自己寫SQL查詢的原生查詢。返回類型由使用的查詢對(duì)象決定,數(shù)據(jù)會(huì)映射到正確的對(duì)象中(Task、ProcessInstance、Execution,等等)。查詢?cè)跀?shù)據(jù)庫中進(jìn)行,因此需要使用數(shù)據(jù)庫中定義的表名與列名。這需要了解內(nèi)部數(shù)據(jù)結(jié)構(gòu),因此建議小心使用原生查詢。數(shù)據(jù)庫表名可以通過API讀取,這樣可以將依賴關(guān)系減到最小。

List<Task> tasks = taskService.createNativeTaskQuery()
  .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) +
      " T WHERE T.NAME_ = #{taskName}")
  .parameter("taskName", "gonzoTask")
  .list();
long count = taskService.createNativeTaskQuery()
  .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T1, " +
      managementService.getTableName(VariableInstanceEntity.class) + " V1 WHERE V1.TASK_ID_ = T1.ID_")
  .count();

4、變量

流程實(shí)例按步驟執(zhí)行時(shí),需要使用一些數(shù)據(jù)。在Flowable中,這些數(shù)據(jù)稱作變量(variable),并會(huì)存儲(chǔ)在數(shù)據(jù)庫中。變量可以用在表達(dá)式中(例如在排他網(wǎng)關(guān)中用于選擇正確的出口路徑),也可以在Java服務(wù)任務(wù)(service task)中用于調(diào)用外部服務(wù)(例如為服務(wù)調(diào)用提供輸入或結(jié)果存儲(chǔ)),等等。

流程實(shí)例可以持有變量(稱作流程變量 process variables);用戶任務(wù)以及執(zhí)行(executions)——流程當(dāng)前活動(dòng)節(jié)點(diǎn)的指針——也可以持有變量。流程實(shí)例可以持有任意數(shù)量的變量,每個(gè)變量存儲(chǔ)為ACT_RU_VARIABLE數(shù)據(jù)庫表的一行。

所有的startProcessInstanceXXX方法都有一個(gè)可選參數(shù),用于在流程實(shí)例創(chuàng)建及啟動(dòng)時(shí)設(shè)置變量。例如,在RuntimeService中:

ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map&amp;lt;String, Object&amp;gt; variables);

也可以在流程執(zhí)行中加入變量。例如,(RuntimeService):

void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);

請(qǐng)注意可以為給定執(zhí)行(請(qǐng)記住,流程實(shí)例由一顆執(zhí)行的樹(tree of executions)組成)設(shè)置局部(local)變量。局部變量將只在該執(zhí)行中可見,對(duì)執(zhí)行樹的上層則不可見。這可以用于 數(shù)據(jù)不應(yīng)該暴露給流程實(shí)例的其他執(zhí)行,或者變量在流程實(shí)例的不同路徑中有不同的值(例如使用并行路徑時(shí))的情況。

可以用下列方法讀取變量。請(qǐng)注意TaskService中有類似的方法。這意味著任務(wù)與執(zhí)行一樣,可以持有局部變量,其生存期為任務(wù)持續(xù)的時(shí)間。

Map<String, Object> getVariables(String executionId);
Map<String, Object> getVariablesLocal(String executionId);
Map<String, Object> getVariables(String executionId, Collection<String> variableNames);
Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames);
Object getVariable(String executionId, String variableName);
<T> T getVariable(String executionId, String variableName, Class<T> variableClass);

變量通常用于Java代理(Java delegates)、表達(dá)式(expressions)、執(zhí)行(execution)、任務(wù)監(jiān)聽器(tasklisteners)、腳本(scripts)等等。在這些結(jié)構(gòu)中,提供了當(dāng)前的execution或task對(duì)象,可用于變量的設(shè)置、讀取。簡單示例如下:

execution.getVariables();
execution.getVariables(Collection<String> variableNames);
execution.getVariable(String variableName);
execution.setVariables(Map<String, object> variables);
execution.setVariable(String variableName, Object value);

請(qǐng)注意也可以使用上例中方法的局部變量版本。

由于歷史(與向后兼容)原因,當(dāng)調(diào)用上述任何方法時(shí),引擎會(huì)從數(shù)據(jù)庫中取出所有變量。也就是說,如果你有10個(gè)變量,使用getVariable(“myVariable”)獲取其中的一個(gè),實(shí)際上其他9個(gè)變量也會(huì)從數(shù)據(jù)庫取出并緩存。這并不壞,因?yàn)楹罄m(xù)的調(diào)用可以不必再讀取數(shù)據(jù)庫。比如,如果流程定義包含三個(gè)連續(xù)的服務(wù)任務(wù)(因此它們?cè)谕粋€(gè)數(shù)據(jù)庫事務(wù)里),在第一個(gè)服務(wù)任務(wù)里通過一次調(diào)用獲取全部變量,也許比在每個(gè)服務(wù)任務(wù)里分別獲取需要的變量要好。請(qǐng)注意對(duì)讀取與設(shè)置變量都是這樣。

當(dāng)然,如果使用大量變量,或者你希望精細(xì)控制數(shù)據(jù)庫查詢與流量,上述的做法就不合適了。我們引入了可以更精細(xì)控制的方法。這個(gè)方法有一個(gè)可選的參數(shù),告訴引擎是否需要讀取并緩存所有變量:

Map<String, Object> getVariables(Collection<String> variableNames, boolean fetchAllVariables);
Object getVariable(String variableName, boolean fetchAllVariables);
void setVariable(String variableName, Object value, boolean fetchAllVariables);

當(dāng)fetchAllVariables參數(shù)為true時(shí),行為與上面描述的完全一樣:讀取或設(shè)置一個(gè)變量時(shí),所有的變量都將被讀取并緩存。

而當(dāng)參數(shù)值為false時(shí),會(huì)使用明確的查詢,其他變量不會(huì)被讀取或緩存。只有指定的變量的值會(huì)被緩存并用于后續(xù)使用。

5、瞬時(shí)變量

瞬時(shí)變量(Transient variable)類似普通變量,只是不會(huì)被持久化。通常來說,瞬時(shí)變量用于高級(jí)使用場(chǎng)景。如果不明確,還是使用普通流程變量為好。

  • 瞬時(shí)變量具有下列特性:
  • 瞬時(shí)變量完全不存儲(chǔ)歷史。
  • 與普通變量類似,設(shè)置瞬時(shí)變量時(shí)會(huì)存入最上層父中。這意味著在一個(gè)執(zhí)行中設(shè)置一個(gè)變量時(shí),瞬時(shí)變量實(shí)際上會(huì)存儲(chǔ)在流程實(shí)例執(zhí)行中。與普通變量類似,可以使用局部(local)的對(duì)應(yīng)方法,將變量設(shè)置為某個(gè)執(zhí)行或任務(wù)的局部變量。
  • 瞬時(shí)變量只能在下一個(gè)“等待狀態(tài)”之前訪問。之后該變量即消失。等待狀態(tài)意味著流程實(shí)例會(huì)持久化至數(shù)據(jù)存儲(chǔ)中。請(qǐng)注意在這個(gè)定義中,異步活動(dòng)也是“等待狀態(tài)”!
  • 只能使用setTransientVariable(name, value)設(shè)置瞬時(shí)變量,但是調(diào)用getVariable(name)也會(huì)返回瞬時(shí)變量(也有g(shù)etTransientVariable(name)方法,它只會(huì)返回瞬時(shí)變量)。這是為了簡化表達(dá)式的撰寫,并保證已有邏輯可以使用這兩種類型的變量。
  • 瞬時(shí)變量屏蔽(shadow)同名的持久化變量。也就是說當(dāng)一個(gè)流程實(shí)例中設(shè)置了同名的持久化變量與瞬時(shí)變量時(shí),getVariable(“someVariable”)會(huì)返回瞬時(shí)變量的值。

在大多數(shù)可以使用普通變量的地方,都可以獲取、設(shè)置瞬時(shí)變量:

  • 在JavaDelegate實(shí)現(xiàn)中的DelegateExecution內(nèi)
  • 在ExecutionListener實(shí)現(xiàn)中的DelegateExecution內(nèi),以及在TaskListener實(shí)現(xiàn)中的DelegateTask內(nèi)
  • 通過execution對(duì)象在腳本任務(wù)內(nèi)
  • 通過RuntimeService啟動(dòng)流程實(shí)例時(shí)
  • 完成任務(wù)時(shí)
  • 調(diào)用runtimeService.trigger方法時(shí)
  • 瞬時(shí)變量相關(guān)的方法遵循普通流程變量方法的命名約定:
void setTransientVariable(String variableName, Object variableValue);
void setTransientVariableLocal(String variableName, Object variableValue);
void setTransientVariables(Map<String, Object> transientVariables);
void setTransientVariablesLocal(Map<String, Object> transientVariables);
Object getTransientVariable(String variableName);
Object getTransientVariableLocal(String variableName);
Map<String, Object> getTransientVariables();
Map<String, Object> getTransientVariablesLocal();
void removeTransientVariable(String variableName);
void removeTransientVariableLocal(String variableName);

示例

假設(shè)’Fetch Data(獲取數(shù)據(jù))'服務(wù)任務(wù)調(diào)用某個(gè)遠(yuǎn)程服務(wù)(例如使用REST)。也假設(shè)需要其需要一些配置參數(shù),并需要在啟動(dòng)流程實(shí)例時(shí)提供。同時(shí),這些配置參數(shù)對(duì)于歷史審計(jì)并不重要,因此我們將它們作為瞬時(shí)變量傳遞:

ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
       .processDefinitionKey("someKey")
       .transientVariable("configParam01", "A")
       .transientVariable("configParam02", "B")
       .transientVariable("configParam03", "C")
       .start();

請(qǐng)注意在到達(dá)用戶任務(wù)并持久化之前,都可以使用這些瞬時(shí)變量。例如,在’Additional Work(額外工作)'用戶任務(wù)中它們就不再可用。也請(qǐng)注意如果’Fetch Data’是異步的,則瞬時(shí)變量在該步驟之后也不再可用。

Fetch Data(的簡化版本)可以像是:

public static class FetchDataServiceTask implements JavaDelegate {
  public void execute(DelegateExecution execution) {
    String configParam01 = (String) execution.getVariable(configParam01);
    // ...
    RestReponse restResponse = executeRestCall();
    execution.setTransientVariable("response", restResponse.getBody());
    execution.setTransientVariable("status", restResponse.getStatus());
  }
}

Process Data(處理數(shù)據(jù))'可以獲取response瞬時(shí)變量,解析并將其相關(guān)數(shù)據(jù)存儲(chǔ)在實(shí)際流程變量中,因?yàn)橹筮€需要使用它們。

離開排他網(wǎng)關(guān)的順序流上的條件表達(dá)式,不關(guān)注使用的是持久化還是瞬時(shí)變量(在這個(gè)例子中status是瞬時(shí)變量):

&amp;lt;conditionExpression xsi:type&amp;#61;&amp;#34;tFormalExpression&amp;#34;&amp;gt;${status &amp;#61;&amp;#61; 200}&amp;lt;/conditionExpression&amp;gt;

6、表達(dá)式

Flowable使用UEL進(jìn)行表達(dá)式解析。UEL代表Unified Expression Language,是EE6規(guī)范的一部分(查看EE6規(guī)范了解更多信息)。

表達(dá)式可以用于Java服務(wù)任務(wù)(Java Service task)、執(zhí)行監(jiān)聽器(Execution Listener)、任務(wù)監(jiān)聽器(Task Listener) 與 條件順序流(Conditional sequence flow)等。盡管有值表達(dá)式與方法表達(dá)式這兩種不同的表達(dá)式,F(xiàn)lowable通過抽象,使它們都可以在需要表達(dá)式的地方使用。

值表達(dá)式 Value expression: 解析為一個(gè)值。默認(rèn)情況下,所有流程變量都可以使用。(若使用Spring)所有的Spring bean也可以用在表達(dá)式里。例如:

${myVar}
${myBean.myProperty}

方法表達(dá)式 Method expression: 調(diào)用一個(gè)方法,可以帶或不帶參數(shù)。當(dāng)調(diào)用不帶參數(shù)的方法時(shí),要確保在方法名后添加空括號(hào)(以避免與值表達(dá)式混淆)。傳遞的參數(shù)可以是字面值(literal value),也可以是表達(dá)式,它們會(huì)被自動(dòng)解析。例如:

${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.doSomething(myVar, execution)}

請(qǐng)注意,表達(dá)式支持解析(及比較)原始類型(primitive)、bean、list、array與map。 Note that these expressions support resolving primitives (including comparing them), beans, lists, arrays and maps.

除了所有流程變量外,還有一些默認(rèn)對(duì)象可在表達(dá)式中使用:

  • execution: DelegateExecution+,持有正在運(yùn)行的執(zhí)行的額外信息。
  • task: DelegateTask持有當(dāng)前任務(wù)的額外信息。請(qǐng)注意:只在任務(wù)監(jiān)聽器的表達(dá)式中可用。
  • authenticatedUserId: 當(dāng)前已驗(yàn)證的用戶id。如果沒有已驗(yàn)證的用戶,該變量不可用。

7、單元測(cè)試

業(yè)務(wù)流程是軟件項(xiàng)目的必要組成部分,也需要使用測(cè)試一般應(yīng)用邏輯的方法——單元測(cè)試——測(cè)試它們。Flowable是嵌入式的Java引擎,因此為業(yè)務(wù)流程編寫單元測(cè)試就同編寫一般的單元測(cè)試一樣簡單。

Flowable支持JUnit 3及4的單元測(cè)試風(fēng)格。按照J(rèn)Unit 3的風(fēng)格,必須擴(kuò)展(extended)org.flowable.engine.test.FlowableTestCase。它通過保護(hù)(protected)成員變量提供對(duì)ProcessEngine與服務(wù)的訪問。在測(cè)試的setup()中,processEngine會(huì)默認(rèn)使用classpath中的flowable.cfg.xml資源初始化。如果要指定不同的配置文件,請(qǐng)覆蓋getConfigurationResource()方法。當(dāng)使用相同的配置資源時(shí),流程引擎會(huì)靜態(tài)緩存,用于多個(gè)單元測(cè)試。

通過擴(kuò)展FlowableTestCase,可以使用org.flowable.engine.test.Deployment注解測(cè)試方法。在測(cè)試運(yùn)行前,會(huì)部署與測(cè)試類在同一個(gè)包下的格式為testClassName.testMethod.bpmn20.xml的資源文件。在測(cè)試結(jié)束時(shí),會(huì)刪除這個(gè)部署,包括所有相關(guān)的流程實(shí)例、任務(wù),等等。也可以使用Deployment注解顯式指定資源位置。查看該類以獲得更多信息。

綜上所述,JUnit 3風(fēng)格的測(cè)試看起來類似:

public class MyBusinessProcessTest extends FlowableTestCase {
  @Deployment
  public void testSimpleProcess() {
    runtimeService.startProcessInstanceByKey("simpleProcess");
    Task task = taskService.createTaskQuery().singleResult();
    assertEquals("My Task", task.getName());
    taskService.complete(task.getId());
    assertEquals(0, runtimeService.createProcessInstanceQuery().count());
  }
}

要使用JUnit 4的風(fēng)格書寫單元測(cè)試并達(dá)成同樣的功能,必須使用org.flowable.engine.test.FlowableRule Rule。這樣能夠通過它的getter獲得流程引擎與服務(wù)。對(duì)于FlowableTestCase(上例),包含@Rule就可以使用org.flowable.engine.test.Deployment注解(參見上例解釋其用途及配置),并且會(huì)自動(dòng)在classpath中尋找默認(rèn)配置文件。當(dāng)使用相同的配置資源時(shí),流程引擎會(huì)靜態(tài)緩存,以用于多個(gè)單元測(cè)試。

下面的代碼片段展示了JUnit 4風(fēng)格的測(cè)試與FlowableRule的用法。

public class MyBusinessProcessTest {
  @Rule
  public FlowableRule FlowableRule = new FlowableRule();
  @Test
  @Deployment
  public void ruleUsageExample() {
    RuntimeService runtimeService = FlowableRule.getRuntimeService();
    runtimeService.startProcessInstanceByKey("ruleUsage");
    TaskService taskService = FlowableRule.getTaskService();
    Task task = taskService.createTaskQuery().singleResult();
    assertEquals("My Task", task.getName());
    taskService.complete(task.getId());
    assertEquals(0, runtimeService.createProcessInstanceQuery().count());
  }
}

8、Web應(yīng)用中的流程引擎

ProcessEngine是線程安全的類,可以很容易地在多個(gè)線程間共享。在web應(yīng)用中,這意味著可以在容器啟動(dòng)時(shí)創(chuàng)建引擎,并在容器關(guān)閉時(shí)關(guān)閉引擎。

下面的代碼片段展示了如何在Servlet環(huán)境中,通過ServletContextListener初始化與銷毀流程引擎。

public class ProcessEnginesServletContextListener implements ServletContextListener {
  public void contextInitialized(ServletContextEvent servletContextEvent) {
    ProcessEngines.init();
  }
  public void contextDestroyed(ServletContextEvent servletContextEvent) {
    ProcessEngines.destroy();
  }
}

contextInitialized方法會(huì)調(diào)用ProcessEngines.init()。它會(huì)在classpath中查找flowable.cfg.xml資源文件,并為每個(gè)文件分別創(chuàng)建ProcessEngine(如果多個(gè)JAR都包含配置文件)。如果在classpath中有多個(gè)這樣的資源文件,請(qǐng)確保它們使用不同的引擎名。需要使用流程引擎時(shí),可以這樣獲?。?/p>

ProcessEngines.getDefaultProcessEngine()

或者:

ProcessEngines.getProcessEngine(&amp;#34;myName&amp;#34;);

context-listener的contextDestroyed方法會(huì)調(diào)用ProcessEngines.destroy()。它會(huì)妥善關(guān)閉所有已初始化的流程引擎。

到此這篇關(guān)于Flowable流程引擎API與服務(wù)的文章就介紹到這了,更多相關(guān)Flowable API內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • ApplicationListenerDetector監(jiān)聽器判斷demo

    ApplicationListenerDetector監(jiān)聽器判斷demo

    這篇文章主要為大家介紹了ApplicationListenerDetector監(jiān)聽器判斷demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Java8新特性之Stream API詳解

    Java8新特性之Stream API詳解

    這篇文章主要介紹了Java8新特性之StreamAPI詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • hadoop之MapReduce框架原理

    hadoop之MapReduce框架原理

    這篇文章主要介紹了hadoop的MapReduce框架原理,MapReduce是分為兩個(gè)階段的,MapperTask階段,和ReduceTask階段。如果有感興趣的小伙伴可以借鑒參考
    2023-03-03
  • Java中的命名與目錄接口JNDI基本操作方法概覽

    Java中的命名與目錄接口JNDI基本操作方法概覽

    這篇文章主要介紹了Java中的命名與目錄接口JNDI基本操作方法概覽,JNDI提供統(tǒng)一的客戶端API使得Java應(yīng)用程序可以和這些命名服務(wù)和目錄服務(wù)之間進(jìn)行交互,需要的朋友可以參考下
    2016-03-03
  • java打印正弦曲線示例

    java打印正弦曲線示例

    這篇文章主要介紹了java數(shù)組排序示例,需要的朋友可以參考下
    2014-03-03
  • Java實(shí)現(xiàn)十秒向MySQL插入百萬條數(shù)據(jù)

    Java實(shí)現(xiàn)十秒向MySQL插入百萬條數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)十秒向MySQL插入百萬條數(shù)據(jù),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定借鑒價(jià)值,需要的可以參考一下
    2022-11-11
  • SpringCloud OpenFeign基本介紹與實(shí)現(xiàn)示例

    SpringCloud OpenFeign基本介紹與實(shí)現(xiàn)示例

    OpenFeign源于Netflix的Feign,是http通信的客戶端。屏蔽了網(wǎng)絡(luò)通信的細(xì)節(jié),直接面向接口的方式開發(fā),讓開發(fā)者感知不到網(wǎng)絡(luò)通信細(xì)節(jié)。所有遠(yuǎn)程調(diào)用,都像調(diào)用本地方法一樣完成
    2023-02-02
  • java實(shí)現(xiàn)字符串反轉(zhuǎn)案例

    java實(shí)現(xiàn)字符串反轉(zhuǎn)案例

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)字符串反轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • JAVA mongodb 聚合幾種查詢方式詳解

    JAVA mongodb 聚合幾種查詢方式詳解

    這篇文章主要介紹了JAVA mongodb 聚合幾種查詢方式詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • Mybatis-plus原生pages分頁未生效的解決方案

    Mybatis-plus原生pages分頁未生效的解決方案

    本文主要介紹了Mybatis-plus原生pages分頁未生效的解決方案,包含介紹了未生效的5種原因以及解決方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07

最新評(píng)論