怎么解析一个bpmn强制关闭人工任务文件中的所有任务

京东购买包邮仅售59元!
关键词:Activiti任务节点属性扩展,Activiti权威指南
在实际的项目开发中,我们需要大量的使用任务节点也就是UserTask,如何默认的属性名称不够用,我们打算扩展UserTask任务节点的属性?这个时候该怎么做呢?相信这也是很多开发人员所面临的问题。本文的讲解基于MODELER设计器。
首先,我们看一下设计器中扩展的属性如下图所示:
由于公司需要使用岗位与角色,所以我们需要扩展一个属性支持岗位的配置以及使用。在项目中我们使用的departmentname属性值。接下来我们看一下如何在后台解析departmentname属性值并使用。
如果使用MODELER设计器,则部署流程资源的时候,需要分为如下几个步骤:
(1)获取前台保存的JSON. (2)调用BpmnJsonConverter将JSON转化为BpmnModel。 (3)部署。
我们使用的时候,仅在第2步骤进行处理即可。因为UserTask中扩展了属性,那么默认的任务节点JSON数据解析类UserTaskJsonConverter是不识别我们定义的departmentname属性,因此我们需要定义一个类替换UserTaskJsonConverter类,以此解析自定义的属性departmentname。
接下来,我们定义任务节点JSON解析类,如下所示:
public class HmUserTaskJsonConverter extends UserTaskJsonConverter {
public void convertToJson(BaseElement baseElement,
ActivityProcessor processor, BpmnModel model,
FlowElementsContainer container, ArrayNode shapesArrayNode,
double subProcessX, double subProcessY) {
super.convertToJson(baseElement, processor, model, container,
shapesArrayNode, subProcessX, subProcessY);
* 解析自定义的扩展属性信息
protected FlowElement convertJsonToElement(JsonNode elementNode,
JsonNode modelNode, Map shapeMap) {
FlowElement flowElement = super.convertJsonToElement(elementNode,
modelNode, shapeMap);
.....//书写解析属性的业务逻辑即可
ShareniuXML.writeXML(flowElement ,elementNode);
return flowE
public static void fillTypes(
Map& convertersToBpmnMap,
Map<class, Class& convertersToJsonMap) {
fillJsonTypes(convertersToBpmnMap);
fillBpmnTypes(convertersToJsonMap);
public static void fillJsonTypes(
Map& convertersToBpmnMap) {
convertersToBpmnMap.put(STENCIL_TASK_USER,
HmUserTaskJsonConverter.class);
public static void fillBpmnTypes(
Map<class, Class& convertersToJsonMap) {
convertersToJsonMap.put(UserTask.class, HmUserTaskJsonConverter.class);
}</class</class
上述类定义完毕之后,我们就需要在流程部署的时候使用该类,如下所示:
public void processModelStart(String modelId) throws Exception {
byte[] bpmnBytes =
String filename =
JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelId));
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
HmBpmnJsonConverter.getConvertersToBpmnMap().put(&UserTask&, HmUserTaskJsonConverter.class);
HmBpmnJsonConverter.getconvertersToJsonMap().put(UserTask.class, HmUserTaskJsonConverter.class);
BpmnModel model = jsonConverter.convertToBpmnModel(editorNode);
//filename = model.getMainProcess().getId() + &.bpmn20.xml&;
filename = model.getMainProcess().getName()+new Date().getTime()+&.bpmn20.xml&;
bpmnBytes = new BpmnXMLConverter().convertToXML(model);
System.out.println(new String(bpmnBytes));
ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
Model model1 = repositoryService.getModel(modelId);
//部署进去后
deploymentBuilder.addInputStream(filename,in);
deploymentBuilder.tenantId(model1.getTenantId());
Deployment deployment = deploymentBuilder.deploy();
model1.setDeploymentId(deployment.getId());
repositoryService.saveModel(model1);
部署流程资源,数据库act_ge_bytearray表中新增的数据如下:
& &process id=&a3bbe914e-2411-4cca-a2c9-f0d& isExecutable=&true&&
& & &startEvent id=&sid-B8-413E-AEB7-2C978C0DDFD3& name=&ddd&&&/startEvent&
& & &userTask id=&sid-2A2-4C70-942A-BF420DF934BF& name=&ddd& xmlns:shareniu=&/& shareniu:departmentname=&& shareniu:specialcheckperson=&&&&/userTask&
& & &sequenceFlow id=&sid-68-44DA-9D27-9DE0A949A17B& sourceRef=&sid-B8-413E-AEB7-2C978C0DDFD3& targetRef=&sid-2A2-4C70-942A-BF420DF934BF&&&/sequenceFlow&
& & &userTask id=&sid-D693DBA8-11C7--E888BC090370& name=&ddd& xmlns:shareniu=&/& shareniu:departmentname=&& shareniu:specialcheckperson=&&&&/userTask&
& & &sequenceFlow id=&sid-0FA-452E-ACD8-7FCD35050DEC& sourceRef=&sid-2A2-4C70-942A-BF420DF934BF& targetRef=&sid-D693DBA8-11C7--E888BC090370&&&/sequenceFlow&
& & &endEvent id=&sid-64D33C97-B433-41EC-BDF2-8A2EE58B4529&&&/endEvent&
& & &sequenceFlow id=&sid-B0999F7A-FACD-4F6F-9ACF-94B28BBDD138& sourceRef=&sid-D693DBA8-11C7--E888BC090370& targetRef=&sid-64D33C97-B433-41EC-BDF2-8A2EE58B4529&&&/sequenceFlow&
& &/process&
任务节点扩展的属性已经被我们成功写入到XML文件中了。
转载请注明: & Activiti任务节点属性扩展This work is licensed under a .
让您不再错过每一篇文章!
随笔分类(180)
随笔档案(86)
文章分类(9)
文章档案(28)
新闻档案(2)
Blog @ Other Site
Virtualization
积分与排名
阅读排行榜
评论排行榜怎么解析一个bpmn文件中的所以任务_百度知道
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。
怎么解析一个bpmn文件中的所以任务
我有更好的答案
在 BPMI Notation Working Group超过2年的努力,于2004年5月对外发布了BPMN 1.0 规范。因此BPMN的出现。而一个业务流程模型(Business Process Model)。后BPMI并入到OMG组织,弥补了从业务流程设计到流程开发的间隙。BPMN定义了一个业务流程图(Business Process Diagram)由BPMI(The Business Process Management Initiative)开发了一套标准叫业务流程建模符号(BPMN - Business Process Modeling Notation),OMG于2011年推出BPMN2.0标准,对BPMN进行了重新定义(Business Process Modeland Notation),该业务流程图基于一个流程图(flowcharting),直到最终用户的管理监控。BPMN也支持提供一个内部的模型可以生成可执行的BPEL4WS,该流程图被设计用于创建业务流程操作的图形化模型。BPMN的主要目标是提供一些被所有业务用户容易理解的符号,从创建流程轮廓的业务分析到这些流程的实现
为您推荐:
其他类似问题
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;BPMN:业务流程建模表示法。
一、流对象
流对象是定义业务流程的主要元素,是流程图的节点对象。有三种流对象:事件,活动,网关。
事件用来表明流程生存期间发生的事情。在BPMN 2.0中, 事件有两大分类:捕获(catching)&或&触发(throwing)&事件。
捕获(Catching):当流程执行到事件, 它会等待被触发。触发的类型是由内部图表或XML中的类型声明来决定的。 捕获事件与触发事件在显示方面是根据内部图表是否被填充来区分的(白色)。
触发(Throwing):当流程执行到事件, 会触发一个事件。触发的类型是由内部图表或XML中的类型声明来决定的。 触发事件与捕获事件在显示方面是根据内部图表是否被填充来区分的(黑色)。
事件定义决定了事件的语义。如果没有事件定义,这个事件就不做什么特别的事情。
定时器事件定义
定时器事件是由指定的时间触发的事件。可用于开始事件,中间事件或边界事件。
错误事件定义
错误事件是由指定错误触发的事件。
信号事件是引用一个命名信号的事件。信号是全局范围的事件(广播语义)。 会发送给所有激活的处理器。
消息事件定义
消息事件是引用一个命名消息的事件。每个消息都有名称和内容。与信号不同,消息事件总会直接发送给一个接收者。
开始事件表明流程在哪里开始。开始事件的类型(流程在接收事件时启动, 还是在指定时间启动,等等),定义了流程如何启动。 在XML中,这些类型是通过声明不同的子元素来区分的。
开始事件都是捕获事件: 最终这些事件都是(一直)等待着,直到对应的触发时机出现。
空开始事件
空开始事件技术上意味着没有指定启动流程实例的触发条件。&也就是说引擎不能预计什么时候流程实例会启动。 空开始事件用于,当流程实例要通过API启动的场景, 通过调用startProcessInstanceByXXX方法。
ProcessInstance processInstance = runtimeService.startProcessInstanceByXXX();
注意:&子流程总是有一个空开始事件。
定时开始事件
定时开始事件用来在指定的时间创建流程实例。 它可以用于只启动一次的流程和在特定时间间隔启动多次的流程。
注意:子流程不能使用定时开始事件。
注意:定时开始事件在流程发布后就会开始计算时间。 不需要调用startProcessInstanceByXXX,虽然也可以调用启动流程的方法, 但是那会导致调用startProcessInstanceByXXX时启动过多的流程。
注意:当包含定时开始事件的新版本流程部署时, 对应的上一个定时器就会被删除。这是因为通常不希望自动启动旧版本流程的流程实例。
消息开始事件
消息开始事件可以使用一个命名的消息来启动流程实例。 这样可以帮助我们使用消息名称来选择正确的开始事件。
在部署包含一个或多个消息开始事件的流程定义时,需要考虑下面的条件:
消息开始事件的名称在给定流程定义中不能重复。流程定义不能包含多个名称相同的消息开始事件。 如果两个或以上消息开始事件应用了相同的事件,或两个或以上消息事件引用的消息名称相同,activiti会在发布流程定义时抛出异常。
消息开始事件的名称在所有已部署的流程定义中不能重复。 如果一个或多个消息开始事件引用了相同名称的消息,而这个消息开始事件已经部署到不同的流程定义中, activiti就会在发布时抛出一个异常。
流程版本:在发布新版本的流程定义时,之前订阅的消息订阅会被取消。 如果新版本中没有消息事件也会这样处理。
信号开始事件
信号开始事件,可以用来通过一个已命名的信号来启动一个流程实例。 信号可以在流程实例内部使用“中间信号抛出事务”触发, 也可以通过API(runtimService.signalEventReceivedXXX&方法)触发。两种情况下, 所有流程实例中拥有相同名称的信号开始事件都会启动。
注意,在两种情况下,都可以选择同步或异步的方式启动流程实例。
必须向API传入signalName, 这是signal元素的name属性值, 它会被signalEventDefinition的signalRef属性引用。
错误开始事件
错误开始事件可以用来触发一个事件子流程。&错误开始事件不能用来启动流程实例。
错误开始事件总是中断。
结束事件表示(子)流程(分支)的结束。 结束事件都是触发事件。 这是说当流程达到结束事件,会触发一个结果。 结果的类型是通过事件的内部黑色图标表示的。 在XML内容中,是通过包含的子元素声明的。
空结束事件
空结束事件意味着到达事件时不会指定抛出的结果。 这样,引擎除了结束当前执行的分支,不会做其他事情。
错误结束事件
当流程执行到错误结束事件, 流程的当前分支就会结束,并抛出一个错误。 这个错误可以被对应的中间边界错误事件捕获。 如果找不到匹配的边界错误事件,就会抛出一个异常。
终止结束事件
当到达终止结束事件时,当前流程实例或子流程将终止。从概念上讲,当执行到达终止结束事件时,第一个作用范围(流程或子流程)将被确定并结束。注意在BPMN 2.0,子流程可以是嵌入的子流程,调用活动,事件子流程或事务子流程。本规则一般适用于:比如有多实例调用活动或嵌入的子流程,只有范围内的实例将结束,其他实例和流程实例都不受影响。
取消结束事件
取消结束事件只能与BPMN事务子流程结合使用。 当到达取消结束事件时,会抛出取消事件,它必须被取消边界事件捕获。 取消边界事件会取消事务,并触发补偿机制。
边界事件都是捕获事件,它会附在一个活动上。 (边界事件不可能触发事件)。这意味着,当活动运行时, 事件会监听对应的触发类型。 当事件被捕获,活动就会中断, 同时执行事件的后续连线。
边界事件是附着在活动上的捕获事件(边界事件决不能触发)。这意味着,当活动运行时,事件会监听某种类型的触发。当事件被捕获,活动就会中断,跟随事件流出的序列流继续执行。
定时边界事件
定时边界事件充当秒表和闹钟。当执行到达附在边界事件的活动时,定时器就启动了。当定时器触发(例如在指定间隔之后),活动中断,跟随边界事件的流出继续执行。
错误边界事件
错误边界事件,它会捕获活动范围内抛出的错误。
定义一个错误边界事件,大多用于内嵌子流程, 或调用活动,对于子流程的情况,它会为所有内部的活动创建一个作用范围。 错误是由错误结束事件触发的。 这个错误会传递给上层作用域,直到找到一个错误事件匹配的边界错误事件。
当捕获了错误事件时,边界事件绑定的活动就会销毁, 也会销毁内部所有的执行分支 (比如,同步节点,内嵌子流程,等等)。 流程执行会沿着边界事件的流出序列流继续执行。
信号边界事件
信号边界事件, 它会捕获一个命名的信号。
注意:与错误边界事件等其他事件不同,信号边界事件不仅捕获附加在其作用域上的信号事件。相反,信号事件具有全局范围(广播语义),这意味着信号可以从任何位置触发,甚至来自不同的流程实例。
注意:与其他事件不同,如错误事件,信号在被捕获时不会被消费。如果有两个活动的信号边界事件捕获相同的信号事件,则触发两个边界事件,即使它们是不同流程实例的一部分。
消息边界事件
消息边界事件,它会捕获一个命名的消息。
取消边界事件
取消边界事件, 当事务取消时触发。当取消边界事件触发时,首先中断当前作用域的所有执行。 然后开始补偿事务内的所有激活的补偿边界事件。 补偿是同步执行的。例如,离开事务栈,边界事务会等待补偿执行完毕。 当补偿完成后,事务子流程会沿着取消边界事件的流出序列流继续执行。
注意:每个事务子流程只能有一个取消边界事件。
注意:如果事务子流程包含内嵌子流程,补偿只会触发已经成功完成的子流程。
注意:如果取消边界子流程对应的事务子流程配置为多实例, 如果一个实例触发了取消,就会取消所有实例。
补偿边界事件
补偿触发时,补偿边界事件对应的补偿处理器会调用相同次数,根据它对应的节点的成功次数。
如果补偿边界事件关联到多实例节点, 补偿事件会订阅每个实例。
如果补偿边界事件关联的节点中包含循环, 补偿事件会在每次节点执行时进行订阅。
如果流程实例结束,订阅的补偿事件都会结束。
补偿边界事件,可用于将补偿处理程序附加到活动。
补偿边界事件必须直接引用一个补偿处理程序。
补偿边界事件与其他边界事件有不同的激活策略。其他边界事件,例如信号边界事件,在它们连接到的活动开始时被激活。当活动结束时,它们将被停用,相应的事件订阅也被取消。补偿边界事件是不同的。当附加的活动成功完成时,补偿边界事件被激活。此时,将创建对应于补偿事件的订阅。当触发补偿事件或相应的流程实例结束时,订阅将被删除。由此,它遵循:
当触发补偿时,与补偿边界事件相关联的补偿处理程序被调用的次数与所附的活动成功完成的次数相同。
如果将补偿边界事件附加到具有多个实例特性的活动中,则为每个实例创建补偿事件订阅。
如果将补偿边界事件附加到包含在循环中的活动中,则每次执行活动时都会创建补偿事件订阅。
如果流程实例结束,则取消对补偿事件的订阅。
注:补偿边界事件不支持内嵌子流程。
中间捕获事件
所有中间捕获事件都使用同样的方式定义:
&intermediateCatchEvent id="myIntermediateCatchEvent" &
&XXXEventDefinition/&
&/intermediateCatchEvent&
中间捕获事件的定义包括
唯一标识(流程范围内)
一个结构为XXXEventDefinition的XML子元素 (比如TimerEventDefinition等) 定义了中间捕获事件的类型。参考特定的捕获事件类型, 获得更多详情。
定时中间捕获事件
定时中间事件充当秒表。当执行到达捕获事件活动时,启动定时器。当定时器触发(例如在指定的间隔之后),则跟随定时中间事件流出的序列流继续执行。
信号中间捕获事件
信号中间捕获事件,它会捕获一个命名的信号。
消息中间捕获事件
消息中间捕获事件,它会捕获一个命名的消息。
中间触发事件
所有中间触发事件的定义都是同样的:
&intermediateThrowEvent id="myIntermediateThrowEvent" &
&XXXEventDefinition/&
&/intermediateThrowEvent&
中间触发事件定义包含
唯一标识(流程范围)
使用格式为XXXEventDefinition的XML子元素 (比如signalEventDefinition等) 定义中间触发事件的类型。 参考对应触发事件的类型,了解更多信息。
中间触发空事件
引擎不会为这个事件做任何事情, 它直接通过。
信号中间触发事件为定义的信号触发一个信号事件。
补偿中间触发事件
用于触发补偿。
活动是在业务流程执行过程中执行的工作。活动有两种类型:任务和子流程。
java服务任务
web service 任务
业务规则任务
java接收任务
执行监听器
任务监听器
多实例(循环)
补偿处理器
事件子流程
事务子流程
调用活动(子流程)
用于控制业务流程的分支与合并。
基于事件网关
二、连接对象
连接对象用来把各个流对象或流对象与其他信息连接起来。有三种连接对象:序列流,消息流,关联。
序列流表示流对象的先后执行顺序。
条件序列流
可以为序列流定义一个条件。离开一个活动时,默认会计算流出序列流的条件。如果条件结果为true,就会选择流出序列流继续执行。当多条序列流被选中时, 就会创建多条分支, 流程会以并行方式继续执行。
默认序列流
所以任务和网关都可以设置一个默认序列流。
消息流表示业务参与者之间发送和接收的消息流动。
关联用于将相关的数据、文本和其它人工信息与流对象联系起来。
泳道用于描述不同业务参与者的功能和职责。泳道包含两种:池和道。
池用于描述业务流程的一个参与者,可以看做是将一系列活动区别于其它池的一个容器。
池与池之间的交互只能使用消息流表示。
道就是在池里面再细分,可以是垂直的也可以是水平的。道也是用于组织和分类活动。
四、人工制品
人工制品作为信息备注,添加到建模的业务流程上下文中,便于人员理解。有三种人工制品:数据对象,组,注释。
数据对象用来表示一个活动如何产生和使用数据的,它们通过关联与活动连接起来。
组用于记录或分析的目的,但不影响序列流。
注释是建模人员为业务流程的读者提供附加文本信息的机制。
阅读(...) 评论()BPMN2新规范与Activiti5
我的图书馆
BPMN2新规范与Activiti5
什么是BPMN、Workflow?
BPM(Business Process Management)——“通过建模、自动化、管理和优化流程,打破跨部门跨系统业务过程依赖,提高业务效率和效果”。
Workflow——“全部或者部分由计算机支持或自动处理的业务过程”(工作流管理联盟WfMC组织对工作流概念的经典定义)
BPM基本内容是管理既定工作的流程,通过服务编排,统一调控各个业务流程,以确保工作在正确的时间被正确的人执行,达到优化整体业务过程的目的。BPM概念的贯彻执行,需要有标准化的流程定义语言来支撑,使用统一的语言遵循一致的标准描述具体业务过程,这些流程定义描述由专有引擎去驱动执行。这个引擎就是工作流引擎,它作为BPM的核心发动机,为各个业务流程定义提供解释、执行和编排,驱动流程“动“起来,让大家的工作“流”起来,为BPM的应用提供基本、核心的动力来源。
现实工作中,不可避免的存在跨系统跨业务的情况,而大部分企业在信息化建设过程中是分阶段或分部门(子系统)按步实施的,后期实施的基础可能是前期实施成果的输出,在耦合业务实施阶段,相同的业务过程可能会在不同的实施阶段重用,在进行流程梳理过程中,不同的实施阶段所使用的流程描述语言或遵循的标准会有所不同(服务厂商不同),有的使用WfMC的XPDL,还有些使用BPML、BPEL、WSCI等,这就造成流程管理、业务集成上存在很大的一致性、局限性,提高了企业应用集成的成本。
BPMN2.0规范的引入
遵循BPMN2.0新规范的工作流产品能很大程度上解决此类问题。BPMN2.0相对于旧的1.0规范以及XPDL、BPML及BPEL等最大的区别是定义了规范的执行语义和格式,利用标准的图元去描述真实的业务发生过程,保证相同的流程在不同的流程引擎得到的执行结果一致。BPMN2.0对流程执行语义定义了三类基本要素,它们是日常业务流程的“三板斧”:
Activities(活动)——在工作流中所有具备生命周期状态的都可以称之为“活动”,如原子级的任务(Task)、流向(Sequence Flow),以及子流程(Sub-Process)等
Gateways(网关)——顾名思义,所谓“网关”就是用来决定流程流转指向的,可能会被用作条件分支或聚合,也可以被用作并行执行或基于事件的排它性条件判断
Events(事件)——在BPMN2.0执行语义中也是一个非常重要的概念,像启动、结束、边界条件以及每个活动的创建、开始、流转等都是流程事件,利用事件机制,可以通过事件控制器为系统增加辅助功能,如其它业务系统集成、活动预警等
这三类执行语义的定义涵盖了业务流程常用的Sequence Flow(流程转向)、Task(任务)、Sub-Process(子流程)、Parallel Gateway(并行执行网关)、ExclusiveGateway(排它型网关)、InclusiveGateway(包容型网关)等常用图元,如图1:
图1:BPMN2.0三类基本执行语义要素
现实业务所有的业务环节都离不开Activities、Gateways和Events,无论是简单的条件审批还是复杂的父子流程循环处理,在一个流程定义描述中,所有的业务环节都离不开Task、Sequence Flow、Exclusive Gateway、Inclusive Gateway(如图1中右侧绿色标记所示元素),其中Task是一个极具威力的元素,它能描述业务过程中所有能发生工时的行为,它包括User Task、Manual Task、Service Task、Script Task等,可以被用来描述人机交互任务、线下操作任务、服务调用、脚本计算任务等常规功能。
User Task:生成人机交互任务,主要被用来描述需要人为在软件系统中进行诸如任务明细查阅、填写审批意见等业务行为的操作,流程引擎流转到此类节点时,系统会自动生成被动触发任务,须人工响应后才能继续向下流转。常用于审批任务的定义。
Manual Task:线下人为操作任务,常用于为了满足流程图对实际业务定义的完整性而进行的与流程驱动无关的线下任务,即此类任务不参与实际工作流流转。常用于诸如物流系统中的装货、运输等任务的描述。
Service Task:服务任务,通常工作流流转过程中会涉及到与自身系统服务API调用或与外部服务相互调用的情况,此类任务往往由一个具有特定业务服务功能的Java类承担,与User Task不同,流程引擎流经此节点会自动调用Java类中定义的方法,方法执行完毕自动向下一流程节点流转。另外,此类任务还可充当“条件路由”的功能对流程流转可选分支进行自动判断。常用于业务逻辑API的调用。
Script Task:脚本任务,在流程流转期间以“脚本”的声明或语法参与流程变量的计算,目前支持的脚本类型有三种:juel(即JSP EL)、groovy和javascript。在Activiti5.9中新增了Shell Task,可以处理系统外部定义的Shell脚本文件,也与Script Task有类似的功能。常用于流程变量的处理。
BPMN2.0流程示例
BPMN2.0为所有业务元素定义了标准的符号,不同的符号代表不同的含义,以OA应用中请假流程为例,使用标准的BPMN2.0图元定义示意如图2:
图2:BPMN2.0请假流程定义
在上述的流程示意图中,所涉及到的执行语义图元主要有表1中的8类:
表1:请假流程所用图元
除了上述Start Event、User Task、Exclusive Gateway、Parallel Gateway、Service Task、End Event标准的BPMN2.0图元外,上述流程图还使用了Lane Set(业务部门、人力资源部、考勤系统),分别表示流程活动所涉及到的部门或角色,Lane的概念和jBPM4中“泳道”的概念一样,都用来表示同一类相似任务的归属者。
应用BPMN2.0标准的一个最显著的特色是,不同阶段的人员,无论是需求分析、概要设计、详细设计或是具体的业务实现,都可在一个流程图上开展工作,避免业务理解存在偏差。一个系统的实现,需求分析人员可以利用BPMN2.0标准图元草绘一下搜集到的需求;然后可以拿给设计人员,讨论出具体的业务需求进行功能设计,由设计人员在草图的基础上逐步细化,并得到需求人员的认同;设计人员又将细化后的流程图交给开发人员,罗列要实现的功能点,指出流程图上各活动节点所具备的行为,设计人员与开发人员依据此图达成共识,进入具体的开发阶段;如果后期请假流程发生更改,仍然是在现有流程图上更改,随着项目的推进,流程图也在不断的演进,但至始至终,项目受众都使用同一个流程图交流,保障需求理解的一致性,一定程度上推动了项目的敏捷性。
Activiti5支持最新的BPMN2.0规范
作为支持最新BPMN2.0规范的开源工作流引擎Activit5,实现了对规范的绝大多数图元的定义,能够满足企业工作流的各种复杂应用。它是一个无侵入的、支持嵌入式和独立部署的开源工作流引擎,是Tom Bayen离开jBoss加入Alfresco公司后的另立山头之作,共同开发Activit5的除了Alfresco外还有SpringSource、MuleSoft、Salves、FuseSource、Signavio等公司。从Activiti5.0到当前的5.9(今年3月份发布),版本更新迭代速度很快,新版本功能稳定,性能良好,为开源社区提供了商业工作流之外非常具有竞争力的选择。
与jBPM5的差别
值得一提的是,Activiti5与jBPM5都属于业界优秀的开源工作流引擎,都支持BPMN2.0最新规范,均基于Apache License,符合J2EE规范,提供工作流建模、执行以及对流程生命周期过程监控。但两者设计理念和技术组成却有很大不同,见下表2:
数据库持久层ORM
Hibernate3
持久化标准
MyBatis机制/Spring事务控制
Bitronix,基于JTA事务管理
数据库连接方式
Jdbc/DataSource
Jdbc/DataSource
支持数据库
Oracle、SQL Server、MySQL等多数数据库
Oracle、SQL Server、MySQL等多数数据库
Command模式、观察者模式等
内部服务通讯
Service间通过API调用
基于Apache Mina异步通讯
SOAP、Mule、RESTful
支持的流程格式
BPMN2、xPDL、jPDL等
目前仅只支持BPMN2 xml
PVM(流程虚拟机)
jBPM3、jBPM4
Drools Flow
表2:Activiti5与jBPM5技术组成
Activiti5使用Spring进行引擎配置以及各个Bean的管理,综合使用IoC和AOP技术,使用CXF作为Web Services实现的基础,使用MyBatis进行底层数据库ORM的管理,预先提供Bundle化包能较容易的与OSGi进行集成,通过与Mule ESB的集成和对外部服务(Web Service、RESTful等)的接口可以构建全面的SOA应用;jBPM5使用jBoss.org社区的大多数组件,以Drools Flow为核心组件作为流程引擎的核心构成,以Hibernate作为数据持久化ORM实现,采用基于JPA/JTA的可插拔的持久化和事务控制规范,使用Guvnor作为流程管理仓库,能够与Seam、Spring、OSGi等集成。
需要指出的是Activiti5是在jBPM3、jBPM4的基础上发展而来的,是原jBPM的延续,而jBPM5则与之前的jBPM3、jBPM4没有太大关联,且舍弃了备受推崇的PVM(流程虚拟机)思想,转而选择jBoss自身产品Drools Flow作为流程引擎的核心实现,工作流最为重要的“人机交互”任务(类似于审批活动)则由单独的一块“Human Task Service”附加到Drools Flow上实现,任务的查询、处理等行为通过Apache Mina异步通信机制完成。
优劣对比:
从技术组成来看,Activiti最大的优势是采用了PVM(流程虚拟机),支持除了BPMN2.0规范之外的流程格式,与外部服务有良好的集成能力,延续了jBPM3、jBPM4良好的社区支持,服务接口清晰,链式API更为优雅;劣势是持久化层没有遵循JPA规范。
jBPM最大的优势是采用了Apache Mina异步通信技术,采用JPA/JTA持久化方面的标准,以功能齐全的Guvnor作为流程仓库,有RedHat(jBoss.org被红帽收购)的专业化支持;但其劣势也很明显,对自身技术依赖过紧且目前仅支持BPMN2。
Activiti5设计模式
命令模式能将命令的发出与执行分开,委派给不同的对象,每一个命令都代表一个指令,其最大的好处是提供了一个公共接口,使得用户可以用同一种方式调用所有的事务,同时也易于添加新事务以扩展系统。
Activiti5大量采用了命令模式,在流程运行期间,所有的指令执行(比如流程部署、流程流转、获取任务等)都使用此模式实现, 其中涉及到四个重要的概念:
Command:Activiti5的命令定义接口,仅有一个execute方法,所有运行期要执行的指令都要实现该接口,定义要执行的具体行为。
CommandContext:命令执行的上下文环境,每个Command的执行都依赖其上下文环境,CommandContext创建了命令执行期间的引擎会话与数据库会话,每个CommandContext都是一个单独的ThreadLocal,执行期间不会受其它线程干预,是线程安全的。
CommandExecutor:命令执行器,负责执行所有的运行时Command。引擎中各项指令的执行(即命令的产生者可能来源于多种对象)都托CommandExecutor处理,仅有一个接口方法:execute(Command command)。 ActivityBehavior:活动行为定义,用于定义BPMN2.0执行语义层的各图元在流程引擎的行为,或称之为所具备的图元特征。与Command的概念类似,仅仅描述“待执行”的指令是什么,会发生什么样的行为,但真正要执行时则由引擎负责驱动。
人机交互任务是业务流程应用中最常用的业务类型,以BPMN2.0中定义的“Task”这个典型元素说明一下命令模式在Activiti5中的应用:
Activiti5针对BPMN2.0的Task Element定义了Task接口,并依据Semantic.xsd执行语义定义了相关任务元素所具有的行为特性,此行为特性通过setActivityBehavior方法进行行为与元素的绑定,这些Behavior在流程引擎驱动流转到活动节点时将被触发,通过execute(ActivityExecution execution)执行ActivityBehavior中指定的操作;
每个活动有若干个Command与之对应,比如ClaimTaskCmd、CompleteTaskCmd、DelegateTaskCmd、SaveTaskCmd、DeleteTaskCmd等,分别表示任务的领取、完成、转交、保存、删除等,这些操作指令的执行结果通过命令执行上下文(CommandContext)得到DAO层的TaskManager将任务对象的变更持久化到数据库中;
引擎不关心要执行什么,凡是实现了Command接口的类都可以通过CommandExecutor执行,除了引擎提供的这些原生的任务指令外,如果业务系统有额外的特性化操作,也可以自定义一组Command,在Command.execute()中自由调用外部服务、发送手机短信、附加任务属性、调用DAO操作数据库等,封装完毕后交由引擎去执行,即可得到希望的结果。同样,如果在业务系统中需要自定义BPMN元素或属性,仅需同步增加ActivityBehavior接口的实现,在解析流程定义文件时将自定义的行为实现与元素(属性)帮定,并缓存之,待引擎驱动到达节点时自动执行。在ActivityBehavior. execute()中依然可以调用各种各样的API已实现特定的业务目的。
此处需要注意的是,Activiti5的CommandContext是包含事务处理的,在每次关闭上下文环境时,会执行事务的提交,但在实际业务系统中,业务事务、引擎事务以及数据库事务应该是被统一到一个事务中去管理,这就需要将Activiti5的事务与业务系统的事务合并。Activiti5通过Spring注入提供了该方式的可行性,引擎内部的事务控制可以委托给业务层去处理,在初始化引擎配置时,将业务系统中定义的DataSource和TransactionManager传递给流程配置的dataSource、transactionManager属性后,Activiti5内部会使用Spring提供的TransactionAwareDataSourceProxy来封装传进来的DataSource,并利用外部的事务管理来接管Activiti5的事务控制,确保了从该DataSource获取的数据库连接与 Spring 定义的事务能够完美地结合,从而实现业务系统与引擎系统事务的集成。
Activiti5对BPMN2.0执行语义的解析
Activiti5通过BpmnParse使用SAX方式进行BPMN2.0 XML流程定义文件的解析,是解析的核心类,从根节点开始解析,依次对DefinitionsAttributes、Imports、ItemDefinitions、Messages、Interfaces、和Errors以及ProcessDefinitions各个元素进行解析(以上均是标准的BPMN2.0元素),最后解析负责流程可视化定义的DiagramInterchangeElements元素。每解析一个元素都会判断元素类型,如果是“活动“类型(包括Task、Gateway等),则会为活动设置相应的ActivityBehavior,同时如果流程定义文件中定义了额外属性,Activiti5会自行利用反射机制注入到ActivityBehavior。
除了Command和ActivityBehavior外,Activiti5还大量引入了监听机制(拦截器的概念),目前引擎主要包含四类监听:
BPMN解析监听——BpmnParseListener,负责对BPMN2.0规范的流程定义文件进行解析控制;
任务监听——TaskListener,负责对各类任务的状态以及任务创建、指派责任人、完成任务三类事件进行响应;
执行监听——ExecutionListener,对执行过程添加辅助管控功能,对引擎中发生的启动、流转、结束事件进行响应;
事务监听——TransactionListener,负责事务控制监听。
PVM流程虚拟机中包含三类事件:Start、End、Take,分别表示流程的启动、流转和结束,流程启动后,流引擎会从Start事件开始执行,通过Take事件,驱动流程流向下一个环节,该“流向”的动作会被PVM运行时的AtomicOperationTransitionNotifyListenerTake监听,该监听会将附加到该流向的所有执行监听依次执行。任务有也有三类事件可以被监听:Create、Assignment、Complete,如果希望在任务被创建或指定了相关责任人或任务完成后增加些额外的辅助功能,可以创建TaskListener接口的实现类,并将其定义到执行定义元素中,Activiti5会处理这一切。这些监听本质上都算是活动的附加代理,在现有操作的基础上额外增加一个管理控制手段以达到特殊的目的,ActivityBehavior从另一个角度来看也是一种代理,都是由DelegateInvocation负责调用执行,它主要用来提供用户代码调用的上下文环境并负责控制实际调用,Activiti5为其提供了五个实现:ActivityBehaviorInvocation、ExecutionListenerInvocation、ExpressionInvocation、JavaDelegateInvocation、TaskListenerInvocation。
Activiti5提供的Command、ActivityBehavior、Listener等接口为引擎的功能扩展提供了方便,如果业务系统的功能不能满足时可以实现这些接口,以无侵入的方式扩展Activiti5,利用这些扩展接口,可以在其执行方法中完成很多业务逻辑,如权限校验、与业务系统的交互、与外部系统集成调用,甚至替换原有功能偷梁换柱暗度陈仓。
Activiti5 API应用
ProcessEngine是Activiti系统的核心接口,七类基础服务接口通过ProcessEngine获取,均采用链式API方式,直观明了,易于使用:
RepositoryService:
流程资源服务的接口,主要用于对流程定义的部署、查询和删除操。新流程的部署使用createDeployment().addResourceXXX().deploy()方法;已部署流程的查询使用createDeploymentQuery()附加查询条件的方式获取;另外可以使用deleteDeployment和deleteDeploymentCascade方法进行流程的删除或级联删除。
TaskService:
任务服务接口,该接口暴露了管理人机交互任务的操作,如任务领取(claiming)、任务完成(completing)和任务指派(assigning),还包括对任务的创建、查询、保存、删除等。
RuntimeService:
运行时服务主要用于启动或查询流程实例,以及流程变量、当前激活状态活动的查询、流程实例的删除等。流程在运行过程中所产生的东西都可以使用该接口进行相关处理。
HistoryService:
流程历史的服务接口。提供对历史流程实例、历史任务的查询和删除操作,从提供的API来看,历史流程的查询其提供了finished和unfinished流程的查询,即是说,HistoryService提供了对已完成和当前正在执行流程的活动/任务查询,这一点似乎与runtimeService提供的查询有些冲突,但其实是有差别的,运行时的信息仅包含任意时刻活动的实际运行状态信息(是从流程运行执行性能上考虑的),而历史信息是对已经固化的信息做简单查询而优化的,其所持有的对象是不同的。
IdentityService:
用户、组管理服务接口,用于管理Group、User的增删改查,并维护Membership,涉及到的API有newUser、newGroup、saveUser、saveGroup、createMembership以及相关的deleteXXX方法。
FormService:
表单服务用于访问表单数据以及在启动新的流程实例时或完成任务时所需的渲染后的表单,提供UI界面辅助用户填写相关值以保存至流程变量。该服务在实际业务应用中并不常用,属于引擎的非核心服务。
ManagementService:
提供流程管理和控制操作的接口服务,和业务流程的运行没有关联关系,比如查询数据库本身的内容、Activiti的版本及序列生成ID规则等,属于引擎的非核心服务。
Activiti5工作流引擎应用需要首先掌握的是配置及API基础应用,下面以上述BPMN2.0请假流程为例,简述Activiti5在具体系统中的应用。
Step1:绘制请假流程图
请假流程图使用标准的BPMN2.0图元进行流程定义,可以使用任何XML编制工具编写(导入XSD可以为编写过程提供代码提示),建议使用Joinwork Process Studio进行可视化编制,如图3:
图3:Step2配置Activiti5环境
流程引擎环境主要涉及到三个方面:数据源、事务管理以及流程引擎配置实例。通常流程引擎仅是业务系统的一个核心模块,其数据源和事务都要委托给业务平台,在流程引擎配置定义中,可以通过ref将业务系统的dataSource和transactionManager注入给Activiti5的引擎配置:&beanid="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration"&
&propertyname="dataSource"ref="dataSource" /&
&propertyname="transactionManager" ref="transactionManager"/&
&propertyname="databaseSchemaUpdate"value="true"/&
&propertyname="jobExecutorActivate"value="false"/&
如果是在OSGi环境中应用Activiti5,还需要将业务环境中注册的dataSource和transactionManager作为OSGi Service引入到当前Bundle,然后再进行processEngineConfiguration的配置:&osgi:referenceid="dataSource"interface="javax.sql.DataSource"/&
&osgi:referenceid="transactionManager"interface="org.springframework.transaction.PlatformTransactionManager"/&
Step3:部署请假流程定义文件到Activiti5环境
利用流程引擎提供的RepositoryService接口实现流程的部署://通过ProcessEngine获取repositoryService
RepositoryServicerepositoryService = processEngine.getRepositoryService();
//使用repositoryService进行新流程部署
repositoryService.createDeployment()
.addClasspathResource("请假申请-条件分支与合并流程.bpmn20.xml")
.deploy();
Step4:创建请假单页面输入请假天数及原由,启动流程
编写html表单输入界面,然后使用Ajax提交请求,由Servlet根据请求参数创建新流程实例,启动流程后界面如图4:
图4:流程启动后的界面
输入请假天数及原因,如果天数大于等于3天,则走“部门经理审批路由“分支,利用jQuery绑定”提交“按钮的操作:$('#startProcess').click(function(){
varurl = '/com.ygsoft.process.demo/ProcessEngineServlet?operate=start&'+$('#inputform').serialize();
//以UTF8方式提交:
type:"POST",
dataType:"json",
contentType:"application/x-www-form-charset=utf-8",//此参数避免中文乱码
success:function(data){
if(data.success){
alert('您的单据已提交,流程ID:'+data.id);
$('#inputform').hide();
$('#viewTodo').show(2000);
alert('您的单据未提交成功');
Backend端利用RuntimeService接口创建新的流程实例:// 通过ProcessEngine获取runtimeService
RuntimeServiceruntimeService = processEngine.getRuntimeService();
// 使从Request中获取请求参数,用于构造流程启动参数
Map&String, Object&params = newHashMap&String, Object&();
String processKey = request.getParameter("processKey");
int day = Integer.parseInt(request.getParameter("day"));
String reason = request.getParameter("reason");
params.put("day", day);
params.put("user", user);
params.put("reason", reason);
// 使用runtimeService启动流程实例(将参数做为流程变量处理)
ProcessInstanceprocessInstance = runtimeService.startProcessInstanceByKey(processKey,params) ;
Step5:获取审批人待办任务利用TaskService接口可是实现指配给自己的以及候选任务:
// 通过ProcessEngine获取taskService
TaskServicetaskService = processEngine.getTaskService();
// 使用taskService根据用户ID获取候选任务
List&Task& tasks = taskService.createTaskQuery()
.taskAssignee(user)
.orderByTaskCreateTime()
将查询到的List通过Gson转换成json数组传递到前端,由jQuery解析并显示到界面。
还有一种情况是查询分配给某个组或某个人的候选任务:List&Task& tasks = taskService.createTaskQuery()
.processInstanceId(processInstance.getId())
.taskCandidateGroup("xxxGrp")
List&Task& tasks = taskService.createTaskQuery()
.processInstanceId(processInstance.getId())
.taskCandidateUser("xxxUser")
Step6:审批人查看任务明细
任务明细除了包含Task本身的信息(如任务名称、描述以及流程变量等)外,还要动态显示当前激活任务的可视化流程图。
Task信息可以从List中获取,可视化流程图可以利用以下方式输出至前端:
// 根据当前Task获取流程定义对象 ProcessDefinitionEntityprocessDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) .getDeployedProcessDefinition(task.getProcessDefinitionId()); // 利用ProcessDiagramGenerator生成当前激活任务的图片流 InputStreamdefinitionImageStream = ProcessDiagramGenerator.generateDiagram(processDefinition, "png", runtimeService.getActiveActivityIds(task.getProcessInstanceId())); // 将图片流生成byte[]数组 byte[] diagramBytes = IoUtil.readInputStream(definitionImageStream,null); response.setContentType("image/png");// 设置浏览器响应的ContentType ServletOutputStream out = response.getOutputStream(); out.write(diagramBytes);// 输出至前端 out.close();
Step7:完成审批任务
审批人在查看请假申请单后,填写审批意见后以Ajax方式提交“完成任务“请求;Servlet利用TaskService进行任务的提交://先完成当前任务:
Map&String, Object&params = taskService.getVariables(taskId);
String reviewMessage = request.getParameter(“msg”);
String choice = request.getParameter(“choice”);
params.put(“msg”, choice+“-”+user+“-”+reviewMessage); plete(taskId, params);
&待第一个的审批工作完成后,流程引擎会产生Task事件,经由并行网关处理后,系统将生成“人力专员确认“的UserTask任务和”自动备案“的ServiceTask任务,其中ServiceTask任务将由系统自动执行,”人力专员确认“任务依然通过Step5、6、7完成,待这两个任务都完成后,两条路由分支由”合并“路由流转到”结束“节点,至此,流程结束。
通过以上API的应用分析,Activiti5 API构成清晰,针对性更强,不同的功能由相应的服务接口完成,访问接口更友好。
BPMN2.0是一个工作流业界标准,规范了大型厂商和开源工作流产品的实现,Activiti5实现了该标准的大部分图元定义和执行语义解释,功能强大,Activiti5可以与IBM、Oracle等大型商用工作流产品流程引擎节点的核心功能媲美,并且为了简化应用、扩充原有功能,Activiti5又自定义了6个扩展元素和15个扩展属性,这些元素和属性能够与BPMN规范相互组合可以实现更多、更实用的业务功能。
笔者通过技术组成、对BPMN规范的覆盖率、API应用友好性、社区支持度、第三方组件依赖程度以及可扩展性六个方面进行分析和比对,Activiti5的综合实力较强。对于如何选型符合BPMN标准的工作流产品,这是一个仁者见仁智者见智的问题,一方面依赖于各个公司对工作流技术方面的历史积累,另一方面也要针对具体项目具体情况区别对待。但如果对于一个全新的项目或对jBPM3、4设计理念认同的公司,不妨考虑Activiti5。
TA的最新馆藏
喜欢该文的人也喜欢}

我要回帖

更多关于 bpmn人工任务结束方式 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信