案例
为了便于快速入门,这里定义一个非常简单的 请假流程。
流程图
官方图如下:
翻译成下图:
解释:
左侧的 圆圈 是
启动事件(start event)。这是一个流程实例的 起点。第一个 矩形 是一个
用户任务(user task)。这是流程中人类用户操作的步骤。在这个例子中,经理需要批准或驳回申请。带叉的菱形 是
排他网关(exclusive gateway),会将流程实例路由至批准或驳回路径。如果同意,就调用某个外部系统api(如:在oa系统请假通过后,调用erp系统api,这样erp系统可以进行排班等)。并将经理的结果通知给申请人
如果驳回,则给员工发送一封邮件
如何设置流程的第一步?
一般启动流程时,都需要提交信息,如:员工名字、请假时长以及说明。那么 提交信息,可以作为流程中的 第一步 吗?
如果 提交信息 作为第一步,输入信息并提交,就 创建流程实例,当用户改变主意时(如:由于是第一步,用户很有可能填写错误,要重新填写),此时就要 取消流程,在某些场景中,可能影响重要的指标,如:统计启动了多少申请,但还未完成
所以,为了灵活,提交信息 不算工作流程的第一步。
注意:是否作为第一步,完全具体情况具体分析
流程定义文件
提示:该流程定义文件是对 官网流程翻译的(下面是官方流程定义文件)
在 resources 文件夹下,创建 请假审批流程5.bpmn20.xml 文件,内容如下:
<?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="holidayRequest" name="请假审批流程5" isExecutable="true">
<startEvent id="startEvent"></startEvent>
<sequenceFlow id="sequenceFlow-d8a55f73-e820-42f1-8a92-6b7d5033caf5" sourceRef="startEvent" targetRef="approveTask"></sequenceFlow>
<userTask id="approveTask" name="部门经理审批" flowable:candidateGroups="managers"></userTask>
<sequenceFlow id="sequenceFlow-ed5282cc-ec2e-48b8-a47c-6015c8b36125" sourceRef="approveTask" targetRef="decision"></sequenceFlow>
<exclusiveGateway id="decision"></exclusiveGateway>
<serviceTask id="externalSystemCall" name="调用外部系统发送假期" flowable:class="org.flowable.CallExternalSystemDelegate"></serviceTask>
<sequenceFlow id="sequenceFlow-6c7b7298-5703-4100-8573-c57d0d5d4462" sourceRef="externalSystemCall" targetRef="holidayApprovedTask"></sequenceFlow>
<userTask id="holidayApprovedTask" name="通知申请人" flowable:assignee="${emp}">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="sequenceFlow-87a050e4-1f38-4a0a-b4c2-ae70de12889e" sourceRef="holidayApprovedTask" targetRef="approveEnd"></sequenceFlow>
<serviceTask id="sendRejectionMail" name="发送拒绝邮件" flowable:class="org.flowable.SendRejectionMail"></serviceTask>
<sequenceFlow id="sequenceFlow-add4cbf3-6b44-4b42-8f3a-d223882105ec" sourceRef="sendRejectionMail" targetRef="rejectEnd"></sequenceFlow>
<endEvent id="approveEnd"></endEvent>
<endEvent id="rejectEnd"></endEvent>
<sequenceFlow id="sequenceFlow-8fcee143-f1e5-4f3e-9eba-593840c30c6f" name="拒绝" sourceRef="decision" targetRef="sendRejectionMail">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${!approved}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="sequenceFlow-50ace6b5-ce3f-4398-8037-700d738937a5" name="同意" sourceRef="decision" targetRef="externalSystemCall">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${approved}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_holidayRequest">
<bpmndi:BPMNPlane bpmnElement="holidayRequest" id="BPMNPlane_holidayRequest">
<bpmndi:BPMNShape bpmnElement="startEvent" id="BPMNShape_startEvent">
<omgdc:Bounds height="30.0" width="30.0" x="100.0" y="155.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="approveTask" id="BPMNShape_approveTask">
<omgdc:Bounds height="60.0" width="100.0" x="180.0" y="140.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="decision" id="BPMNShape_decision">
<omgdc:Bounds height="40.0" width="40.0" x="330.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="externalSystemCall" id="BPMNShape_externalSystemCall">
<omgdc:Bounds height="60.0" width="100.0" x="449.9999932944776" y="139.99999791383746"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="holidayApprovedTask" id="BPMNShape_holidayApprovedTask">
<omgdc:Bounds height="60.00000000000003" width="100.0" x="629.9999906122686" y="139.99999791383746"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sendRejectionMail" id="BPMNShape_sendRejectionMail">
<omgdc:Bounds height="60.0" width="100.0" x="449.9999865889554" y="284.9999825358397"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="approveEnd" id="BPMNShape_approveEnd">
<omgdc:Bounds height="28.0" width="28.0" x="794.9999881535771" y="155.99999767541888"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="rejectEnd" id="BPMNShape_rejectEnd">
<omgdc:Bounds height="28.0" width="28.0" x="644.9999903887511" y="300.9999780505905"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow-87a050e4-1f38-4a0a-b4c2-ae70de12889e" id="BPMNEdge_sequenceFlow-87a050e4-1f38-4a0a-b4c2-ae70de12889e">
<omgdi:waypoint x="729.9499829189559" y="169.99999782142714"></omgdi:waypoint>
<omgdi:waypoint x="794.9999834136223" y="169.99999770120135"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow-6c7b7298-5703-4100-8573-c57d0d5d4462" id="BPMNEdge_sequenceFlow-6c7b7298-5703-4100-8573-c57d0d5d4462">
<omgdi:waypoint x="549.949993294448" y="169.99999791383746"></omgdi:waypoint>
<omgdi:waypoint x="629.9999906122686" y="169.9999979138375"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow-8fcee143-f1e5-4f3e-9eba-593840c30c6f" id="BPMNEdge_sequenceFlow-8fcee143-f1e5-4f3e-9eba-593840c30c6f">
<omgdi:waypoint x="350.0" y="189.94312542991003"></omgdi:waypoint>
<omgdi:waypoint x="350.0" y="314.99998253583976"></omgdi:waypoint>
<omgdi:waypoint x="449.9999865889554" y="314.99998253583976"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow-d8a55f73-e820-42f1-8a92-6b7d5033caf5" id="BPMNEdge_sequenceFlow-d8a55f73-e820-42f1-8a92-6b7d5033caf5">
<omgdi:waypoint x="129.9499986183554" y="170.0"></omgdi:waypoint>
<omgdi:waypoint x="180.0" y="170.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow-50ace6b5-ce3f-4398-8037-700d738937a5" id="BPMNEdge_sequenceFlow-50ace6b5-ce3f-4398-8037-700d738937a5">
<omgdi:waypoint x="369.94335470726526" y="169.99999972184497"></omgdi:waypoint>
<omgdi:waypoint x="449.9999932944776" y="169.9999986085296"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow-add4cbf3-6b44-4b42-8f3a-d223882105ec" id="BPMNEdge_sequenceFlow-add4cbf3-6b44-4b42-8f3a-d223882105ec">
<omgdi:waypoint x="549.9499865889554" y="314.99998112538395"></omgdi:waypoint>
<omgdi:waypoint x="644.9999896993223" y="314.9999784441077"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow-ed5282cc-ec2e-48b8-a47c-6015c8b36125" id="BPMNEdge_sequenceFlow-ed5282cc-ec2e-48b8-a47c-6015c8b36125">
<omgdi:waypoint x="279.95000000000005" y="170.0"></omgdi:waypoint>
<omgdi:waypoint x="330.0" y="170.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
解释:
每一个步骤(在BPMN 2.0术语中称作活动(activity))都有一个id属性,为其提供一个在XML文件中唯一的标识符。所有的活动都可以设置一个名字,以提高流程图的可读性。
活动之间通过顺序流(sequence flow)连接,在流程图中是一个有向箭头。在执行流程实例时,执行(execution)会从启动事件沿着顺序流流向下一个活动。
离开排他网关(带有X的菱形)的顺序流很特别:都以表达式(expression)的形式定义了条件(condition) (见第25至32行)。当流程实例的执行到达这个网关时,会计算条件,并使用第一个计算为true的顺序流。这就是排他的含义:只选择一个。当然如果需要不同的路由策略,可以使用其他类型的网关。
这里用作条件的表达式为${approved},这是${approved == true}的简写。变量’approved’被称作流程变量(process variable)。流程变量是持久化的数据,与流程实例存储在一起,并可以在流程实例的生命周期中使用。在这个例子里,我们需要在特定的地方(当经理用户任务提交时,或者以Flowable的术语来说,完成(complete)时)设置这个流程变量,因为这不是流程实例启动时就能获取的数据。
官方流程定义文件
提示:下面是官方流程定义文件,一般情况用上面翻译的就行
在 resources 文件夹下,创建 holiday-request.bpmn20.xml 文件,内容如下:
<?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: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"
xmlns:flowable="http://flowable.org/bpmn"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="http://www.flowable.org/processdef">
<process id="holidayRequest" name="Holiday Request" isExecutable="true">
<startEvent id="startEvent"/>
<sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>
<userTask id="approveTask" name="Approve or reject request"/>
<sequenceFlow sourceRef="approveTask" targetRef="decision"/>
<exclusiveGateway id="decision"/>
<sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[
${approved}
]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="decision" targetRef="sendRejectionMail">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[
${!approved}
]]>
</conditionExpression>
</sequenceFlow>
<serviceTask id="externalSystemCall" name="Enter holidays in external system"
flowable:class="org.flowable.CallExternalSystemDelegate"/>
<sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>
<userTask id="holidayApprovedTask" name="Holiday approved"/>
<sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>
<serviceTask id="sendRejectionMail" name="Send out rejection email"
flowable:class="org.flowable.SendRejectionMail"/>
<sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>
<endEvent id="approveEnd"/>
<endEvent id="rejectEnd"/>
</process>
</definitions>

