BPMN 标准
BPMN 2.0 是什么?
BPMN是英文Business Process Model and Notation的缩写,即业务流程模型注解, 是业务流程模型的一种规范图形注解。这个规范是由对象治理组(Object Management Group - OMG)保护的.与任何特定商业组织或工具是没有关系,无需为此付费.
BPMN 2.0即BPMN标准的 2.0 版本,以后版本是比较稳定的一个版本。容许在BPMN的图形和元素中增加准确的技术细节, 同时制订BPMN元素的执行语法。 通过应用XML语言来指定业务流程的可执行语法, BPMN标准曾经演变为业务流程的语言,能够执行在任何兼容BPMN 2.0的流程引擎中, 比方:Activiti、jBPM、Bonita、Camunda、ActiveVOS(商业),同时仍然能够应用弱小的图形注解。
倒退历史
BPMN 规范倒退版本历史如下:
BPMN1.x被大多数的建模工具和BPMS厂商所反对。然而, BPMN1.x只是一些建模符号,不反对元模型,不反对存储和替换,也不反对执行。那么围绕着BPMN1.x的存储、替换和执行,必然会产生新的竞争,这次的配角换成了XPDL、BPEL和BPDM。
XPDL作为WfMC(工作流治理联盟)提出的流程定义语言标准,自身就是一个元模型,能够存储,并且具备执行语义。现在有超过80个的不同公司的产品应用XPDL来替换流程定义,同时也有一些厂商在本人提供的BPMN工具中应用了XPDL作为替换和存储格局。
为了抗衡XPDL,OASIS组织(包含几个大的平台公司,Microsoft、 BEA、 IBM、 SAP 、Sun、Oracle)开发了BPEL标准。但BPMN到BPEL的转换存在着先天上的缺点,起因是BPMN是基于图的,而BPEL是基于块的。这个缺点导致有些BPMN建模的流程无奈映射到BPEL,两者的双向工程更是存在问题。这个缺点成为人们重复诟病的对象。许多反对BPEL的产品为了解决这一问题,不得不在用户建模时做出种种限度,让用户绘制不出无奈转换的模型。
而BPDM(业务流程定义元模型)则是OMG组织本人提出来解决BPMN存储和替换问题的标准。于2007年7月造成初稿,2008年7月被OMG最终采纳。BPDM是一个规范的概念定义,用来表白业务流程模型。元模型定义了用来替换的概念,关系和场景,能够使得不同的建模工具所建模进去的流程模型进行替换。BPDM超过了BPMN和BPEL所定义的业务流程建模的因素,它定义了编排和编制。
三者的竞争关系仿佛还将持续,但,BPMN2.0呈现了。BPMN2.0相比BPMN1.x,最重要的变动在于其定义了流程的元模型和执行语义,即它本人解决了存储、替换和执行的问题,BPMN由单纯的业务建模从新回归了它的根源,即作为一个对业务人员敌对的规范流程执行语言的图形化前端。BPMN2.0一出手,竞争就完结了,XPDL、BPEL和BPDM各自筹备回家钓鱼。看起来胜利者仿佛是BPMN,但看看BPMN2.0的领导者,就会发现最初的胜利者还是IBM,Oracle和SAP这些大厂商们,他们提交的草案明确要赋予BPMN2.0以执行语义,这迫使BPDM团队撤回了其提交,并将他们的提议与BPDM团队想法合并,这就是BPMN2.0最初内容的由来。
—— 摘自CSDN《BPMN2.0协定解析》
BPMNJS 简介
bpmn.js是一个BPMN 2.0渲染工具包和web建模器。它是用JavaScript编写的,将BPMN 2.0 图表嵌入在浏览器中, 并独立于后端, 这也使得将其嵌入到工作Web应用程序中变得很容易: 能够独立应用也能够集成到你的利用中。
该库的构建形式既能够是查看器,也能够是Web建模器
- 应用查看器(Viewer)将BPMN 2.0 嵌入到应用程序中,并用零碎数据丰盛其查看器。
- 应用建模器(Modeler) 在应用程序中创立BPMN 2.0 图表。
diagram-js 和bpmn-moddle
BPMN 2.0 中 bpmn-js次要依赖的库有两个: diagram-js 和bpmn-moddle.
bpmn.js是建设在 diagram-js和bpmn-moddle 两个库之上进行应用的。其中 diagram-js 是用来进行绘制形态和连贯。它为咱们提供了与这些图形元素交互的办法,以及帮忙用户构建弱小的BPMN 查看器等辅助工具. 对于建模它提供了上下文、调色板和重做/撤销等性能。bpmn-moddle 它容许咱们读取和写入合乎 BPMN 2.0 模式的XML 文档,并拜访图表上绘制的形态和连贯背地的BPMN相干信息。在这两个关联库之上,bpmn-js定义了BPMN的细节,例如外观、建模规定和工具(调色板)等等。
diagram-js(图表交互/建模)
模块零碎:在底层 diagram-js应用依赖注入来连贯和发现图表组件。在diagram-js的上下文中探讨模块时,指的是提供命名服务以及其实现的单元。"服务"是一个函数或实例,它能够应用其余服务在图表的上下文中做事。
上面是与生命周期事件挂钩的一个服务,它通过 eventBus 代理一个事件来做到能够处理事件的性能。如下:
const MyPlugin = (eventBus) => { eventBus.on('element.changed', (event) => { console.log('element ', event.element, 'changed'); });}MyPlugin.$inject = ['eventBus' ];
diagram-js是围绕许多根本服务构建的:
- Canvas- 提供用于增加和删除图形元素的 API;解决元素生命周期并提供 API 来缩放和滚动。
- EventBus- 事件总线模块来治理监听事件,相干方能够订阅各种事件,并在它们收回后对其采取行动。事件总线帮忙咱们解耦关注点并将性能模块化,以便新性能能够轻松地与现有行为挂钩。
- ElementFactory- 依据 diagram-js 的外部数据模型创立形态和连贯的工厂。
- ElementRegistry- 理解增加到图表中的所有元素,并提供 API 以通过id检索元素及其图形示意。
- GraphicsFactory- 负责创立形态和连贯的图形示意。理论的外观和感觉由渲染器定义,即DefaultRender在绘图模块外部。
diagram-js还提供一些辅助工具箱:
- CommandStack- 负责建模期间的重做和吊销。
- ContextPad- 提供围绕元素的上下文操作。
- Overlays- 提供用于将附加信息附加到图表元素的 API。
- Modeling- 提供用于更新画布上的元素(挪动、删除)的 API
- Palette - 左侧和右侧工具面板等等一些可扩大的辅助工具;
bpmn-moddle
bpmn-moddle是封装了BPMN 2.0模型,并提供了读写 BPMN 2.0 XML 文档工具。导入时 将 XML 文档解析为JavaScript 对象树,在建模时对该树进行编辑和验证,而后在保留图表时将其导出成 BPMN 2.0 XML协定文件。
bpmn-moddle 将 BPMN 2.0 标准增加为元模型,并为BPMN 2.0 模式验证提供了简略的接口,并提供如下API:
- formXML - 从给定的XML字符串创立 BPMN 树
- toXML - 将BPMN对象树写入BPMN 2.0 XML
BPMN 2.0 根本构造
事件
事件通常是与流动和网关一起工作的,事件是用在理论的每个业务流程中重要的组成模式。
事件让业务建模工具用很天然的形式形容业务流程,比方:
当我介绍到一个客户的准入信息,这个流程就启动.
如果两个小时内工作没有进行审核或者是进行相干操作,这个工作节点就超时揭示或者完结该流程
这就是通过事件进行驱动业务流程。事件又分很多种事件类型:
空启动事件
启动事件阐明流程的开始(或子流程),图形模式,看起来是一个圆(可能) 外部有一个小图标。图标指定了事件的事件类型 会在流程实例创立时被触发。
空启动事件画进去的是一个空圆,外部么有图标,意思是这个触发器是未知或者未指定。一个空开始事件的定义如下:
<startEvent id="start" name="myStart" />其中id是必须得,name是可选项
空完结事件
完结事件指定了流程实例中一个流程门路的完结。图形上,它看起来就是一个圆领有厚边框(可能)外部有小图标。图标指定了完结的时候会执行哪种操作。
空完结事件画进去是一个圆,领有厚边框,外部没有图标,这意味着当流程达到事件时,不会抛出任何信号。一个空完结事件的定义如下:
<endEvent id="end" name="myEnd" />
如下图是一个空的开始事件和空完结事件流程:
终止完结事件
终止和空完结事件的区别是 理论中流程的门路是如何解决的(或者应用BPMN 2.0的术语叫做token)。终止完结事件会完结整个流程实例,而空完结事件只会完结以后流程门路。他们都不会抛出任何事件 当达到完结事件的时候。一个终止完结事件的定义如下:
<endEvent id="terminateEnd" name="myTerminateEnd"> <terminateEventDefinition/></endEvent>
终止完结事件被描绘成完结事件一样(圆,厚边框),外部图标时一个残缺的圆。在上面的例子中,实现工作A 会完结流程实例,当实现实现工作B时只会完结达到完结事件 的流程门路,只剩下工作A关上。示例如下:
定时启动事件
定时启动事件用来示意流程须要在指定工夫启动。能够指定一个非凡的工夫点(比方,2010年10月10日下午5点),然而也能够用一个通常的工夫(比方,每个周五的中午)。
定时启动事件看起来是在圆圈中有一个表的图标。
应用定时启动事件,要增加一个timerEventDefinition元素在开始事件元素上面:
<startEvent name="Every Monday morning" id="myStart"> <timerEventDefinition/></startEvent>
图形如下:
两头事件
两头事件用来示意在流程执行过程中产生的事件(比方, 在流程启动之后,在它实现之前)。两头事件看起来就像一个有着双边线的圆圈,圆圈中的图标示意了事件的类型。
这儿有好多种两头事件类型,比方定时器事件,触发事件,流传事件,等等。 两头事件既能够抛出也能够捕捉:
抛出:当一个流程达到事件中,它会立即触发一个对应的触发器(一个激活,一个谬误,等等)。抛出事件用图形示意起来就是应用彩色填充的图标。
捕捉:当一个流程达到事件中,它会期待一个对应的触发器产生(一个谬误,一个定时器,等等)捕捉事件用图形示意起来就是没有应用彩色填充的图标(比方,外部是红色的)。
两头事件网关类型有如下几种:
| 捕捉事件 | 抛出事件 |
| --- | --- |
| 音讯两头捕捉事件 | 音讯两头抛出事件 |
| 定时两头捕捉事件 | 降级两头抛出事件 |
| 条件两头捕捉事件 | 弥补两头抛出事件 |
| 信号两头捕捉事件 | 信号两头抛出事件 |
| 链接两头捕捉事件 | |
程序流
程序流是事件,流动和网关之间的连线,显示为一条实线 带有箭头,在BPMN图形中(jPDL中等效的是transition)。每个程序流都有一个源头和一个指标援用,蕴含了流动,事件或网关的id。
<sequenceFlow id="GEF" name="GEF" sourceRef="工作A" targetRef="空终止完结事件" />
为了防止应用一个程序流,必须增加condition条件到程序流中。在运行时,只有当condition条件后果为true,程序流才会被执行。
为了给程序流增加condition条件,增加一个conditionExpression元素到程序流中。条件能够放在${}中。
<sequenceFlow id='111'> <conditionExpression xsi:type="tFormalExpression">${age >10}</conditionExpression></sequenceFlow><sequenceFlow id='22'> <conditionExpression xsi:type="tFormalExpression">${age <=10}</conditionExpression></sequenceFlow>
示例图如下:
留神,以后必须把xsi:type="tFormalExpression"增加到conditionExpression中。一个条件性的程序流能够看到一个小菱形图片 在程序流的终点。记住表达式始终能够定义在程序流上,然而一些构造不会解释它(比方,并行网关)。
流动(比方用户工作)和网关(比方惟一网关)能够用户默认程序流。默认程序流只会在流动或网关的 所有其余内向程序流的condition条件为false时才会应用。默认程序流图形像是程序流多了一个斜线标记。
网关
BPMN中的网关是用来管制流程中的流向的。更确切的是, 当一个token(BPMN 2.0中execution的概念注解)达到一个网关, 它会依据网关的类型进行合并或切分。网关描绘成一个菱形,应用一个外部图标来指定类型 (惟一,宽泛,其余)。
所有网关类型,有如下几种:
- 排他网关(惟一网关):也称专用网关, 只有一条门路会被选
当用作分支网关(将程序流分成多个门路,一分为二)时,专用网关能够具备2个或更多个传出门路,当某个变量条件返回“真”时,它会专门只指向下一个门路,当应用专用网关时,对于某个流程实例,运行时只能在多个门路中应用其中任意一条,这就是应用术语“独占或排他”的意思,查看每个门路上的变量条件,直到有一个门路的变量条件评估为真,一旦条件评估为真,流程就沿着为真的门路后退,并且不再查看其余路基的条件。
- 并行网关:所有门路会被同时抉择
- 容纳网关:能够同时执行多条线路,也能够在网关上设置条件
然而每个网关都能够设置gatewayDirection。上面的值能够应用:
- unspecificed (默认):网关可能领有多个 进入和外出程序流。
- mixed:网关必须领有多个 进入和外出程序流。
- converging:网关必须领有多个进入程序流, 然而只能有一个外出程序流。
- diverging:网关必须领有一个进入程序流, 和多个外出程序流。
比方上面的例子:并行网关的gatewayDirection属性为'converging',会领有json行为。
<parallelGateway id="test" name="GFE" gatewayDirection="converging" />
示例图如下:
1、排他网关(惟一网关)
惟一网关表白了一个流程中的惟一决策。会有一个内向程序流被应用,依据定义在程序流中的条件。示例图如下:
惟一网关须要所有内向程序流上都定义条件。 对这种规定一种例外是默认程序流。 应用default 属性来援用一个已存在的 程序流的id。这个程序流会被应用,当其余内向程序流的条件都执行为false时。
<exclusiveGateway id="decision" name="decideBasedOnAmountAndBankType" default="myFlow"/><sequenceFlow id="myFlow" name="fromGatewayToStandard" sourceRef="decision" targetRef="standard"></sequenceFlow>
惟一网关能够同时实现汇聚和发散性能。这个逻辑很容易了解: 对于每个达到这个网关的分支流程,都会抉择一个内向程序流来继续执行。 上面的图形在BPMN 2.0中是齐全非法的 (疏忽名称和申明的条件)。
2、并行网关
并行网关用来切分或同步相干的进入或外出程序流。
- 并行网关领有一个进入程序流的和多于一个的外出程序流叫做'并行切分或'AND-split'。所有外出程序流都会 被并行应用。留神:像标准中定义的那样, 外出程序流中的条件都会被疏忽。
- 并行网关领有多个进入程序流和一个外出程序流叫做'并行归并';所有进入程序流须要达到这个并行归并,在外向程序流应用之前。
<parallelGateway id="GFE" name="GFE" />
上面的图形显示了一个并行网关能够如何应用如下:
一个并行网关(其实是任何网关)能够同时领有切分和汇聚行为。 上面的图形在BPMN 2.0中是齐全非法的。 在流程启动之后,A和B工作都会激活。当A和B实现时,C,D和E 工作会被激活。示例图如下:
3、蕴含网关
一个蕴含网关 - 也叫做OR-gateway - 被用来进行“条件性”切分或汇聚程序流。它根本的行为就和一个并行网关一样,然而它也能够统计条件,在外出程序流上(切分行为)和计算,如果这儿有流程来到,能够达到网关(合并行为)。
蕴含网关显示为一个典型的网关图形,里边有一个圆圈(参考'OR'的语法)。 和惟一网关不同,所有条件表达式被执行(发散或切分行为)。对于每个表达式后果为true时,一个新的子流程分支就会被创立。没有定义条件的程序流会永远被抉择(比方一个子流程在这种状况下总是会被创立)。
一个收敛的蕴含网关(合并行为)有一个更艰难的执行逻辑。当一个执行(在BPMN 2.0的语法中叫做Token)达到一个合并蕴含网关。就会进行上面的检测(援用标准的文字):
对于每个空的进入程序流,这里没有Token在程序流的图形下面,比方,这里有一个没有间接的门路(由程序流组成)从Token到这个程序流,除非a) 门路达到了一个蕴含网关,或b) 门路达到了一个节点,间接到一个非空的 进入程序流的蕴含网关 "
简略来说:当一个流程达到了这个网关,所有的激活流程会被检测它们是否能够达到蕴含网关,只是统计程序流(留神:条件不会被执行!)。当蕴含网关被应用时,它通常用在一个切分/汇聚蕴含网关对中。在其余状况,流程行为足够简略,只有通过看图就能够了解了。
当然,不难想象状况,当流程切分和汇聚在简单的组合,应用大量的构造,其中包含蕴含网关。在那些状况,很可能呈现理论的流程行为可能与建模者的冀望不符。所以,当应用蕴含网关时,要留神通常的最佳实际是让蕴含网关成对应用。
上面的图形演示了如何应用蕴含网关。 (例子来自于Bruce Silver的"BPMN method and style")
工作
一个工作示意工作须要被内部实体实现, 比方人工或主动服务。在BPMN 2.0中,这里有很多工作类型,一些示意期待状态(比方,User Task一些示意主动流动(比方,Service Task。所以小心不要混同了工作的概念,在切换语言的时候。工作被描绘成一个圆角矩形,个别外部蕴含文字。工作的类型(用户工作,服务工作,脚本工作,等等)显示在矩形的左上角,用小图标区别。依据工作的类型,引擎会执行不同的性能。
1、用户工作(人工工作)
user task是典型的'人工工作', 理论中的每个workflow或BPMN软件中都能够找到。当流程执行达到这样一个user task时, 一个新人工工作就会被创立,交给用户的工作列表。和manual task的次要区别是 (也与人工工作对应)是流程引擎理解工作。 引擎能够跟踪竞争,调配,工夫,其余,这些不是manual task的状况。
user task描述为一个圆角矩形,在左上角是一个小用户图标。
user task被定义为上面的BPMN 2.0 XML:
<userTask id="myTask" name="My task" />
示例图如下:
依据标准,能够应用多种实现(WebService, WS-humantask,等等)。通过应用implementation属性。以后,只有规范的jBPM工作机制才能够用,所以这里(还)没有定义'implementation'属性的性能。
BPMN2.0标准蕴含了一些办法把任务分配给用户,组,角色等等。以后的BPMN 2.0jBPM实现容许应用一个resourceAssignmentExpression来分配任务,联合humanPerformer or PotentialOwner构造。这部分心愿在将来的版本里可能进一步演变。
potentialOwner用来在你心愿确定用户,组,角色的时候。这是一个task的候选人。参考上面的例子。这里的'My task'工作的候选人组是'management'用户组。也要留神,须要在流程内部定义一个资源,这样工作分配器能够援用到这个资源。实际上,任何流动都能够援用一个或多个资源元素。目前,只须要定义这个资源就能够了(因为它是标准中的一个必须的元素),然而在当前的公布中会进行增强(比方,资源能够领有运行时参数)。
2、服务工作
Service Task是一个主动流动,它会调用一些服务,比方web service,java service等等。以后jBPM引擎 只反对调用java service,然而web service的调用曾经在将来的版本中做了打算。
示例图如下:
定义一个服务工作须要好几行XML(这里就能够看到BPEL的影响力)。当然,在不久的将来,咱们心愿有工具能够把这部分大量的简化。一个服务工作须要如下定义:
<serviceTask id="MyServiceTask" name="My service task" implementation="Other" operationRef="myOperation" />
服务工作须要一个必填的id和一个可选的name。implementation元素是用来示意调用服务的类型。可选值是WebService, Other或者Unspecified。因为咱们只实现了Java调用,当初只能抉择Other。
服务工作将调用一个操作,operation的id 会在operationRef属性中援用。 这样一个操作就是上面实例的interface的一部分。每个操作都至多有一个输出信息,并且最多有一个输入信息。
<interface id="myInterface" name="org.jbpm.MyJavaServicek"> <operation id="myOperation2" name="myMethod"> <inMessageRef>inputMessage</inMessageRef> <outMessageRef>outputMessage</outMessageRef> </bpmn:operation></interface>
对于java服务,接口的名称用来指定java类的全类名。操作的名称用来指定将要调用办法名。输出/输入信息示意着java办法的参数/返回值,定义如下所示:
<message id="inputMessage" name="input message" structureRef="myItemDefinition1" />
3、脚本工作
脚本工作是一个主动流动,当达到这个工作的时候流程引擎会执行一个脚本。脚本工作应用形式如下:
<scriptTask id="scriptTask" name="Script Task" scriptLanguage="bsh"> <script><![CDATA[ for(int i=0; i < input.length; i++){ System.out.println(input[i] + " x 2 = " + (input[i]*2)); }]]> </script></scriptTask>
脚本工作,除了必填id和可选的name之外,还容许指定scriptLanguage和script。因为咱们应用了JSR-223(java平台的脚本语言)批改脚本语言就须要:
- 把scriptLanguage 属性批改为JSR-223兼容的名称
- 在classpath下增加JSR标准的ScriptEngine实现
下面的XML对应图形如下所示(增加了空开始和完结事件)。
图形如下:
4、手工工作
手工工作是一个由内部人员执行的工作,然而没有指定是一个BPM零碎或是一个服务会被调用。在真实世界里,有很多例子:装置一个电话零碎,应用定期邮件发送一封信,用电话分割客户,等等。
<manualTask id="myManualTask" name="Call customer" />
手工工作的指标更像 文档/建模揭示的,因为它对流程引擎的运行没有任何意义。因而,当流程引擎遇到一个手工工作时会简略略过。
图形如下:
5、接管工作
receive task是一个工作会等到内部音讯的到来。除了宽泛应用的web service用例,标准在其余环境中的应用也是一样的 web service用例还没有实现,然而receive task曾经能够在java环境中应用了。
receive task显示为一个圆角矩形(和task图形一样)在左上角有一个小信封的图标。
在java环境中,receive task没有其余属性,除了id和name(可选),行为就像是一个期待状态。为了在你的业务流程中应用期待状态,只须要退出如下几行:
<receiveTask id="receiveTask" name="wait" />
流程执行会在这样一个receive task中期待。流程会应用相熟的jBPM signal methods来继续执行。留神,这些可能在将来扭转,因为'signal'在BPMN 2.0中领有齐全不同的含意。
Execution execution = processInstance.findActiveExecutionIn("receiveTask");executionService.signalExecutionById(execution.getId());
图形如下:
数据(Data):
数据次要通过四种元素示意
- 数据对象(Data Objects)
- 数据输出(Data Inputs)
- 数据输入(Data Outputs)
- 数据存储(Data Stores)
连贯对象(Connecting Objects)
流对象彼此相互连贯或者连贯到其余信息的办法次要有三种
- 程序流:用一个带实心箭头的实心线示意,用于指定流动执行的程序
- 信息流:用一条带箭头的虚线示意,用于形容两个独立的业务参与者(业务实体/业务角色)之间发送和承受的音讯流动
- 关联:用一根带有线箭头的点线示意,用于将相干的数据、文本和其余人工信息与流对象分割起来。用于展现流动的输出和输入
泳道(Swimlanes)
通过泳道对次要的建模元素进行分组,将流动划分到不同的可视化类别中来形容由不同的参与者的责任与职责。
案例
参考资料
- https://www.omg.org/spec/BPMN/2.0/
- https://zhuanlan.zhihu.com/p/32625363
源码
本文示例源码:https://github.com/gfe-team/BPMN
团队介绍
高灯科技交易合规前端团队(GFE), 隶属于高灯科技(北京)交易合规业务事业线研发部,是一个富裕激情、充斥创造力、保持技术驱动全面成长的团队, 团队平均年龄27岁,有在各自畛域深耕多年的大牛, 也有刚刚毕业的小牛, 咱们在工程化、编码品质、性能监控、微服务、交互体验等方向踊跃进行摸索, 谋求技术驱动产品落地的主旨,打造欠缺的前端技术体系。
- 愿景: 成为最值得信赖、最有影响力的前端团队
- 使命: 保持客户体验第一, 为业务发明更多可能性
- 文化: 敢于承当、深刻业务、集思广益、简略凋谢
Github:github.com/gfe-team
团队邮箱:gfe@goldentec.com
作者:GFE-刘连军
著作权归GFE(高灯科技交易合规团队)所有。商业转载请分割作者取得受权,非商业转载请注明出处。