Activiti工作流学习-----基于5.19.0版本(7)
八、BPMN 2.0流程图详解
BPMN 2.0的标准的出现是好事,用户不在被某个工作流开发商绑架或者在工作流中开发妥协,Activiti作为BPMN标准的一套解决方案,使得用户在选择工作流框架时可以平滑的迁移过渡。也有负面的不好的消息,就是BPMN标准是大量开会讨论和开发商妥协的结果(一般这是在做梦),所以用户在阅读BPMN规范会感觉到它太笨重了,Activiti开发工作流将用户体验放到第一位置,开发出了工作流设计插件。工作流官方推荐使用工作流设计插件。
8.1 事件(Event)
每个流程设计都有start event和end event,而在整个流程中发生的事件都是有event来表示。事件在设计面板中用圆圈表示,在BPMN 2.0中主要有两种事件:
- Catching:当流程执行到事件的时候, 它会等待被触发。而触发条件需要用户配置在这个圆圈图标的属性里面,和下面第二种圆圈图标外形上的区别是:Catching图标里面是空的,就是空圈。
- Throwing:当流程执行到事件的时候,它会立即触发,同样的触发器也需要配置在图标属性里面,和Catching图标不同是圆圈图标里面有东西是,黑色的。
总的来说,事件定义决定了事件的语义。如果没有事件定义,这个事件就不做什么特别的事情。 没有设置事件定义的开始事件不会在启动流程时做任何事情。如果给开始事件添加了一个事件定义 (比如定时器事件定义)我们就声明了开始流程的事件 "类型 " (这时定时器事件监听器会在某个时间被触发)。
8.1.1 定时器事件
定时器事件是根据指定的时间触发的事件。可以用于开始事件(start event), 中间事件(intermediate event)和边界事件(boundary event)。定时器事件必须含有下面一种属性的配置。
timeDate:指定ISO 8601格式的日期定时器激活。(至于ISO 8601日期格式可以详见百度:http://baike.baidu.com/view/931641.htm)
<timerEventDefinition>
<timeDate>2016-08-23T18:13:00</timeDate>
</timerEventDefinition>
timeDuration:定义定时器经过多少时间后激活。时间段也是取得ISO 8601格式,比如在一年三个月五天六小时七分三十秒内,可以写成P1Y3M5DT6H7M30S。
<timerEventDefinition>
<timeDuration>P10D</timeDuration>
</timerEventDefinition>
timeCycle:定义定时器重复间隔,在某些场景使用,比如周期性的启动流程,任务超时发送提醒。timeCycle的设置目前有两种方式:ISO 8601和Cron表达式(quartz任务调度框架提供的解决方案),activiti默认是使用ISO 8601。例如现在重复三次,每次间隔10小时:
<timerEventDefinition>
<timeCycle activiti:endDate="2016-08-22T16:42:11+00:00">R3/PT10H</timeCycle>
</timerEventDefinition>
<timerEventDefinition>
<timeCycle>R3/PT10H/${EndDate}</timeCycle>
</timerEventDefinition>
其中endDate是可选的配置,上面使用了两张方式加上了endDate, 定时器将会在指定的时间停止工作。
此外如果你使用Cron 表达式,可以这样写:
0 0/5 * * * ?
注意: 第一个数字表示秒,而不是像通常Unix cron中那样表示分钟。重复的时间周期能更好的处理相对时间,它可以计算一些特定的时间点 (比如用户任务的开始时间),而cron表达式可以处理绝对时间, 这对定时启动事件特别有用。
你可以使用表达式进行配置,在里面动态设置值,不过该值需要为ISO 8601或者(cron表达式)格式,
<boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport">
<timerEventDefinition>
<timeDuration>${duration}</timeDuration>
</timerEventDefinition>
</boundaryEvent>
定义器的执行有先决条件:async executor和job被启用定时器才会激活(例如在activiti.cfg.xml中配置了jobExecutorActivate或者asyncExecutorActivate为true)。
8.1.2 错误事件定时器
BPMN的错误是关于业务上面的异常处理,它和java代码上的异常是不同的,两者完全不同,比如这样配置一个错误事件:
<endEvent id="myErrorEndEvent">
<errorEventDefinition errorRef="myError" />
</endEvent>
8.1.3 信号事件
信号事件会引用一个命名的信号,所谓的信号作用在整个流程引擎全局范围内,会发送给所有活跃的处理器。信号事件在BPMN文件中是定义在signalEventDefinition中,其中的signalRef属性可以引用前面声明的signal,而signal在definitions的根节点中作为子元素,下面就是一个例子
<definitions... >
<!-- 声明signal -->
<signal id="alertSignal" name="alert" /> <process id="catchSignal">
<intermediateThrowEvent id="throwSignalEvent" name="Alert">
<!-- signal event definition -->
<signalEventDefinition signalRef="alertSignal" />
</intermediateThrowEvent>
...
<intermediateCatchEvent id="catchSignalEvent" name="On Alert">
<!-- signal event definition -->
<signalEventDefinition signalRef="alertSignal" />
</intermediateCatchEvent>
...
</process>
</definitions>
Throwing信号事件:在BPMN中配置或者用代码实现都可以发出信号,而使用代码可以这样子:
RuntimeService.signalEventReceived(String signalName);
RuntimeService.signalEventReceived(String signalName, String executionId);
这两个方法不同之处在于第一个方法发出全局的信号,第二个方法会指定execution发出信号。
Catching信号事件:被中间事件和边界事件捕获的事件。
前面第二个方法的executionId或者查询当前活跃的信号事件方法如下:
List<Execution> executions = runtimeService.createExecutionQuery()
.signalEventSubscriptionName("alert")
.list();
信号的作用范围:
默认的信号作用域是整个流程引擎,也就是说你可以throw一个信号在多个流程实例之间并发生作用。有时候我们需要作用范围仅仅是在发生事件的流程实例里,限制信号的作用范围,可以这样配置,不过它并不是BPMN2.0规范中的,是activiti独有的,其中activiti:scope的默认值是global。
<signal id="alertSignal" name="alert" activiti:scope="processInstance"/>
信号事件案例:这里我使用了Activiti Explorer在线流程图设计器设计了两张图,展示了信号交互。
第一张流程是从保险规则变动开始的,然后相关人员审批,如果同意后会发出保险条件发生改变的信号。
第二张流程中将在红框标识的地方会捕获(Catching)这个事件,使得保险合同在这时重新计算。
信号是通过广播传递给所有活跃的事件,但有时候我们并不是想要这种结果,譬如下图:
上面流程图的意思是执行“do something”任务时出现的错误,会被边界错误事件捕获, 然后使用信号传播给并发路径上的分支,进而中断"do something inparallel"任务, 但是,根据信号的广播含义,它也会传播给所有其他订阅了信号事件的流程实例,这就是我们不想要的。这时我们需要调用前面介绍触发信号的API的第二个方法进行手动关联。
8.1.4 消息事件
消息事件会引用已命名的消息。和信号不同的是,消息具有名称和内容,并且消息始终指定了单个的接收者。
消息事件定义在BPMN文件的messageEventDefinition元素中,其中messageRef属性值来自于message,至于message是配置在definitions的根元素里面。下面是一个例子:
<definitions id="definitions"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples"
xmlns:tns="Examples"> <message id="newInvoice" name="newInvoiceMessage" />
<message id="payment" name="paymentMessage" /> <process id="invoiceProcess"> <startEvent id="messageStart" >
<messageEventDefinition messageRef="newInvoice" />
</startEvent>
...
<intermediateCatchEvent id="paymentEvt" >
<messageEventDefinition messageRef="payment" />
</intermediateCatchEvent>
...
</process> </definitions>
抛出消息事件:Activiti作为嵌入式的引擎,它不会关注怎么接收消息,接收消息取决于你的环境和特定的平台,比如你可以连接到JMS消息队列或者执行WebService或REST请求,这是需要你的应用层架构中进行实现,Activiti只是其中一部分。
在你的应用里面收到消息,你需要处理它,如果是启动流程实例的消息,可以参考下面的API:
ProcessInstance startProcessInstanceByMessage(String messageName);
ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object> processVariables);
这些API允许使用引用的消息进行启动流程实例。如果流程实例需要接收这些消息,首先你需要关联指定流程实例和消息,然后触发处于等待的流程,使用RunTimeService可以触发基于消息的流程。
void messageEventReceived(String messageName, String executionId);
void messageEventReceived(String messageName, String executionId, HashMap<String, Object> processVariables);
查询订阅消息事件的流程定义:
对于start event的消息,消息事件关联到指定的流程定义,消息的订阅可以使用ProcessDefinitionQuery查询。
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.messageEventSubscription("newCallCenterBooking")
.singleResult();
对于明确的消息是对应一个流程的,所以查询结果一般是0个或者1个,如果是流程定义更新,那么方法返回最新的流程定义。
如果是中间消息事件,订阅的消息关联到特定的流程,我们可以使用ExecutionQuery进行查询:
Execution execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("paymentReceived")
.variableValueEquals("orderId", message.getOrderId())
.singleResult();
下面的实例通过两个不同的消息进行启动流程实例:
在某些需要多个start event启动流程实例需要统一的处理方式的时候是有用处的。
Activiti工作流学习-----基于5.19.0版本(7)的更多相关文章
- Activiti工作流学习-----基于5.19.0版本(8)
8.1.5 Start Event 继续上一篇的事件的分享笔记,Start Event指明该处是流程开始,至于开始事件的类型(消息到达开始,指定的事件循环开始等),定义如何开始是在开始事件圆圈图标里面 ...
- Activiti工作流学习-----基于5.19.0版本(2)
二.activiti.cfg.xml的其他bean节点配置 2.1 新特性:Job Executor和Async Executor 从5.17.0版本的activiti开始提供作业执行者(Job Ex ...
- Activiti工作流学习-----基于5.19.0版本(5)
五.与Spring集成 实际项目中一般都有Spring的身影,与Spring集成使得Activiti的实用性得到提高.activiti和Spring整合需要activiti-spring的jar在类路 ...
- Activiti工作流学习-----基于5.19.0版本(6)
七. BPMN的简介 读者了解到这里,应付一般的工作流开发已经足够了.此处应该有华丽的分割线,在工作流项目中核心开发人员主要是对工作流业务设计以及实现,而初级开发人员是对业务功能的代码实现.以后将主要 ...
- Activiti工作流学习-----基于5.19.0版本(1)
该版本的Activiti运行须知: 1.JDK 6+,Eclipse最好是Kepler以上版本. 2.试验功能都有EXPERIMENTAL标注,被标注的部分不应该视为稳定的. 有兴趣的同学可以去了解下 ...
- Activiti工作流学习-----基于5.19.0版本(4)
四.使用工作流开发 org.activiti.engine.ProcessEngine提供的Service作用在工作流引擎上面,如果所示是模仿一个公司简单的审批流程,你可以下载这个Demo:Activ ...
- Activiti工作流学习-----基于5.19.0版本(3)
前面关于eventType的属性值的配置简单的说了一下,activiti支持的值如下表所示:这是我摘抄的activiti官网的 Event 的名字 描述 Event的类名 ENGINE_CREATED ...
- Activiti工作流学习之流程图应用详解
Activiti工作流学习之流程图应用详解 1.目的 了解Activiti工作流是怎样应用流程图的. 2.环境准备2.1.相关软件及版本 jdk版本:Jdk1.7及以上 IDE:eclipse ...
- Activiti工作流学习之概述(一)
一.工作流介绍 我第一次听到这个词,是蒙逼的,再看百度百度,更傻眼了,完全说的不像人话啊,举几个生活中的例子,就明白多了比如:请假.报销等等,如果文字太过抽象,请看图: 二.工作流引擎 Process ...
随机推荐
- #pragma execution_character_set的意义
就是设置执行字符集,指示char的执行字符集是UTF-8编码.如果源文件中出现中文,必须要设置为 #if _MSC_VER >= 1600 #pragma execution_ch ...
- python通过代理刷网页点击量
python通过代理刷网页点击量 更新异常处理情况 @time 2013-0803 更新循环里计数问题和随机等待时间问题 #!/usr/bin/python #-*- coding:utf-8 -*- ...
- 【细说Java】Java的重写与隐藏
重写与隐藏,有些书上或介绍上可能名称不一样,但都大差不差.以前只了解重写,隐藏也听说过,但没有详细了解过,趁现在,整理一下这两方面的内容吧. 首先,先说一下概念方面的东西. 重写 重写:子类继承了父类 ...
- android仿京东、淘宝商品详情页上拉查看详情
话不多说,直接上干货,基本就是一个scrollview中嵌套两个scrollview或者webview;关键点事处理好子scrollview和父scrollview的触摸.滑动事件已达到想要的效果.大 ...
- 公告:本博客搬迁到:http://www.courtiercai.com/
公告: 您好,本人意见本博客搬迁到:http://www.courtiercai.com/.
- Kafka小记
kafka简介 kafka是由LinkedIn开发,主要是用来处理Linkedin的大面积活跃数据流处理(activity stream). 此类的数据经常用来反映网站的一些有用的信息,比如PV,页 ...
- (转)How to renew your Apple Push Notification Push SSL Certificate
转自:https://blog.serverdensity.com/how-to-renew-your-apple-push-notification-push-ssl-certificate/ It ...
- 【C#正则基础】正则表达式
1. 代表任意多个字符:(.*?)2. 代表网页里的<body>*</body>任意的标签内容,替换以后网页源码就只剩纯文本:<[^>]*>3. 代表网页中的 ...
- 常见算法:C语言求最小公倍数和最大公约数三种算法
最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们的公倍数,当中一个最小的公倍数是他们的最小公倍数,相同地,若干个整数公有的倍数中最小的正整数称为它们的最小公倍数,维基百科:定义点击打开链接 求 ...
- [Git] Automatically running tests before commits with ghooks
Wouldn't it be nice if everyone ran the tests before committing code? With ghooks, you can automatic ...