前言:
不用到处百度BPMN2的博客了,本篇文章带你系统掌握BPMN2规范的核心知识点。全文2万字,全覆盖BPMN2知识点,图文并茂,泡杯咖啡,慢慢细品~
BPMN(Business Process Modeling Notation,业务流程建模符号)是一种流程建模的通用和标准语言,用来绘制业务流程图,以便更好地让各部门之间理解业务流程和相互关系,旨在促进业务流程的沟通和理解。
BPMN 标准发展版本历史有BPMN1.0,BPMN1.1,BPMN1.2,BPMN2.0。BPMN2.0在1.x基础上新增了元模型、存储、交互、执行。
Flowable用的是BPM2.0模型规范。
BPMN2.0结构主要有,事件、顺序流、网关、任务、子流程与调用活动等。
本篇文章也是简单描述一下BPMN的结构有哪些,不展开细致内容,后续有使用的地方详细讲解。
更多BPM相关信息可以查阅:BPMN官网
事件(event)通常用于为流程生命周期中发生的事情建模。事件总是图形化为圆圈。在BPMN 2.0中,有两种主要的事件分类:捕获(catching)与抛出(throwing)事件。
事件定义(event definition),用于定义事件的语义。没有事件定义的话,事件就“不做什么特别的事情”。例如,一个没有事件定义的开始事件,并不限定具体是什么启动了流程。如果为这个开始事件添加事件定义(例如定时器事件定义),就声明了启动流程的“类型”(例如对于定时器事件定义,就是到达了特定的时间点)。
定时器事件(timer event definition),是由定时器所触发的事件。可以用于开始事件,中间事件,或边界事件。定时器事件的行为取决于所使用的业务日历(business calendar)。定时器事件有默认的业务日历,但也可以为每个定时器事件定义,单独定义业务日历。
...
定时器定义必须且只能包含下列的一种元素:
2022-12-06T12:13:14
P10D
R3/PT10H
请注意:定时器只有在异步执行器启用时才能触发(需要在flowable.cfg.xml中,将asyncExecutorActivate设置为true。因为默认情况下异步执行器都是禁用的)。
重要提示: BPMN错误与Java异常不是一回事。事实上,这两者毫无共同点。BPMN错误事件是建模业务异常(business exceptions)的方式。而Java异常会按它们自己的方式处理。
信号事件(signal event),是引用具名信号的事件。信号是全局范围(广播)的事件,并会被传递给所有激活的处理器(等待中的流程实例/捕获信号事件 catching signal events)。
使用signalEventDefinition元素声明信号事件定义。其signalRef属性引用一个signal元素,该signal元素需要声明为definitions根元素的子元素。下面摘录一个流程,使用中间事件(intermediate event)抛出与捕获信号事件。
...
...
两个signalEventDefinition引用同一个signal元素。
消息事件(message event),是指引用具名消息的事件。消息具有名字与载荷。与信号不同,消息事件只有一个接收者。
消息事件定义使用messageEventDefinition元素声明。其messageRef属性引用一个message元素,该message元素需要声明为definitions根元素的子元素。下面摘录一个流程,声明了两个消息事件,并由开始事件与消息捕获中间事件(intermediate catching message event)引用。
...
...
启动事件(start event)是流程的起点。启动事件的类型(流程在消息到达时启动,在指定的时间间隔后启动,等等),定义了流程如何启动,并显示为启动事件中的小图标。在XML中,类型由子元素声明来定义。
启动事件随时捕获:启动事件(保持)等候,直到特定的触发器被触发。
结束事件(end event)标志着流程或子流程中一个分支的结束。结束事件总是抛出(型)事件。这意味着当流程执行到达结束事件时,会抛出一个结果。结果的类型由事件内部的黑色图标表示。在XML表示中,类型由子元素声明给出。
边界事件(boundary event)是捕获型事件,依附在活动(activity)上。边界事件永远不会抛出。这意味着当活动运行时,事件将监听特定类型的触发器。当捕获到事件时,会终止活动,并沿该事件的出口顺序流继续。
所有的边界事件都用相同的方式定义:
边界事件由下列元素定义:
所有的捕获中间事件(intermediate catching events)都使用相同方式定义:
捕获中间事件由下列元素定义:
所有的抛出中间事件(intermediate throwing evnet)都使用相同方式定义:
抛出中间事件由下列元素定义:
说明:事件大类是这十种,细分小类有31种(查看的是v6.3.0版本,更新版本可能有新的事件)。
顺序流(sequence flow)是流程中两个元素间的连接器。在流程执行过程中,一个元素被访问后,会沿着其所有出口顺序流继续执行。这意味着BPMN 2.0的默认是并行执行的:两个出口顺序流就会创建两个独立的、并行的执行路径。
顺序流,用从源元素指向目标元素的箭头表示。箭头总是指向目标元素。
在顺序流上可以定义条件(conditional sequence flow)。当离开BPMN 2.0活动时,默认行为是计算其每个出口顺序流上的条件。当条件计算为true时,选择该出口顺序流。如果该方法选择了多条顺序流,则会生成多个执行,流程会以并行方式继续。
请注意:上面的介绍针对BPMN 2.0活动(与事件),但不适用于网关(gateway)。不同类型的网关,会用不同的方式处理带有条件的顺序流。
100 && order.price < 250}]]>
所有的BPMN 2.0任务与网关都可以使用默认顺序流(default sequence flow)。只有当没有其他顺序流可以选择时,才会选择默认顺序流作为活动的出口顺序流。流程会忽略默认顺序流上的条件。
活动的默认顺序流由该活动的default属性定义。下面的XML片段展示了一个排他网关(exclusive gateway),带有默认顺序流flow 2。只有当conditionA与conditionB都计算为false时,才会选择默认顺序流作为网关的出口顺序流。
${conditionA}
${conditionB}
网关(gateway)用于控制执行的流向(或者按BPMN 2.0的用词:执行的“标志(token)”)。网关可以消费(consuming)与生成(generating)标志。
排他网关(exclusive gateway),用于对流程中的决策建模。当执行到达这个网关时,会按照所有出口顺序流定义的顺序对它们进行计算。选择第一个条件计算为true的顺序流(当没有设置条件时,认为顺序流为true)继续流程。
请注意:使用排他网关时,只会选择一条顺序流。当多条顺序流的条件都计算为true时,会且仅会选择在XML中最先定义的顺序流继续流程。如果没有可选的顺序流,会抛出异常。
${input == 1}
${input == 2}
${input == 3}
并行网关(parallel gateway),它可以将执行分支(fork)为多条路径,也可以合并(join)多条入口路径的执行。
并行网关的功能取决于其入口与出口顺序流:
请注意:并行网关不计算条件。如果连接到并行网关的顺序流上定义了条件,会直接忽略该条件。
请注意:并行网关不需要“平衡”(也就是说,前后对应的两个并行网关,其入口/出口顺序流的数量不需要一致)。每个并行网关都会简单地等待所有入口顺序流,并为每一条出口顺序流创建并行执行,而不受流程模型中的其他结构影响。
可以把包容网关(inclusive gateway)看做排他网关与并行网关的组合。与排他网关一样,可以在包容网关的出口顺序流上定义条件,包容网关会计算条件。然而主要的区别是,包容网关与并行网关一样,可以同时选择多于一条出口顺序流。
包容网关的功能取决于其入口与出口顺序流:
简单的理解:包容网关有着和并行网关一样的功能,多条并行执行,有合并和分叉等,然后就加上计算顺序流的条件。
基于事件的网关(event-based gateway)提供了根据事件做选择的方式。网关的每一条出口顺序流都需要连接至一个捕获中间事件。当流程执行到达基于事件的网关时,与等待状态类似,网关会暂停执行,并且为每一条出口顺序流创建一个事件订阅。
请注意:基于事件的网关的出口顺序流与一般的顺序流不同。这些顺序流从不实际执行。相反,它们用于告知流程引擎:当执行到达一个基于事件的网关时,需要订阅什么事件。有以下限制:
“用户任务(user task)”用于对需要人工执行的任务进行建模。当流程执行到达用户任务时,会为指派至该任务的用户或组的任务列表创建一个新任务。
脚本任务(script task)是自动执行的活动。当流程执行到达脚本任务时,会执行相应的脚本。
脚本任务使用script与scriptFormat元素定义。
Java服务任务(Java service task)用于调用Java类。
有四种方法声明如何调用Java逻辑:
1)使用flowable:class属性提供全限定类名(fully qualified classname),指定流程执行时调用的类。
2)也可以使用解析为对象的表达式。该对象必须遵循的规则,与使用flowable:class创建的对象规则相同
delegateExpressionBean是一个实现了JavaDelegate接口的bean,定义在Spring容器中。
3)使用flowable:expression属性指定需要计算的UEL方法表达式。(将在名为printer的对象上调用printMessage方法(不带参数)。)
也可以为表达式中使用的方法传递变量。
将在名为printer的对象上调用printMessage方法。传递的第一个参数为DelegateExecution,名为execution,在表达式上下文中默认可用。传递的第二个参数,是当前执行中,名为myVar变量的值。
4)可以使用flowable:expression属性指定需要计算的UEL值表达式。
会调用名为split的bean的ready参数的getter方法,getReady(不带参数)。该对象会被解析为执行的流程变量或(如果可用的话)Spring上下文中的bean。
Web服务任务(Web service task)用于同步地调用外部的Web服务。
Web服务任务与Java服务任务图标一样。
业务规则任务(business rule task)用于同步地执行一条或多条规则。Flowable使用名为Drools Expert的Drools规则引擎执行业务规则。目前,业务规则中包含的.drl文件,必须与定义了业务规则服务并执行规则的流程定义一起部署。这意味着流程中使用的所有.drl文件都需要打包在流程BAR文件中,与任务表单等类似。
Flowable让你可以通过自动的邮件服务任务(email task),增强业务流程。可以向一个或多个收信人发送邮件,支持cc,bcc,HTML文本,等等。请注意邮件任务不是BPMN 2.0规范的“官方”任务(所以也没有专用图标)。因此,在Flowable中,邮件任务实现为一种特殊的服务任务。
下面的XML代码片段是使用邮件任务的示例。
Hello ${male ? 'Mr.' : 'Mrs.' } ${recipientName},
As of ${now}, your order has been processed and shipped.
Kind regards,
TheCompany.