教程地址:https://tkjohn.github.io/flowable-userguide/#bpmnConditionalSequenceFlow
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef"> <process id="holley-test8" name="zhl-test8" isExecutable="true"> <documentation>后禮測試流程</documentation> <!-- 執行監聽器 可以捕獲的事件:1.流程實例的啟動和結束。2.流程執行轉移。3.活動的啟動和結束。4.網關的啟動和結束。5.中間事件的啟動和結束。6.啟動事件的結束,和結束事件的啟動。 <flowable:executionListener class="類名全路徑" event="start"/> 注意:這個類需要實現org.flowable.engine.delegate.ExecutionListener接口 <flowable:executionListener expression="${myPojo.myMethod(execution.event)}" event="end" /> 注意:execution.event將事件作為參數傳遞 執行監聽器也支持使用delegateExpression。 <flowable:executionListener event="start" delegateExpression="${myExecutionListenerBean}" /> --> <extensionElements> <flowable:executionListener class="com.insgeek.platform.event.holley.listener.MyExecutionListener" event="start"/> <!-- <flowable:eventListener events="ACTIVITY_COMPLETED" class="com.insgeek.platform.event.holley.listener.MyEventListener"/>--> </extensionElements> <!-- <extensionElements>--> <!-- <flowable:eventListener class="com.insgeek.platform.event.holley.listener.MyEventListener" />--> <!-- <flowable:eventListener delegateExpression="${testEventListener}" events="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" />--> <!-- </extensionElements>--> <startEvent id="startEvent1"/> <userTask id="task-number-01" name = "${name}任務1" flowable:formFieldValidation="true" flowable:assignee="${holidayForm.name}"> <!-- flowable:candidateUsers="" --> <!-- flowable:candidateGroups=""--> <extensionElements> <flowable:formProperty id="days" expression="${days}" required="true" type="int" name="請假天數"/> <flowable:formProperty id="name" expression="${name}" required="true" name="請假天數"/> <flowable:formProperty id="id" expression="${id}" type="long" required="true" name="請假人id"/> </extensionElements> </userTask> <sequenceFlow id="line-number-01" sourceRef="startEvent1" targetRef="task-number-01"/> <!-- 服務任務: 注意: flowable:class="全路徑類名" 這個方法主要使用在service task中,此處作為測試 (指定實現了JavaDelegate或ActivityBehavior的類) 調用解析為委托對象(delegation object)的表達式 :delegateExpressionBean是一個實現了JavaDelegate接口的bean,定義在Spring容器中 <serviceTask id="serviceTask" flowable:delegateExpression="${delegateExpressionBean}" 調用方法表達式(method expression): 將在名為printer的對象上調用printMessage方法(不帶參數) <serviceTask id="javaService" name="My Java Service Task" flowable:expression="${printer.printMessage()}" /> 將在名為printer的對象上調用printMessage方法。傳遞的第一個參數為DelegateExecution,名為execution,在表達式上下文中默認可用。傳遞的第二個參數, 是當前執行中,名為myVar變量的值。 <serviceTask id="javaService" name="My Java Service Task" flowable:expression="${printer.printMessage(execution, myVar)}" /> 對值表達式(value expression)求值 會調用名為split的bean的ready參數的getter方法,getReady(不帶參數)。該對象會被解析為執行的流程變量或(如果可用的話)Spring上下文中的bean <serviceTask id="javaService" name="My Java Service Task" flowable:expression="${split.ready}" /> 只會為serviceTask上定義的Java類創建一個實例。所有流程實例共享同一個類實例,用於調用execute(DelegateExecution)。這意味着該類不能有任何成員變量, 並需要是線程安全的,因為它可能會在不同線程中同時執行。這也影響了字段注入的使用方法。 flowable:class和flowable:delegateExpression支持字段注入,如下: <extensionElements> <flowable:field name="text" stringValue="Hello World" /> </extensionElements> 對於較長文本: <extensionElements> <flowable:field name="text"> <flowable:string> This is a long string </flowable:string> </flowable:field></extensionElements> <extensionElements> <flowable:field name="text1"> <flowable:expression>${genderBean.getGenderString(gender)}</flowable:expression> </flowable:field> <flowable:field name="text2"> <flowable:expression>Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}</flowable:expression> </flowable:field> </ extensionElements> 另外,為避免XML太過冗長,可以將表達式設置為屬性,而不是子元素。 <flowable:field name="text1" expression="${genderBean.getGenderString(gender)}" /> <flowable:field name="text1" expression="Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}" /> --> <!-- 方法表達式(method expression)調用 bean中的方法--> <serviceTask id="task-number-02" name="服務任務1" flowable:class="com.insgeek.platform.event.holley.task.TestServiceTaskDelegate"> <!-- flowable:expression="${holidayForm.toString()}" --> <extensionElements> <flowable:formProperty id="approve" expression="${approve}" required="true" type="boolean" name="審批結果"/> <flowable:formProperty id="days" expression="${days}" required="true" type="int" name="請假天數"/> </extensionElements> </serviceTask> <sequenceFlow id="line-number-02" sourceRef="task-number-01" targetRef="task-number-02"> <extensionElements> <!-- 流程轉移時執行監聽器 在流程執行轉移時被調用。請注意listener元素並未定義event,因為在轉移上只會觸發take事件。當監聽器定義在轉移上時,event屬性的值將被忽略 --> <flowable:executionListener class="com.insgeek.platform.event.holley.listener.MyExecutionListener" /> </extensionElements> </sequenceFlow> <!-- 條件順序流: 條件順序流的XML表示格式為含有conditionExpression(條件表達式)子元素的普通順序流。 請注意目前只支持tFormalExpressions可以省略xsi:type=""定義,默認為唯一支持的表達式類型 目前conditionalExpressions只能使用UEL。使用的表達式需要能解析為boolean值,否則當計算條件時會拋出異常。 這個例子通過典型的JavaBean的方式,使用getter引用流程變量的數據 <conditionExpression xsi:type="tFormalExpression"> <![CDATA[${order.price > 100 && order.price < 250}]]> </conditionExpression> 這個例子調用了一個解析為boolean值的方法: <conditionExpression xsi:type="tFormalExpression"> <![CDATA[${order.isStandardOrder()}]]> </conditionExpression> --> <exclusiveGateway id="gateway-number-01"/> <sequenceFlow id="line-number-03" sourceRef="task-number-02" targetRef="gateway-number-01"/> <!-- 任務監聽器:用於在特定的任務相關事件發生時,執行自定義的Java邏輯或表達式。*只能*在流程定義中作為用戶任務的子元素 任務監聽器包含下列屬性: event(事件)(必填):觸發任務監聽器的任務事件類型。可用的事件有: create(創建):當任務已經創建,並且所有任務參數都已經設置時觸發。 assignment(指派):當任務已經指派給某人時觸發。請注意:當流程執行到達用戶任務時,在觸發create事件之前,會首先觸發assignment事件。 這順序看起來不太自然,但是有實際原因的:當收到create事件時,我們通常希望能看到任務的所有參數,包括辦理人。 complete(完成):當任務已經完成,從運行時數據中刪除前觸發。 delete(刪除):在任務即將被刪除前觸發。請注意任務由completeTask正常完成時也會觸發。 class:需要調用的委托類。這個類必須實現org.flowable.engine.delegate.TaskListener接口。 expression:(不能與class屬性一起使用):指定在事件發生時要執行的表達式。可以為被調用的對象傳遞DelegateTask對象與事件名(使用task.eventName)作為參數。 <flowable:taskListener event="create" expression="${myObject.callMethod(task, task.eventName)}" /> delegateExpression:指定一個能夠解析為TaskListener接口實現類的對象的表達式。與服務任務類似。 <flowable:taskListener event="create" delegateExpression="${myTaskListenerBean}" /> --> <userTask id="task-number-03" name="${name}任務2" flowable:assignee="zhl" > <!-- flowable:candidateUsers="user1,user2" 當使用候選人分配時,會創建一個任務,但是任務中的assignee的值為null。 而且如果同時配置flowable:assignee和flowable:candidateUsers,則只會創建flowable:assignee的任務 --> <extensionElements> <!-- 任務監聽器,可以在任務監聽器中動態分配用戶--> <flowable:taskListener event="complete" class="com.insgeek.platform.event.holley.listener.MyAssignmentHandlerTaskListener" /> <!-- 活動結束時執行監聽器--> <flowable:executionListener expression="${myExpressionExecutionListener.test(execution.eventName)}" event="end" /> </extensionElements> <!-- 指派具體用戶 --> <!-- <humanPerformer>--> <!-- <resourceAssignmentExpression>--> <!-- <formalExpression>test</formalExpression>--> <!-- </resourceAssignmentExpression>--> <!-- </humanPerformer>--> </userTask> <userTask id="task-number-04" name="${name}任務4" flowable:candidateUsers="aaa,bbb"> <!-- flowable:assignee="${name}"--> <extensionElements> <flowable:executionListener event="start" expression=" ${rejectExecutionListener.test(execution)}"/> <!-- 添加一個在事件create時的監聽器,在監聽器中可以將該事件分配給其它人, 分配之后,原處理人沒有權限了,但此時在ru_identityLink表中還會為之前的處理人創建N條數據(假設實例是Q個,如果是m個候選人的話,n=(m+1)*Q。如果是指定的某個處理人,則n=Q)--> <flowable:taskListener event="create" class = "com.insgeek.platform.event.holley.listener.AssignmentTaskListener"/> </extensionElements> <!-- 多實例時,會給每個指派的用戶創建數量等同於assigneeList長度的並行任務,只是每一個執行任務都有一個名為user的(局部)流程變量,含有集合userList中的一項值 --> <multiInstanceLoopCharacteristics isSequential="false" flowable:collection="${myTest.getUsers(execution)}" flowable:elementVariable="user" > <!-- flowable:collection="userList" flowable:elementVariable="user" >--> <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.3 }</completionCondition> </multiInstanceLoopCharacteristics> </userTask> <sequenceFlow id="line-number-04" sourceRef="gateway-number-01" targetRef="task-number-03" > <!-- 注意:條件流下面添加執行監聽器時,順序一定要放在條件標簽上面,否則會報錯 --> <extensionElements> <!-- 流程轉移時執行監聽器 在流程執行轉移時被調用。請注意listener元素並未定義event,因為在轉移上只會觸發take事件。當監聽器定義在轉移上時,event屬性的值將被忽略 --> <flowable:executionListener class="com.insgeek.platform.event.holley.listener.MyExecutionListener2" /> </extensionElements> <conditionExpression xsi:type="tFormalExpression"> <![CDATA[ ${days > 3} ]]> </conditionExpression> </sequenceFlow> <sequenceFlow id="line-number-05" sourceRef="gateway-number-01" targetRef="task-number-04"> <extensionElements> <!-- 流程轉移時執行監聽器 在流程執行轉移時被調用。請注意listener元素並未定義event,因為在轉移上只會觸發take事件。當監聽器定義在轉移上時,event屬性的值將被忽略 --> <flowable:executionListener class="com.insgeek.platform.event.holley.listener.MyExecutionListener3" /> </extensionElements> <conditionExpression xsi:type="tFormalExpression"> <![CDATA[ ${days <= 3} ]]> </conditionExpression> </sequenceFlow> <endEvent id="endEvent1"> <extensionElements> <flowable:executionListener class="com.insgeek.platform.event.holley.listener.MyEndExecutionListener" event="end"/> </extensionElements> </endEvent> <sequenceFlow id="line-number-06" sourceRef="task-number-03" targetRef="endEvent1"/> <sequenceFlow id="line-number-07" sourceRef="task-number-04" targetRef="endEvent1" /> <!-- 多實例:網關與事件不能設置為多實例。 按照BPMN2.0規范的要求,用於為每個實例創建執行的父執行,會提供下列變量: nrOfInstances:實例總數。 nrOfActiveInstances:當前活動的(即未完成的),實例數量。對於順序多實例,這個值總為1。 nrOfCompletedInstances:已完成的實例數量。 可以調用execution.getVariable(x)方法獲取這些值。 每個被創建的執行,都有局部變量(對其他執行不可見,也不存儲在流程實例級別) loopCounter:給定實例在for-each循環中的index。可以通過Flowable的elementIndexVariable屬性為loopCounter變量重命名 --> </process> </definitions>
注意事項:
1.在條件流上添加執行監聽器時,一定要保證extensionElements元素放在conditionExpression元素之前,否則會報錯,正確順序如下:
<sequenceFlow id="line-number-04" sourceRef="gateway-number-01" targetRef="task-number-03" > <!-- 注意:條件流下面添加執行監聽器時,順序一定要放在條件標簽上面,否則會報錯 --> <extensionElements> <!-- 流程轉移時執行監聽器 在流程執行轉移時被調用。請注意listener元素並未定義event,因為在轉移上只會觸發take事件。當監聽器定義在轉移上時,event屬性的值將被忽略 --> <flowable:executionListener class="com.insgeek.platform.event.holley.listener.MyExecutionListener" /> </extensionElements> <conditionExpression xsi:type="tFormalExpression"> <![CDATA[ ${days > 3} ]]> </conditionExpression> </sequenceFlow>