Activiti工作流学习笔记
先从工作流的启动开始讲,Activiti提供了四种工作流的启动方式
1.空启动事件
2.定时启动事件
3.异常启动事件
4.消息启动事件
空启动事件中标签内没有任何其他元素的定义
<startEvent id="startEvent" name="StartEvent"></startEvent>
Activity根据需求在空启动事件上进行了扩展,activiti:formKey表示与这个启动事件所关联的外置表单,activiti:initiator表示启动该流程的人员的id
<startEvent id ="StartEvent" name="startevent" activiti:formKey="user.form"></startEvent>
<startEvent id ="StartEvent" name ="startevent" activiti:initiator="user.id"></startEvent>
定时启动事件可以用于定期循环流程和一次性流程,比如企业的月报每月末汇总一次
<startEvent id="startEvent" name="time sart for process">
<timerEventDefinition>
<timeCycle>R1/2018-3-31T00:00/PM1M</timeCycle>
</timerEventDefinition>
<startEvent>
异常启动事件不能被runTimeService.startProcess()调用启动,他是通过另外一个流程的异常结束事件触发,下面是通过一个scripTask来捕获异常代码为AII001的异常并输出捕获语句
<startEvent id ="startEvent">
<errorEventDefinition erroeRef="AII001"></errorEventDefinition>
</startEvent>
<scriptTask id = "scripttask" name="scriptask" scriptFrommat="Groovy">
<script><![CDATA[out:println "catch an error";]]</script>
</scriptTask>
消息启动事件通过一个消息名称触发从而启动一个流程实例,通常结合消息抛出事件一起使用。
<message id = "reSendFile" name="重新发送消息">
<startEvent id = "messageStart">
<messageEventDefinition messageRef="reSendFile"/>
</startEvent>
结束事件包括空结束事件,异常结束事件,终止结束事件,取消结束事件
空结束事件不处理抛出结果,也可以理解为抛出空
<endEvent id = "endEvent" name= "end Event"/>
异常结束事件定义了抛出的异常错误代码,如果定义了异常开始事件怎会根据错误代码匹配到对应的异常开始事件触发对应的流程
<endEvent id = "endEvent" name="end Event">
<errorEventDefinition errorRef="AIA-001" />
</endEvent>
终止结束事件可以终止一个流程,当一个流程因为某些原因不能继续向下进行的时候则可以将该流程的一条输出流指向终止结束事件,空结束事件结束的是一次执行,而终止结束事件结束的是整个流程。
<endEvent id="endEvent" name="终止结束事件">
<terminateEventDefinition></terminateEventDefinition>
</endEvent>
取消结束事件可以取消一个事物子流程的执行,也只能在子流程中使用,当子流程出现异常需要取消时可以定义一个取消结束事件,当输出流指向一个取消结束事件是流程就会中断执行。
<endEvent id = "endEvent" name="cancel">
<cancelEventDefinition />
<endEvent>
顺序流
标准顺序流
标准顺序流是连接两个或多个模型建立关系
<sequenceFlow id = "flow" sourceRef="startEvent" targertRef="userTask"><sequenceFlow>
条件顺序流
条件顺序流是在标准顺序流上面添加条件表达式,只用通过条件才可以达到目标活动
<sequenceFlow id="flow" name="条件顺序流" sourceRef="startEvent" targetRef="usertask">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${pass==true}]]>
</conditionExpression>
</sequenceFlow>
任务
任务是流程中比较重要的部分,根据业务需求的不同任务也可以分为很多种
1.用户任务
2.脚本任务
3.WebService任务
4.业务规则任务
5.邮件任务
6.Mule任务
7.Camel任务
8.手动任务
9.Java Service 任务
10.Shell任务
用户任务
用户任务需要人参与, Activiti在BPMN2.0的基础上的基础上对属性进行了扩展
activiti:assignee指定了任务的处理人
activiti:cadidateUsers指定了用户任务的候选人,多个用逗号隔开
activiti:cadidateGroups指定了用户任务的候选组,多个用逗号隔开
activiti:dueDate 指定了用户任务的到期日
activiti:priority 指定了用户任务的优先级
下面用户任务指定了候选组为deptLeader 并且执行任务的时候提交一个动态表单(后面会讲)
<userTask id="deptLeaderAudit" name="部门领导审批" activiti:candidateGroups="deptLeader">
<extensionElements>
<activiti:formProperty id="startDate" name="请假开始日期" type="date" value="${startDate}" datePattern="yyyy-MM-dd" readable="true" writable="false"></activiti:formProperty>
<activiti:formProperty id="endDate" name="请假结束日期" type="date" value="${endDAte}" datePattern="yyyy-MM-dd" readable="true" writable="false"></activiti:formProperty>
<activiti:formProperty id="reason" name="请假原因" type="string" value="${reason}" readable="true" writable="false"></activiti:formProperty>
<activiti:formProperty id="deptLeaderPass" name="审批意见" type="enum" required="true" writable="true">
<activiti:value id="true" name="同意"></activiti:value>
<activiti:value id="false" name="不同意"></activiti:value>
</activiti:formProperty>
</extensionElements>
</userTask>
脚本任务可以运行引擎依赖语言之外的脚本语言,activiti支持的语言包括Groovy,JavaScript,Juel,activiti扩展的属性有
scriptFormat:指定脚本所依赖的语言
resultVariable:将脚本中返回的结果保存在变量里,当然这个变量需要在脚本里定义
<scriptTask id="initvars" name="初始化变量" scriptFormat="groovy">
<script>
<![CDATA[def name="铁头哥哥" ;
execution.setVariable("name",name);]]>
</script>
</scriptTask>
<scriptTask id="printvars" name="输出变量" scriptFormat="groovy">
<script>
<![CDATA[out:println:name;]]>
</script>
</scriptTask>
JavaService Task允许定义一个实现指定接口的java类或者表达式,java类必须实现JavaDelegate,ActivityBehavior其中一个,还可以配置执行java类时所传入的变量
activiti:expression可以使用UEL定义需要执行的任务内容,例如计算公示,调用Bean的方法等
activiti:delegateExpression功能和activiti:class类似,而且同样需要实现JavaDelegate或ActivityBehavior中一个接口,只不过这里不是指定一个具体的实现类,而是运行的时候动态设置
<serviceTask id ="myServiceTask" name="Java Service" activiti:class="tietougege.activiti.JavaServiceDelegate">
</serviceTask>
<serviceTask id ="myService2" name="JavaService" activiti:expression="#{leaveService.back()}"/>
<serviceTask id ="myService3" name="JavaService" activiti:expression="${leaveServiceDelegate}"/>
通过Web Service任务可以调用外部的Web Service 资源,通过implementation="##WebService"可以定义task为webService类型,通过ioSpecification定义元素输入输出参数
dataInputAssociation定义了属性输入关系,dataOutputAssociation定义了属性输出关系
<serviceTask id="checkGeneralManagerAudit" name="是否需要总经理审批"
implementation="##WebService" operationRef="tns:auditOperation">
<ioSpecification>
<dataInput itemSubjectRef="tns:generalManagerAuditRequestItem"
id="dataInput" />
<dataOutput itemSubjectRef="tns:generalManagerAuditResponseItem"
id="dataOutput" />
<inputSet>
<dataInputRefs>dataInput</dataInputRefs>
</inputSet>
<outputSet>
<dataOutputRefs>dataOutput</dataOutputRefs>
</outputSet>
</ioSpecification>
<!-- 属性名称必须映射,否则报异常 https://gist.github.com/5994803 -->
<dataInputAssociation>
<sourceRef>startDate</sourceRef>
<targetRef>startDate</targetRef>
</dataInputAssociation>
<dataInputAssociation>
<sourceRef>endDate</sourceRef>
<targetRef>endDate</targetRef>
</dataInputAssociation>
<dataOutputAssociation>
<sourceRef>needed</sourceRef>
<targetRef>needed</targetRef>
</dataOutputAssociation>
</serviceTask>
网关
1.排他网关
2.并行网关
3.包容网关
4.事件网关
排他网关:流程执行到该网关时,按照输出流的顺序逐个计算,当条件计算结果为true时,继续执行当前网关的输出流,在排他网关中,如果多个网关的计算结果都为true,那么他只会执行第一个值为true的网关,忽略其他表达式为true的网关,如果多个网关没有为true的时,他会抛出异常
<excludsiveGateway id="exclusiveGateway" default="flow1"/>
<exclusiveGateway id="exclusivegateway5" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow3" sourceRef="deptLeaderAudit"
targetRef="exclusivegateway5"></sequenceFlow>
<sequenceFlow id="flow4" name="拒绝" sourceRef="exclusivegateway5"
targetRef="modifyApply">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderApproved == 'false'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow5" name="同意" sourceRef="exclusivegateway5"
targetRef="hrAudit">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderApproved == 'true'}]]></conditionExpression>
</sequenceFlow>
并行网关:对并发的任务进行流程建模,他能把单条线路任务拆分成多个路径并执行或将多条线路合并
<parallelGateway id="fork" name="Parallel GateWay Fork"></parallelGateway>
<userTask id ="usertask1" name="部门领导审批"></userTask>
<userTask id="usertask2" name="人事审批"></userTask>
<parallelGateway id="join" name="Parallel Gateway Join"></parallelGateway>
<userTask id="usertask3" name="考勤归档"></userTask>
<endEvent id="endEvent1" name="end"></endEvent>
<userTask id="usertask4" name="请假申请"></userTask>
<sequenceFlow id="flow2" name="" sourceRef="usertask4" targetRef="fork"/>
<sequenceFlow id="flow3" name="" sourceRef="fork" targetRef="usertask1"/>
<sequenceFlow id="flow4" name="" sourceRef="fork" targetRef="usertask2"/>
<sequenceFlow id="flow5" name="" sourceRef="usertask1" targetRef="join"/>
<sequenceFlow id="flow6" name="" sourceRef="usertask2" targetRef="join"/>
<sequenceFlow id="flow7" name="" sourceRef="join" targetRef="usertask3"/>
<sequenceFlow id="flow8" name="" sourceRef="usertask3" targetRef="endevent1"/>
<sequenceFlow id="flow9" name="" sourceRef="startevent1" targetRef="usertask4"/>
包容网关:包容网关融合了排他网关和并行网关的特性,排他网关允许在每条线路上设置条件,并行网关可以执行多条线路,包容网关既可以同时执行多条线路又可以在网关上设置条件
第一行定义了fork类型的包容网关,第二行定义了join类型的包容网关,第九行和第十四行是两个条件顺序流
1 <inclusiveGateway id="igFork" name="Inclusive Gateway fork"></inclusiveGateway>
2 <inlcusiveGateway id="igJoin" name="Inclusive GAteway Join"></inclusiveGateway>
3 <userTask id="usertask1" name="部门领导审批"></userTask>
4 <userTask id="usertask2" name="人事审批"></userTask>
5 <userTask id="usertask3" name="考勤归档"></userTask>
6 <endEvent id ="endEvent1" name="end" ></endEvent>
7 <userTask id="usertask4" name="请假申请"></userTask>
8 <sequenceFlow id="flow2" name="" sourceRef="usertask4" targetRef="igFork"/>
9 <sequenceFlow id="flow3" name="需要部门领导审批?" sourceRef="igFork" targetRef="usertask1"/>
10 <conditionExpression xsi:type="tFormalExpression">
11 <![CDATA[${leader==true}]]>
12 </conditionExpression>
13 <sequenceFlow>
14 <sequenceFlow id="flow4" name="需要人事审批?" sourceRef="igFork" targetRef="usertask2">
15 <conditionExpression xsi:type="tFormalExpression">
16 <![CDATA[${hr==true}]]>
17 </conditionExpression>
18 </sequenceFlow>
19 <sequenceFlow id="flow5" name="" sourceRef="usertask1" targetRef="igJoin"/>
20 <sequenceFlow id="flow6" name="" sourceRef="usertask2" targetRef="igJoin"/>
21 <sequenceFlow id="flow7" name="" sourceRef="igJoin" targetRef="usertask3"/>
22 <sequenceFlow id="flow8" name="" sourceRef="usertask3" targetRef="endevent1"/>
23 <sequenceFlow id ="flow9" name="" sourceRef="startevent" targetRef="usertask4"/>
事件网关:事件网关是专门为中间捕获事件设置的,它允许设置多个输出流指向多个不同的中间捕获事件(最少两个)。在流程执行到事件网关后,流程处于“等待”状态,因为中间捕获事件需要依赖中间抛出事件触发才能更改“等待”状态为“活动”状态,当然,定时捕获事件除外(他由时间驱动)
<signal id="alertSignal" name="alert"></signal>
<process id="EventGateway" name="EventGateway">
<startEvent id="startevent1" name="Start"></startEvent>
<eventBaseGateway id="eventgateway1" name="Event Gateway"></eventBaseGateway>
<intermediateCatchEvent id="timeintermediatecatchevent1" name="TimeCatchEvent">
<timeEventDefinition>
<timeDuration>PT1S</timeDuration>
</timeEventDefinition>
</intermediateCatchEvent>
<scriptTask id="scripttask1" name="定时器任务执行之后" scriptformat="groovy"><script><!CDATA[out:println "after time event";]]></script>
</scriptTask>
<intermediateCatchEvent id="signalintermediatecatcheevent1" name="SignalCatchEvent">
<signalEventDefinition signalRef="alertSignal">
</signalEventDefinition>
</intermediateCatchEvent>
<scriptTask id="scripttask2" name="信号捕获事件之后" scriptformat="groovy"><script><!CDATA[out:println "after signal event";]]></script></scriptTask>
<endEvent id="endEvent" name="END"></endEvent>
<sequenceFlow id="flow1" name="" soureRef="startevent1" targetRef="eventgateway1">
<sequenceFlow id="flow2" name="" soureRef="eventgateway1" targetRef="timeintermediatecatchevent1">
<sequenceFlow id="flow3" name="" soureRef="timeintermediatecatchevent1" targetRef="scripttask1">
<sequenceFlow id="flow4" name="" soureRef="eventgateway1" targetRef="signalintermediatecatcheevent1">
<sequenceFlow id="flow5" name="" soureRef="signalintermediatecatcheevent1" targetRef="scripttask2">
<sequenceFlow id="flow6" name="" soureRef="scripttask1" targetRef="endEvent">
<sequenceFlow id="flow7" name="" soureRef="scripttask2" targetRef="endEvent">
第一行定义一个信号等待中间信号捕获事件捕获,第五号定义了一个时间中间捕获事件,第12行定义了信号中间捕获事件,流程启动后两个输出流均处于等状态,等到中间捕获事件处理完成后变成活跃状态
子流程
在企业中还有一些通用的业务流程,例如,付款流程作为公司业务运作的核心流程之一,在业务设计和架构设计上会保持通用,或者在业务架构中作为一个通用的模块,不同的业务根据财务流程 的规范传入指定的参数就可以使用付款流程。
1.只能切仅能包含一个空启动流程
2.至少有一个结束流程
3.在子流程中顺序流不能直接设置输出流到子流程之外的活动中去,如果需要可以通过边界事件替代
<process id="subprocess" name="subprocess">
<startEvent id ="startevent1" name="start"></startEvent>
<userTask id ="usertask1" name="下单" ></userTask>
<endEvent id="end" name="end"></endEvent>
<subProcess id ="subprocess1" name="付款子流程">
<startEvent id="startEvent2" name="start"></startEvent>
<userTask id="usertask2" name="银行付款"></userTask>
<endEvent id ="endEvent1" name="End"></endEvent>
<serviceTask id="mailtask1" name="发送邮件" activiti:type="mail">
</serviceTask>
<sequenceFlow id="flow1" name="" sourceRef="startEvent2" targetRef="usertask2"></sequenceFlow>
<sequenceFlow id="flow2" name="" sourceRef="usertask2" targetRef="mailtask1"></sequenceFlow>
<sequenceFlow id="flow3" name="" sourceRef="mailtask1" targetRef="endEvent1"></sequenceFlow>
</subProcess>
<sequenceFlow id="flow4" name="" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<sequenceFlow id="flow5" name="" sourceRef="usertask1" targetRef="subprocess1"></sequenceFlow>
<sequenceFlow id="flow6" name="" sourceRef="subprocess1" targetRef="end"></sequenceFlow>
</process>
调用活动:调用活动解决的问题是流程的通用性,和子流程的作用一致,但是表现方式不同,使用一个调用活动却带嵌入子流程方式的活动即可,通过创建一个调用活动模型并指定外部流程的ID方式作为主流程的一个活动。
<callActivity id="callactivity1" name="调用付款流程" calledElement="payment">
<extensionElements>
<activiti: in source="amount" target="amount"></activiti:in>
<activiti:out source="paid" target="paid"></activiti:out>
<activiti:out sourceExpression="${payTime}" target="payTime"></activiti:out>
</extensionElements>
Activiti工作流学习笔记的更多相关文章
- Activiti工作流学习笔记(三)——自动生成28张数据库表的底层原理分析
原创/朱季谦 我接触工作流引擎Activiti已有两年之久,但一直都只限于熟悉其各类API的使用,对底层的实现,则存在较大的盲区. Activiti这个开源框架在设计上,其实存在不少值得学习和思考的地 ...
- Activiti工作流学习笔记(四)——工作流引擎中责任链模式的建立与应用原理
原创/朱季谦 本文需要一定责任链模式的基础,主要分成三部分讲解: 一.简单理解责任链模式概念 二.Activiti工作流里责任链模式的建立 三.Activiti工作流里责任链模式的应用 一.简单理解责 ...
- Activiti工作流学习笔记一
Activiti工作流 一:Activiti第一天 1:工作流的概念 说明: 假设:这两张图就是华谊兄弟的请假流程图 图的组成部分: 人物:范冰冰冯小刚王中军 事件(动作):请假.批准.不批准 工作流 ...
- Activiti工作流学习之流程图应用详解
Activiti工作流学习之流程图应用详解 1.目的 了解Activiti工作流是怎样应用流程图的. 2.环境准备2.1.相关软件及版本 jdk版本:Jdk1.7及以上 IDE:eclipse ...
- Activiti工作流学习之概述(一)
一.工作流介绍 我第一次听到这个词,是蒙逼的,再看百度百度,更傻眼了,完全说的不像人话啊,举几个生活中的例子,就明白多了比如:请假.报销等等,如果文字太过抽象,请看图: 二.工作流引擎 Process ...
- Activiti工作流学习(三)Activiti工作流与spring集成
一.前言 前面Activiti工作流的学习,说明了Activiti的基本应用,在我们开发中可以根据实际的业务参考Activiti的API去更好的理解以及巩固.我们实际的开发中我们基本上都使用sprin ...
- Activiti工作流学习(一)部署对象和流程定义
一.前言 前一段时间在工作中,使用了流程审批,对api的调用非常不熟悉,都是调用别人写好的接口在界面上进行显示,基本了解了流程审批的主要步骤,现对流程审批进行学习,主要是调用api进行CRUD操作,感 ...
- Activiti工作流学习-----基于5.19.0版本(6)
七. BPMN的简介 读者了解到这里,应付一般的工作流开发已经足够了.此处应该有华丽的分割线,在工作流项目中核心开发人员主要是对工作流业务设计以及实现,而初级开发人员是对业务功能的代码实现.以后将主要 ...
- Activiti工作流学习-----基于5.19.0版本(1)
该版本的Activiti运行须知: 1.JDK 6+,Eclipse最好是Kepler以上版本. 2.试验功能都有EXPERIMENTAL标注,被标注的部分不应该视为稳定的. 有兴趣的同学可以去了解下 ...
随机推荐
- Microsoft Deployment Toolkit build 8456
MDT build 8456的重大变化摘要. 支持的配置更新 Windows ADK for Windows 10,版本1809 Windows 10,版本1809 Configuration Man ...
- mysql中几个日期时间类型之间的区别和使用
MySQL中有如下几个时间类型:date.time.datetime.timestamp.year MySQL数据类型 含义 date 只存 ...
- boost学习目录
Boost之数值转换lexical_cast https://www.cnblogs.com/TianFang/archive/2013/02/05/2892506.html Boost之字符串算法s ...
- Go之运算符
逻辑运算符用于连接布尔型表达式.在Java中不同于数学的逻辑表达 3<X<5 ,java 中应该写成 x>3 & x<5 "&" 和&quo ...
- 02——Solr学习之Solr安装与配置(linux上的安装)
借鉴博客:https://www.jianshu.com/p/1100f54fcbd8 https://www.cnblogs.com/jepson6669/p/9134652.html 1.准备一个 ...
- Vue.js 2.x笔记:状态管理Vuex(7)
1. Vuex简介与安装 1.1 Vuex简介 Vuex是为vue.js应用程序开发的状态管理模式,解决的问题: ◊ 组件之间的传参,多层嵌套组件之间的传参以及各组件之间耦合度过高问题 ◊ 不同状态中 ...
- jQuery的事件处理
一.页面加载响应事件 $(document).ready()方法,获取文档就绪的时候.他极大地提高了Web相应速度.虽然该方法可以代替传统的window.onload()方法,但是两者之间仍然有差别. ...
- odoo 权限问题
odoo 权限问题 权限组问题 权限组是为了将人员按组划分同一分配权限.权限组的建立是基于每个应用来实现的 建立一个应用的分组(可省略,主要用于创建用户时有选择项) 建立一条record记录model ...
- 阿里云配置安全组(配置入口port)
访问:www.aliyun.com 登录后,左上角点击: 点击[云服务器] 点击右下角[配置规则] 入口 出口
- Equipment UVA - 1508(子集补集)
The Korea Defense and Science Institute, shortly KDSI, has been putting constant effort into newequi ...