七、 BPMN的简介

读者了解到这里,应付一般的工作流开发已经足够了。此处应该有华丽的分割线,在工作流项目中核心开发人员主要是对工作流业务设计以及实现,而初级开发人员是对业务功能的代码实现。以后将主要对流程图设计的概念和具体设计进行描述,如果你感兴趣可以继续了解。

7.1 什么是BPMN?

BPMN的全称是Business Process Model and Notation,它是一套BPM的规范,从2004年起,BPMN规范的推动有OMG组织维护,开始推出的BPMN1.0主要是对设计图中图形的设计,一经推出便受到了业务流程设计者的欢迎,后面推出了BPMN2.0。

在Eclipse IDE中点击File--->New--->Other--->搜索Activiti Diagram即可,

创建好了bpmn文件后,用xml editor打开就是如下所示,xml文件的根节点是definitions,在里面可以定义多个流程定义。虽然建议是一个流程定义文件中只有一个流程定义,方便后期的维护。在definitions里面含有属性xmlns、targetNamespace,targetNamespace的值随意。

<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples"> <process id="myProcess" name="My First Process">
..
</process> </definitions>

process含有两个属性:

  • id:该属性是必需的,Id将会转换为ProcessDefinition的key值, 在启动流程实例的时候调用startProcessInstanceByKey方法会用到key,不过注意的是RuntimeService操作的流程定义都是最新的。
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess");

需要区分 startProcessInstanceById方法传入的id是以key:version形式格式化的,不要和流程定义xml文件中的Id混淆,流程定义xml中的id仅仅是以key的形式的组成部分而已,通过processDefinition.getId()方法可以获取id,它的长度为64个字符,所以不要将流程定义的xml文件的id设置过长,以至于数据库无法生成流程定义id抛出ActivitiException。

  • name:可选的属性值配置,流程引擎不会使用该值,不过一般我们都需要设置,方便设计时查看。

这里选取官方的一个例子进行实践:

设计的流程图很简单:

这个流程定义文件中包含了start event(起点,就是左边的圆圈)、end event(终点,右边的圆圈)、User Tasks(用户任务,中间两个方块)。

其中user task就是设计的任务节点,第一个user task被指定了用户组为accountancy的执行,第二个user task被指定了用户组为management的执行,使用Eclipse IDE设计的时候可以这样为两个task添加属性值:

设置好了的FinancialReportProcess.bpmn20.xml文件用xml editor打开就是这样:

 <?xml version="1.0" encoding="UTF-8" ?>
<definitions id="definitions"
targetNamespace="http://activiti.org/bpmn20"
xmlns:activiti="http://activiti.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"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"> <process id="financialReport" name="Monthly financial report process"> <startEvent id="theStart" /> <sequenceFlow id="flow1" sourceRef="theStart" targetRef="writeReportTask" /> <userTask id="writeReportTask" name="Write monthly financial report" >
<documentation>
Write monthly financial report for publication to shareholders.
</documentation>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>accountancy</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask> <sequenceFlow id="flow2" sourceRef="writeReportTask" targetRef="verifyReportTask" /> <userTask id="verifyReportTask" name="Verify monthly financial report" >
<documentation>
Verify monthly financial report composed by the accountancy department.
This financial report is going to be sent to all the company shareholders.
</documentation>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask> <sequenceFlow id="flow3" sourceRef="verifyReportTask" targetRef="theEnd" /> <endEvent id="theEnd" /> </process> <bpmndi:BPMNDiagram>
<bpmndi:BPMNPlane bpmnElement="financialReport">
<bpmndi:BPMNShape bpmnElement="theStart">
<omgdc:Bounds height="30.0" width="30.0" x="75.0" y="225.0" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="writeReportTask">
<omgdc:Bounds height="80.0" width="100.0" x="165.0" y="200.0" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="verifyReportTask">
<omgdc:Bounds height="80.0" width="100.0" x="330.0" y="200.0" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="theEnd">
<omgdc:Bounds height="28.0" width="28.0" x="480.0" y="226.0" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1">
<omgdi:waypoint x="105.0" y="240.0" />
<omgdi:waypoint x="165.0" y="240.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2">
<omgdi:waypoint x="265.0" y="240.0" />
<omgdi:waypoint x="330.0" y="240.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3">
<omgdi:waypoint x="430.0" y="240.0" />
<omgdi:waypoint x="480.0" y="240.0" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram> </definitions>

其中xml中的sequenceFlow就是流程图里面的连接线,一般我们会eclipse的流程设计图形化界面(Activiti Designer)上面设置name的属性值,方便查看。其中连线的起点和终点用sourceRef和targetRef表示。

我们创建了流程定义文件后,创建流程定义对象需要发布流程定义文件,工作流引擎做了两件事情:1.将配置文件存进数据库中。 2.将配置文件解析为内存中的java对象。

Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("FinancialReportProcess.bpmn20.xml")
.deploy();

获取流程实例可以通过流程定义文件中的id(也就是存入数据库的记录的key)获取。

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("financialReport");

调用startProcessInstanceByKey后台会做很多事情,启动流程实例将会通过前面流程图的start event(就是第一个圆圈),流程引擎将会沿着sequence flow(就是线路,目前只有一条)到达第一个任务节点,流程引擎将会将持久化第一个任务到数据库中。这时用户或者用户组可以拾取任务(具体你需要编写代码查询有相关权限用户或者用户组和当前任务,在调用拾取的API绑定用户和任务),并将这个结果保存进数据库,这时流程引擎将会等待任务完成。可见流程实例是一路执行的除非进入等待状态。在进入等待状态时,流程引擎也会将流程实例状态保存进入数据库,如果用户完成了任务,流程引擎会继续执行下去或者到达流程的结束。即使期间发生系统重启崩溃,存入数据库的流程实例的状态也是安全有效的。

在任务被成功创建后,startProcessInstanceByKey将会返回值并且当前活动的任务处于等待状态,如果当前任务被分配给用户组,那么用户组里的成员都是执行任务的候选者。

使用TaskService可以获取任务,进一步我们可以操作任务(Task):

List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit").list();

因为kermit也是在用户组accountancy里面,所以可以查询出任务,至于accountancy用户组是之前我们在流程定义文件中配置过的:

<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>accountancy</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>

我们也可以直接使用用户组来进行查询任务:

TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();

使用Activiti Explorer项目可以帮助我们投入更多的精力在流程图的设计上面,少敲代码,点击鼠标即可验证设计图功能。具体做法是启动项目Activiti Explorer,以管理员kermit/密码kermit登录系统,点击流程--->流程设计工作区---->导入后,将上面FinancialReportProcess.bpmn20.xml文件上传,

上传的效果:列表中会有一个叫Monthly financial report process的流程

选择流程Monthly financial report process,然后在处理模型选择部署,我们设计的流程图就生效了。

部署后,我使用了用户fozzie作为本次实践的用户(为什么没选其他的用户呢,因为activiti里面有现成的用户咯),然后发现里面没有用户组accountancy,添加用户组并把用户fozzie加进用户组中:

点击管理--->组---添加组,输入如下点击添加组即可。

添加成员:

弹出框输入用户名,选择该用户 点击done即可:

退出当前用户使用账户fozzie/fozzie登录系统后,可以发现他的权限变少了(这不是重点),点击流程--->已部署的流程定义,选中Monthly financial report process点击启动流程。

这时流程实例就会生成,流程引擎将会执行到第一个user task,现在我们使用账户fozzie登录系统,会发现有一个组任务,可以看见详情:

组任务如果被拾取的话,就会在组任务中消失,相应组下面的其他用户将不能获得该任务:

taskService.claim(task.getId(), "fozzie");

fozzie用户拾取了任务,被拾取的任务现在就会成为个人任务,个人可以查询自己的任务:

List<Task> tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();

在Activiti Explorer的UI页面里,上述代码可以通过点击签收按钮完成:

假如fozzie开始进行工作,现在工作完成:

taskService.complete(task.getId());

上面这段代码是Activiti工作流引擎继续执行的信号,同时完成的任务本身将会在正在运行表(ACT_RU_EXECUTION)中去除,这时任务节点流转到第二个任务上面,而在Activiti Explorer的UI页面上面就是点击完成按钮即可。第二个任务和第一个任务类似,就不再提了。

重复操作后第二个任务就完成了,现在流程引擎进入了end event,流程实例完成,然后运行表中数据清空.使用historyService可以验证流程的执行情况:

HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance =
historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());

  

Activiti工作流学习-----基于5.19.0版本(6)的更多相关文章

  1. Activiti工作流学习-----基于5.19.0版本(8)

    8.1.5 Start Event 继续上一篇的事件的分享笔记,Start Event指明该处是流程开始,至于开始事件的类型(消息到达开始,指定的事件循环开始等),定义如何开始是在开始事件圆圈图标里面 ...

  2. Activiti工作流学习-----基于5.19.0版本(2)

    二.activiti.cfg.xml的其他bean节点配置 2.1 新特性:Job Executor和Async Executor 从5.17.0版本的activiti开始提供作业执行者(Job Ex ...

  3. Activiti工作流学习-----基于5.19.0版本(5)

    五.与Spring集成 实际项目中一般都有Spring的身影,与Spring集成使得Activiti的实用性得到提高.activiti和Spring整合需要activiti-spring的jar在类路 ...

  4. Activiti工作流学习-----基于5.19.0版本(1)

    该版本的Activiti运行须知: 1.JDK 6+,Eclipse最好是Kepler以上版本. 2.试验功能都有EXPERIMENTAL标注,被标注的部分不应该视为稳定的. 有兴趣的同学可以去了解下 ...

  5. Activiti工作流学习-----基于5.19.0版本(4)

    四.使用工作流开发 org.activiti.engine.ProcessEngine提供的Service作用在工作流引擎上面,如果所示是模仿一个公司简单的审批流程,你可以下载这个Demo:Activ ...

  6. Activiti工作流学习-----基于5.19.0版本(7)

    八.BPMN 2.0流程图详解 BPMN 2.0的标准的出现是好事,用户不在被某个工作流开发商绑架或者在工作流中开发妥协,Activiti作为BPMN标准的一套解决方案,使得用户在选择工作流框架时可以 ...

  7. Activiti工作流学习-----基于5.19.0版本(3)

    前面关于eventType的属性值的配置简单的说了一下,activiti支持的值如下表所示:这是我摘抄的activiti官网的 Event 的名字 描述 Event的类名 ENGINE_CREATED ...

  8. Activiti工作流学习之流程图应用详解

    Activiti工作流学习之流程图应用详解 1.目的  了解Activiti工作流是怎样应用流程图的. 2.环境准备2.1.相关软件及版本    jdk版本:Jdk1.7及以上 IDE:eclipse ...

  9. Activiti工作流学习之概述(一)

    一.工作流介绍 我第一次听到这个词,是蒙逼的,再看百度百度,更傻眼了,完全说的不像人话啊,举几个生活中的例子,就明白多了比如:请假.报销等等,如果文字太过抽象,请看图: 二.工作流引擎 Process ...

随机推荐

  1. 转:VC中UpdateData()函数的使用

    VC中UpdateData()函数的使用 UpdateData(FALSE)与UpdateData(TRUE)是相反的过程     UpdateData(FALSE)是把程序中改变的值更新到控件中去  ...

  2. .sdp文件格式介绍

    最近做RTSP流播放,需要了解.sdp这种会话描述的文件格式,当然,里面的具体语法有SDP解析器来分析.但是我需要大概了解一些字段的意思,它是文本描述的,采用key value的形式描述. https ...

  3. chk cloud

  4. B - Network - uva 315(求割点)

    题意:给一个无向连通图,求出割点的数量. 首先输入一个N(多实例,0结束),下面有不超过N行的数,每行的第一个数字代表后面的都和它存在边,0表示行输入的结束(很蛋疼的输入方式). 分析:割点的模板题 ...

  5. CSS常用选择器

    关于CSS常用选择器: 1.ID选择器 关于ID选择器具有唯一性,在文档流中,ID是唯一的,在低版本的浏览器中,允许出现不适唯一ID的情况,而在高版本的浏览器中,出现ID不唯一的情况浏览器会出现的报错 ...

  6. TTTAttributedLabel使用介绍(转)

    TTTAttributedLabel 库地址 https://github.com/TTTAttributedLabel/TTTAttributedLabel 可以实现电话  地址  链接自动查找显示 ...

  7. 自定义listView添加滑动删除功能

    今天研究了一下android里面的手势,结合昨天学习的自定义View,做了一个自定义的listview,继承自listView,添加了条目的滑动手势操作,滑动后出现一个删除按钮,点击删除按钮,触发一个 ...

  8. 苹果有益让老iPhone变慢以迫使消费者购买新一代的iPhone?

    首先,来一组来自谷歌Trends的图片.(谷歌Trends记录了某段时间内相关关键词搜索的次数.) 假设你做数据,那么你应该会有些感觉. 特别是第一幅图,它规律似乎比第二幅更明显,第二幅图仅仅是一个普 ...

  9. [Typescript] Function defination

    Define a function type and params type: // The function init // Accept two params which are both typ ...

  10. 内容提供者 ContentResolver 数据库 示例 -2

    MainActivity public class MainActivity extends ListActivity {     // 访问内容提供者时需要的主机名称     public stat ...