activiti5.17流程进入阻塞状态,定时任务根据数据库状态推动流程到下个节点
- 格式:docx
- 大小:49.41 KB
- 文档页数:7
activiti 定时边界执行方法Activiti定时边界执行方法介绍在使用Activiti工作流引擎时,我们经常会遇到需要在一定时间内执行某个任务的需求。
Activiti提供了定时边界事件(Boundary Timer Event)来实现这一功能。
本文将详细介绍Activiti中定时边界执行方法的各种方式。
方法一:使用定时边界事件1.在BPMN流程图中,将定时边界事件(Boundary Timer Event)添加到需要设置定时边界的任务节点。
2.配置定时边界事件的时间表达式,指定任务节点在多长时间后执行。
3.定时边界事件触发后,将触发的事件发送给任务节点,并执行相应的逻辑。
方法二:使用定时器服务(Timer Service)1.在BPMN流程图中,通过使用Service Task(可自定义实现类)来调用定时器服务。
2.在实现类中,通过编程方式设置定时器任务,描述任务触发的时间与逻辑。
3.定时器任务触发后,执行相应的逻辑。
方法三:使用Java定时器1.在BPMN流程图中,通过使用Service Task(可自定义实现类)来调用Java定时器。
2.在实现类中,通过编程方式创建Java定时器,并设置定时执行的逻辑。
3.Java定时器触发后,执行相应的逻辑。
方法四:使用定时任务框架1.在BPMN流程图中,通过使用Service Task(可自定义实现类)来调用定时任务框架。
2.在实现类中,使用定时任务框架提供的API,配置定时执行任务的时间与逻辑。
3.定时任务触发后,执行相应的逻辑。
结论以上是Activiti中实现定时边界执行方法的几种常见方式。
在使用时,根据具体的需求和技术背景选择最适合的方法。
无论采用哪种方式,都能够实现在一定时间内执行任务的目的,提高工作流的效率和灵活性。
注意:在配置定时边界事件的时间表达式时,需要根据具体的业务需求和时间规则准确设置,避免出现误操作或无法满足需求的情况。
方法一:使用定时边界事件1.在BPMN流程图中,将定时边界事件(Boundary Timer Event)添加到需要设置定时边界的任务节点。
activiti的定时器的用法
Activiti的定时器可以用于在指定的时间点触发任务或事件。
在BPMN中,定时器可以应用于任务节点、边界事件和中间事件。
1. 任务节点的定时器用法:
在BPMN模型中的任务节点上,可以设置定时器属性来定义任务的触发时间。
定时器可以是简单的时间表达式,也可以是基于cron表达式的复杂定时规则。
例如,可以设置一个定时器,让任务在当前时间的5分钟后触发,或者按照每天特定的时间触发。
2. 边界事件的定时器用法:
边界事件是与任务节点关联的事件,它们可以在任务执行过程中触发。
可以在边界事件上设置定时器属性,使得当特定时间达到时触发边界事件。
例如,可以设置一个定时器,让边界事件在任务开始后的30分钟后触发。
3. 中间事件的定时器用法:
中间事件是与流程图中的事件相关联的节点,它们可以在流程执行过程中触发。
可以在中间事件上设置定时器属性,使得当特定时间达到时触发事件。
例如,可以设置一个定时器,让中间事件在某个特定时间触发。
要使用Activiti的定时器功能,需要按照以下步骤进行操作:1. 在BPMN模型中选择需要应用定时器的任务节点、边界事件或中间事件;
2. 在相应节点的属性面板中设置定时器属性,包括触发时间和时间规则;
3. 配置Activiti引擎的定时器Job Executor,确保其正常运行;
4. 运行流程,等待定时器触发相应的任务或事件。
需要注意的是,定时器的触发、执行和处理结果都由Activiti
引擎负责管理,可以通过Activiti的Job Executor和定时器监
听器来控制定时任务的执行。
activiti流转原理Activiti是一个开源的用于工作流和业务流程管理的引擎,它采用了基于BPMN 2.0标准的模型作为输入,并提供了强大的流转引擎来执行这些模型。
它提供了一种灵活而可扩展的方式来管理和执行各种类型的工作流和业务流程。
在Activiti中,流转是指将一个流程实例从一个活动节点转移到下一个活动节点的过程。
流转的原理是通过执行和控制来实现的。
下面将详细介绍Activiti的流转原理。
1.流转的触发流转的触发可以通过多种方式来实现,包括手动触发、定时触发、事件触发等。
手动触发是指用户在流程运行过程中手动执行一些操作来引发流转,比如提交申请、审核通过等。
定时触发是指根据预定的时间表来触发流转,比如在特定的日期或时间段执行一些活动。
事件触发是指根据特定的事件发生来触发流转,比如收到消息、邮件等。
2.流转的执行流转的执行是指按照预定的流程模型,将流程实例从一个活动节点转移到下一个活动节点的过程。
在Activiti中,流转的执行是由各种执行器来完成的,包括以下几种:-用户任务执行器:用于执行用户任务,即需要人工干预的活动节点。
用户任务执行器负责分配任务给用户,等待用户完成任务,并在任务被完成后继续流转。
-脚本任务执行器:用于执行脚本任务,即需要执行一段脚本的活动节点。
脚本任务执行器负责解析并执行脚本,并在脚本执行完成后继续流转。
-服务任务执行器:用于执行服务任务,即需要调用外部服务的活动节点。
服务任务执行器负责调用服务接口,并在服务调用完成后继续流转。
-接收任务执行器:用于执行接收任务,即等待外部触发事件的活动节点。
接收任务执行器负责等待特定的事件发生,并在事件发生后继续流转。
3.流转的控制流转的控制是指根据预定的流程规则和条件控制流程实例的流转。
在Activiti中,流程规则和条件可以通过表达式和脚本来定义和处理。
流转的控制主要包括以下几个方面:-顺序流控制:根据流程模型中定义的顺序流规则,按照活动节点的先后顺序依次执行。
Activity 定时任务原理一、什么是定时任务?定时任务,顾名思义,就是根据设定的时间点或时间间隔,触发某个特定的任务或操作。
在软件开发中,定时任务通常用于执行一些周期性的操作,比如定时清理数据、定时发送邮件、定时备份文件等。
二、 Android 中的定时任务在Android开发中,我们经常会遇到需要实现定时任务的情况。
某个应用需要在用户长时间不操作的情况下,自动更新数据;或是需要在某个特定的时间执行某个操作。
这就需要用到Android中的定时任务机制来实现。
三、 Android 中的定时任务实现方式在Android中,我们可以通过以下几种方式来实现定时任务:1. 使用 Handler 和 Runnable通过创建一个 Handler 对象,并利用其 postDelayed 方法来实现延时执行某个任务,从而达到定时任务的效果。
这种方式比较简单,适合于一些简单的定时任务。
2. 使用 AlarmManagerAlarmManager 是一个系统级别的服务,可以在特定的时间触发某些操作。
通过使用 AlarmManager,我们可以实现一些需要在特定时间点触发的定时任务,比如闹钟提醒、定时发送通知等。
3. 使用 JobSchedulerJobScheduler 是 Android 5.0 引入的一个新的调度服务,在Android 5.0 及以上的系统中可以使用。
它可以根据一些特定的条件来触发任务的执行,比如网络连接状态、电量情况等,非常灵活和智能。
4. 使用 WorkManagerWorkManager 是 Android 架构组件中的一部分,它可以用来管理和调度后台任务。
相比于其他方式,WorkManager 具有更好的兼容性和灵活性,它可以适配不同的 Android 版本,并且支持在不同的条件下执行任务,比如在网络连接可用时执行任务、在设备充电时执行任务等。
四、 Activity 定时任务的实现原理在 Android 中,如果我们希望在某个 Activity 中实现定时任务,通常可以借助上述提到的一些方式来实现。
activiti学习5:开启流程和流程前进activiti学习5:开启流程和流程前进上⼀篇博客中介绍了activiti如何部署流程定义⽂件,这次来学习下如何开启流程和使流程前进。
⽬录⼀、流程和任务的关系以下是⼀个简单的请假流程图,其中有⼀个开始事件,两个⽤户任务,⼀个结束事件。
启动流程后,activiti会⾃动创建第⼀个流程节点的⽤户任务,然后我们完成第⼀个⽤户任务流程就会前进到下⼀个流程节点,创建第⼆个节点的流程任务并删除第⼀个流程任务。
⼆、开启流程activiti提供了⼀个RuntimeService服务组件来在流程运⾏时对流程实例进⾏管理与控制。
开启流程就需要使⽤其中的api2.1根据流程定义key开启流程上⼀篇博客中说道了⼀个流程部署成功后,会在部署信息表act_re_deployment和流程定义表act_re_procdef中插⼊记录。
流程定义key就是act_re_procdef表中的KEY_字段的值。
当表中存在KEY_字段相同的记录时,activiti会选择版本号 VERSION_最新的⼀条流程定义记录来开启流程/*** 开启流程,根据流程定义key开启流程,* 如果流程定义表中有多个相同的流程定义key,activiti会根据版本号字段VERSION_选择最新的版本来开启流程*/@Testpublic void test1() {String processDefinitionKey="process";//开启流程,得到流程实例对象ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);System.out.println(processInstance);}activiti⽤ProcessInstance这个接⼝来描述开启流程后得到的流程实例。
activiti工作流原理
activiti是一个Java开源的工作流引擎,用于管理和执行流程。
它基于BPMN 2.0规范,提供了一套强大的工作流管理功能。
activiti的工作原理可以分为以下几个方面:
1. 流程定义:使用BPMN
2.0规范的XML格式编写流程定义,定义流程中的各个环节、任务和流转条件。
2. 流程部署:将流程定义部署到activiti引擎中,引擎会解析
和验证流程定义,并将其转换为可执行的对象模型。
3. 流程实例化:通过引擎的API或图形界面,创建流程实例。
引擎会根据流程定义的模型创建一个新的流程实例,并将其加入到流程引擎的运行时环境中。
4. 任务执行:当一个流程实例启动后,活动会依次被执行。
引擎会根据流程定义的逻辑,自动判断下一个应该执行的任务,并将其分配给相应的参与者。
5. 任务完成:参与者完成任务后,将会通知引擎,并将相关信息提交。
引擎会根据流程定义的设定,判断是否满足继续流转的条件。
6. 流程控制:根据流程定义中的条件和监听器,引擎会根据当前的流程状态和相关事件,决定下一个应该执行的任务。
7. 流程结束:当流程达到结束条件时,该流程实例将会被标记为已完成。
整个流程的执行过程即结束。
activiti提供了丰富的API和可视化工具,使得用户能够方便地管理和配置工作流。
它的设计目标是简单、易用,同时又具备灵活的扩展性,可以满足各种不同业务场景的需求。
Activiti⼯作流框架中的任务调度!⼯作流框架中的任务流程元素详解,使⽤监听器监听任务执⾏任务⽤户任务描述⽤户任务⽤来设置必须由⼈员完成的⼯作当流程执⾏到⽤户任务,会创建⼀个新任务,并把这个新任务加⼊到分配⼈或群组的任务列表中图形标记⽤户任务显⽰成⼀个普通任务(圆⾓矩形),左上⾓有⼀个⼩⽤户图标XML内容XML中的⽤户任务定义:id属性是必须的,name属性是可选的:<userTask id="theTask" name="Important task" />⽤户任务可以设置描述,添加documentation元素可以定义描述:<userTask id="theTask" name="Schedule meeting" ><documentation>Schedule an engineering meeting for next week with the new hire.</documentation>描述⽂本可以通过标准的java⽅法来获取:task.getDescription()持续时间任务可以⽤⼀个字段来描述任务的持续时间可以使⽤查询API来对持续时间进⾏搜索,根据在时间之前或之后进⾏搜索Activiti提供了⼀个节点扩展,在任务定义中设置⼀个表达式,这样在任务创建时就可以设置初始持续时间表达式应该是:java.util.Datejava.util.String(ISO8601格式),ISO8601持续时间(⽐如PT50M)null在流程中使⽤上述格式输⼊⽇期,或在前⼀个服务任务中计算⼀个时间.这⾥使⽤了持续时间,持续时间会基于当前时间进⾏计算,再通过给定的时间段累加: 使⽤"PT30M"作为持续时间,任务就会从现在开始持续30分钟<userTask id="theTask" name="Important task" activiti:dueDate="${dateVariable}"/>任务的持续时间也可以通过TaskService修改,或在TaskListener中通过传⼊的DelegateTask参数修改⽤户分配⽤户任务可以直接分配给⼀个⽤户,通过humanPerformer元素定义humanPerformer定义需要⼀个resourceAssignmentExpression来实际定义⽤户.⽬前只⽀持formalExpressions<process ... >...<userTask id='theTask' name='important task' ><humanPerformer><resourceAssignmentExpression><formalExpression>kermit</formalExpression></resourceAssignmentExpression></humanPerformer></userTask>只有⼀个⽤户可以作为任务的执⾏者分配⽤户在activiti中,⽤户叫做执⾏者拥有执⾏者的⽤户不会出现在其他⼈的任务列表中,只能出现执⾏者的个⼈任务列表中直接分配给⽤户的任务可以通过TaskService获取:List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();任务也可以加⼊到⼈员的候选任务列表中.需要使⽤potentialOwner元素⽤法和humanPerformer元素类似,需要指定表达式中的每个项⽬是⼈员还是群组<process ... >...<userTask id='theTask' name='important task' ><potentialOwner><resourceAssignmentExpression><formalExpression>user(kermit), group(management)</formalExpression></resourceAssignmentExpression></potentialOwner></userTask>使⽤potentialOwner元素定义的任务可以通过TaskService获取:List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit");这会获取所有kermit为候选⼈的任务,表达式中包含user(kermit).这也会获得所有分配包含kermit这个成员的群组(⽐如,group(management),前提是kermit是这个组的成员,并且使⽤了activiti的账号组件).⽤户所在的群组是在运⾏阶段获取的, 它们可以通过IdentityService进⾏管理如果没有显式指定设置的是⽤户还是群组,引擎会默认当做群组处理下⾯的设置与使⽤group(accountancy)⼀样:<formalExpression>accountancy</formalExpression>Activiti对任务分配的扩展当分配不复杂时,⽤户和组的设置⾮常⿇烦.为避免复杂性,可以使⽤⽤户任务的⾃定义扩展assignee属性: 直接把⽤户任务分配给指定⽤户(和使⽤humanPerformer 效果完全⼀样)<userTask id="theTask" name="my task" activiti:assignee="kermit" />candidateUsers属性: 为任务设置候选⼈(和使⽤potentialOwner效果完全⼀样,不需要像使⽤potentialOwner通过user(kermit)声明,这个属性只能⽤于⼈员)<userTask id="theTask" name="my task" activiti:candidateUsers="kermit, gonzo" />candidateGroups属性: 为任务设置候选组(和使⽤potentialOwner效果完全⼀样,不需要像使⽤potentialOwner通过group(management)声明,这个属性只能⽤于群组)<userTask id="theTask" name="my task" activiti:candidateGroups="management, accountancy" />candidateUsers和candidateGroups可以同时设置在同⼀个⽤户任务中Activiti中虽然有账号管理组件和IdentityService ,账号组件不会检测设置的⽤户是否存在. Activiti允许与其他已存的账户管理⽅案集成使⽤创建事件的任务监听器来实现⾃定义的分配逻辑:<userTask id="task1" name="My task" ><extensionElements><activiti:taskListener event="create" class="org.activiti.MyAssignmentHandler" /></extensionElements></userTask>DelegateTask会传递给TaskListener的实现,通过它可以设置执⾏⼈,候选⼈和候选组public class MyAssignmentHandler implements TaskListener {public void notify(DelegateTask delegateTask) {// Execute custom identity lookups here// and then for example call following methods:delegateTask.setAssignee("kermit");delegateTask.addCandidateUser("fozzie");delegateTask.addCandidateGroup("management");...}}使⽤spring时,使⽤表达式把任务监听器设置为spring代理的bean,让这个监听器监听任务的创建事件⽰例:执⾏者会通过调⽤ldapService这个spring bean的findManagerOfEmployee⽅法获得.流程变量emp会作为参数传递给bean<userTask id="task" name="My Task" activiti:assignee="${ldapService.findManagerForEmployee(emp)}"/>可以⽤来设置候选⼈和候选组:<userTask id="task" name="My Task" activiti:candidateUsers="${ldapService.findAllSales()}"/>⽅法返回类型只能为String(候选⼈) 或Collection < String >(候选组):public class FakeLdapService {public String findManagerForEmployee(String employee) {return "Kermit The Frog";}public List<String> findAllSales() {return Arrays.asList("kermit", "gonzo", "fozzie");}}脚本任务描述脚本任务是⼀个⾃动节点当流程到达脚本任务,会执⾏对应的脚本图形标记脚本任务显⽰为标准BPMN 2.0任务(圆⾓矩形),左上⾓有⼀个脚本⼩图标XML内容脚本任务定义需要指定script和scriptFormat<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy"><script>sum = 0for ( i in inputArray ) {sum += i}</script></scriptTask>scriptFormat的值必须兼容JSR-223(java平台的脚本语⾔).默认Javascript会包含在JDK中,不需要额外的依赖.如果要使⽤其他的脚本引擎,必须要是JSR-223引擎兼容的.还需要把对应的jar添加到classpath下, 并使⽤合适的名称:activiti单元测试经常使⽤groovygroovy脚本引擎放在groovy-all.jar中,在2.0版本之前,脚本引擎是groovy jar的⼀部分.使⽤需要添加依赖:<dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-all</artifactId><version>2.x.x<version></dependency>脚本变量到达脚本任务的流程可以访问的所有流程变量,都可以在脚本中使⽤<script>sum = 0for ( i in inputArray ) {sum += i}</script>也可以在脚本中设置流程变量,直接调⽤execution.setVariable("variableName", variableValue) 默认,不会⾃动保存变量(activiti 5.12之前) 可以在脚本中⾃动保存任何变量,只要把scriptTask的autoStoreVariables属性设置为true 最佳实践是不要使⽤,⽽是显式调⽤execution.setVariable()<scriptTask id="script" scriptFormat="JavaScript" activiti:autoStoreVariables="false">参数默认为false: 如果没有为脚本任务定义设置参数,所有声明的变量将只存在于脚本执⾏的阶段在脚本中设置变量: 这些命名已经被占⽤,不能⽤作变量名- out, out:print, lang:import, context, elcontext.<script>def scriptVar = "test123"execution.setVariable("myVar", scriptVar)</script>脚本结果脚本任务的返回值可以通过制定流程变量的名称,分配给已存在或者⼀个新流程变量,需要使⽤脚本任务定义的'activiti:resultVariable'属性任何已存在的流程变量都会被脚本执⾏的结果覆盖如果没有指定返回的变量名,脚本的返回值会被忽略<scriptTask id="theScriptTask" name="Execute script" scriptFormat="juel" activiti:resultVariable="myVar"><script>#{echo}</script></scriptTask>脚本的结果-表达式 #{echo} 的值会在脚本完成后,设置到myVar变量中Java服务任务描述Java服务任务⽤来调⽤外部Java类图形标记Java服务任务显⽰为圆⾓矩形,左上⾓有⼀个齿轮⼩图标XML内容声明Java调⽤逻辑有四种⽅式:实现JavaDelegate或者ActivityBehavior执⾏解析代理对象的表达式调⽤⼀个⽅法表达式调⽤⼀个值表达式执⾏⼀个在流程执⾏中调⽤的类,需要在activiti:class属性中设置全类名:<serviceTask id="javaService"name="My Java Service Task"activiti:class="org.activiti.MyJavaDelegate" />使⽤表达式调⽤⼀个对象,对象必须遵循⼀些规则,并使⽤activiti:delegateExpression属性进⾏创建:<serviceTask id="serviceTask" activiti:delegateExpression="${delegateExpressionBean}" />delegateExpressionBean是⼀个实现了JavaDelegate接⼝的bean,定义在实例的spring容器中要执⾏指定的UEL⽅法表达式, 需要使⽤activiti:expression:<serviceTask id="javaService"name="My Java Service Task"activiti:expression="#{printer.printMessage()}" />⽅法printMessage()会调⽤名为printer对象的⽅法为表达式中的⽅法传递参数:<serviceTask id="javaService"name="My Java Service Task"activiti:expression="#{printer.printMessage(execution, myVar)}" />调⽤名为printer对象上的⽅法printMessage.第⼀个参数是DelegateExecution, 在表达式环境中默认名称为execution. 第⼆个参数传递的是当前流程的名为myVar的变量要执⾏指定的UEL⽅法表达式, 需要使⽤activiti:expression:<serviceTask id="javaService"name="My Java Service Task"activiti:expression="#{split.ready}" />ready属性的getter⽅法:getReady() 会作⽤于名为split的bean上.这个对象会被解析为流程对象和spring环境中的对象实现要在流程执⾏中实现⼀个调⽤的类,这个类需要实现org.activiti.engine.delegate.JavaDelegate接⼝,并在execute⽅法中提供对应的业务逻辑.当流程执⾏到特定阶段,会指定⽅法中定义好的业务逻辑,并按照默认BPMN 2.0中的⽅式离开节点⽰例: 创建⼀个java类的例⼦,对流程变量中字符串转换为⼤写这个类需要实现org.activiti.engine.delegate.JavaDelegate接⼝,要求实现execute(DelegateExecution) ⽅法,包含的业务逻辑会被引擎调⽤流程实例信息:流程变量和其他信息,可以通过DelegateExecution接⼝访问和操作public class ToUppercase implements JavaDelegate {public void execute(DelegateExecution execution) throws Exception {String var = (String) execution.getVariable("input");var = var.toUpperCase();execution.setVariable("input", var);}}serviceTask定义的class只会创建⼀个java类的实例所有流程实例都会共享相同的类实例,并调⽤execute(DelegateExecution) 类不能使⽤任何成员变量,必须是线程安全的,必须能模拟在不同线程中执⾏.影响着属性注⼊的处理⽅式流程定义中引⽤的类(activiti:class)不会在部署时实例化只有当流程第⼀次执⾏到使⽤类的时候,类的实例才会被创建如果找不到类,会抛出⼀个ActivitiException这个原因是部署环境(更确切是的classpath)和真实环境往往是不同的:当使⽤ant或业务归档上传到Activiti Explorer来发布流程,classpath没有包含引⽤的类内部实现类也可以提供实现org.activiti.engine.impl.pvm.delegate.ActivityBehavior接⼝的类实现可以访问更强⼤的ActivityExecution,它可以影响流程的流向注意: 这应该尽量避免.只有在⾼级情况下并且确切知道要做什么的情况下,再使⽤ActivityBehavior接⼝属性注⼊为代理类的属性注⼊数据. ⽀持如下类型的注⼊: 固定的字符串表达式如果有效的话,数值会通过代理类的setter⽅法注⼊,遵循java bean的命名规范(⽐如fistName属性对应setFirstName(Xxx)⽅法)如果属性没有对应的setter⽅法,数值会直接注⼊到私有属性中⼀些环境的SecurityManager不允许修改私有属性,要把想注⼊的属性暴露出对应的setter⽅法来⽆论流程定义中的数据是什么类型,注⼊⽬标的属性类型都应该是 org.activiti.engine.delegate.Expression⽰例: 把⼀个常量注⼊到属性中属性注⼊可以使⽤class属性在声明实际的属性注⼊之前,需要定义⼀个extensionElements的XML元素<serviceTask id="javaService"name="Java service invocation"activiti:class="org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected"><extensionElements><activiti:field name="text" stringValue="Hello World" /></extensionElements></serviceTask>ToUpperCaseFieldInjected类有⼀个text属性,类型是org.activiti.engine.delegate.Expression. 调⽤text.getValue(execution) 时,会返回定义的字符串Hello World可以使⽤长⽂字(⽐如,内嵌的email),使⽤activiti:string⼦元素:<serviceTask id="javaService"name="Java service invocation"activiti:class="org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected"><extensionElements><activiti:field name="text"><activiti:string>Hello World</activiti:string></activiti:field></extensionElements></serviceTask>可以使⽤表达式,实现在运⾏期动态解析注⼊的值这些表达式可以使⽤流程变量或spring定义的bean.服务任务中的java类实例会在所有流程实例中共享:为了动态注⼊属性的值,可以在org.activiti.engine.delegate.Expression中使⽤值和⽅法表达式会使⽤传递给execute⽅法的DelegateExecution参数进⾏解析<serviceTask id="javaService" name="Java service invocation"activiti:class="org.activiti.examples.bpmn.servicetask.ReverseStringsFieldInjected"><extensionElements><activiti:field name="text1"><activiti:expression>${genderBean.getGenderString(gender)}</activiti:expression></activiti:field><activiti:field name="text2"><activiti:expression>Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}</activiti:expression></activiti:field></ extensionElements></ serviceTask>⽰例: 注⼊表达式,并使⽤在当前传⼊的DelegateExecution解析:public class ReverseStringsFieldInjected implements JavaDelegate {private Expression text1;private Expression text2;public void execute(DelegateExecution execution) {String value1 = (String) text1.getValue(execution);execution.setVariable("var1", new StringBuffer(value1).reverse().toString());String value2 = (String) text2.getValue(execution);execution.setVariable("var2", new StringBuffer(value2).reverse().toString());}}可以把表达式设置成⼀个属性,⽽不是⼦元素:因为java类实例会被重⽤,注⼊只会发⽣⼀次,当服务任务调⽤第⼀次的时候发⽣注⼊当代码中的属性改变了,值也不会重新注⼊,把它们看作是不变的,不⽤修改它们服务任务结果服务流程返回的结果(使⽤表达式的服务任务)可以分配给已经存在的或新的流程变量通过指定服务任务定义的activiti:resultVariable属性来实现指定的流程变量会被服务流程的返回结果覆盖如果没有指定返回变量名,就会忽略返回结果<serviceTask id="aMethodExpressionServiceTask"activiti:expression="#{myService.doSomething()}"activiti:resultVariable="myVar" />服务流程的返回值(在myService上调⽤doSomething() ⽅法的返回值,myService可能是流程变量,也可能是spring的bean),在服务执⾏完成之后,会设置到名为myVar的流程变量⾥处理异常执⾏⾃定义逻辑时,常常需要捕获对应的业务异常,在流程内部进⾏处理抛出BPMN Errors: 在服务任务或脚本任务的代码⾥抛出BPMN error: 要从JavaDelegate,脚本,表达式和代理表达式中抛出名为BpmnError的特殊ActivitiExeption 引擎会捕获这个异常,把它转发到对应的错误处理中:边界错误事件或错误事件⼦流程public class ThrowBpmnErrorDelegate implements JavaDelegate {public void execute(DelegateExecution execution) throws Exception {try {executeBusinessLogic();} catch (BusinessException e) {throw new BpmnError("BusinessExceptionOccured");}}}构造参数是错误代码,会被⽤来决定哪个错误处理器会来响应这个错误这个机制只⽤于业务失败,应该被流程定义中设置的边界错误事件或错误事件⼦流程处理. 技术上的错误应该使⽤其他异常类型,通常不会在流程⾥处理异常顺序流: 内部实现类在⼀些异常发⽣时,让流程进⼊其他路径<serviceTask id="javaService"name="Java service invocation"activiti:class="org.activiti.ThrowsExceptionBehavior"></serviceTask><sequenceFlow id="no-exception" sourceRef="javaService" targetRef="theEnd" /><sequenceFlow id="exception" sourceRef="javaService" targetRef="fixException" />这⾥的服务任务有两个外出顺序流:分别叫exception和no-exception. 异常出现时会使⽤顺序流的ID来决定流向public class ThrowsExceptionBehavior implements ActivityBehavior {public void execute(ActivityExecution execution) throws Exception {String var = (String) execution.getVariable("var");PvmTransition transition = null;try {executeLogic(var);transition = execution.getActivity().findOutgoingTransition("no-exception");} catch (Exception e) {transition = execution.getActivity().findOutgoingTransition("exception");}execution.take(transition);}}JavaDelegate使⽤Activiti服务需要在Java服务任务中使⽤Activiti服务的场景: ⽐如,通过RuntimeService启动流程实例,⽽callActivity不满⾜需求org.activiti.engine.delegate.DelegateExecution允许通过 org.activiti.engine.EngineServices接⼝直接获得这些服务:public class StartProcessInstanceTestDelegate implements JavaDelegate {public void execute(DelegateExecution execution) throws Exception {RuntimeService runtimeService = execution.getEngineServices().getRuntimeService();runtimeService.startProcessInstanceByKey("myProcess");}}所有activiti服务的API都可以通过这个接⼝获得使⽤这些API调⽤出现的所有数据改变,都是在当前事务中在例如spring和CDI这样的依赖注⼊环境也会起作⽤,⽆论是否启⽤了JTA数据源⽰例: 下⾯的代码功能与上⾯的代码⼀致,这是RuntimeService是通过依赖注⼊获得,⽽不是通过org.activiti.engine.EngineServices接⼝@Component("startProcessInstanceDelegate")public class StartProcessInstanceTestDelegateWithInjection {@Autowiredprivate RuntimeService runtimeService;public void startProcess() {runtimeService.startProcessInstanceByKey("oneTaskProcess");}}因为服务调⽤是在当前事务⾥,数据的产⽣或改变,在服务任务执⾏完之前,还没有提交到数据库.所以API对于数据库数据的操作,意味着未提交的操作在服务任务的API调⽤中都是不可见的WebService任务描述WebService任务可以⽤来同步调⽤⼀个外部的WebService图形标记WebService任务与Java服务任务显⽰效果⼀样(圆⾓矩形,左上⾓有⼀个齿轮⼩图标)XML内容要使⽤WebService需要导⼊操作和类型,可以使⽤import标签来指定WebService的WSDL<import importType="/wsdl/"location="http://localhost:63081/counter?wsdl"namespace="/" />声明告诉activiti导⼊WSDL定义,但没有创建itemDefinition和message假设想调⽤⼀个名为prettyPrint的⽅法,必须创建为请求和响应信息对应的message和itemDefinition <message id="prettyPrintCountRequestMessage" itemRef="tns:prettyPrintCountRequestItem" /><message id="prettyPrintCountResponseMessage" itemRef="tns:prettyPrintCountResponseItem" /><itemDefinition id="prettyPrintCountRequestItem" structureRef="counter:prettyPrintCount" /><itemDefinition id="prettyPrintCountResponseItem" structureRef="counter:prettyPrintCountResponse" />在申请服务任务之前,必须定义实际引⽤WebService的BPMN接⼝和操作基本上,定义接⼝和必要的操作.对每个操作都会重⽤上⾯定义的信息作为输⼊和输出⽰例: 定义了counter接⼝和prettyPrintCountOperation操作:<interface name="Counter Interface" implementationRef="counter:Counter"><operation id="prettyPrintCountOperation" name="prettyPrintCount Operation"implementationRef="counter:prettyPrintCount"><inMessageRef>tns:prettyPrintCountRequestMessage</inMessageRef><outMessageRef>tns:prettyPrintCountResponseMessage</outMessageRef></operation></interface>然后定义WebService任务,使⽤WebService实现,并引⽤WebService操作<serviceTask id="webService"name="Web service invocation"implementation="##WebService"operationRef="tns:prettyPrintCountOperation">WebService任务IO规范每个WebService任务可以定义任务的输⼊输出IO规范<ioSpecification><dataInput itemSubjectRef="tns:prettyPrintCountRequestItem" id="dataInputOfServiceTask" /><dataOutput itemSubjectRef="tns:prettyPrintCountResponseItem" id="dataOutputOfServiceTask" /><inputSet><dataInputRefs>dataInputOfServiceTask</dataInputRefs></inputSet><outputSet><dataOutputRefs>dataOutputOfServiceTask</dataOutputRefs></outputSet></ioSpecification>WebService任务数据输⼊关联指定数据输⼊关联有两种⽅式:使⽤表达式使⽤简化⽅式使⽤表达式指定数据输⼊关联: 需要定义来源和⽬的item,并指定每个item属性之间的对应关系:<dataInputAssociation><sourceRef>dataInputOfProcess</sourceRef><targetRef>dataInputOfServiceTask</targetRef><assignment><from>${dataInputOfProcess.prefix}</from><to>${dataInputOfServiceTask.prefix}</to></assignment><assignment><from>${dataInputOfProcess.suffix}</from><to>${dataInputOfServiceTask.suffix}</to></assignment></dataInputAssociation>分配item的前缀和后缀使⽤简化⽅式指定数据输⼊关联: sourceRef元素是activiti的变量名,targetRef元素是item定义的⼀个属性:<dataInputAssociation><sourceRef>PrefixVariable</sourceRef><targetRef>prefix</targetRef></dataInputAssociation><dataInputAssociation><sourceRef>SuffixVariable</sourceRef><targetRef>suffix</targetRef></dataInputAssociation>PrefixVariable变量的值分配给prefix属性,把SuffixVariable变量的值分配给suffix属性WebService任务数据输出关联指定数据输出关联有两种⽅式:使⽤表达式使⽤简化⽅式使⽤表达式指定数据输出关联: 需要定义⽬的变量和来源表达式<dataOutputAssociation><targetRef>dataOutputOfProcess</targetRef><transformation>${dataOutputOfServiceTask.prettyPrint}</transformation></dataOutputAssociation>⽅法和数据输⼊关联完全⼀样使⽤简化⽅式指定数据输出关联: sourceRef元素是item定义的⼀个属性,targetRef元素是activiti的变量名<dataOutputAssociation><sourceRef>prettyPrint</sourceRef><targetRef>OutputVariable</targetRef></dataOutputAssociation>⽅法和数据输⼊关联完全⼀样业务规则任务描述业务规则任务⽤来同步执⾏⼀个或多个规则Activiti使⽤drools规则引擎执⾏业务规则: 包含业务规则的.drl⽂件必须和流程定义⼀起发布流程定义⾥包含了执⾏这些规则的业务规则任务流程使⽤的所有.drl⽂件都必须打包在流程BAR⽂件⾥如果想要⾃定义规则任务的实现: 想⽤不同⽅式使⽤drools,或者使⽤完全不同的规则引擎.你可以使⽤BusinessRuleTask上的class或表达式属性图形标记业务规则任务是⼀个圆⾓矩形,左上⾓使⽤⼀个表格⼩图标进⾏显⽰XML内容要执⾏部署流程定义的BAR⽂件中的⼀个或多个业务规则,需要定义输⼊和输出变量:对于输⼊变量定义,可以使⽤逗号分隔的⼀些流程变量输出变量定义只包含⼀个变量名,会把执⾏业务规则后返回的对象保存到对应的流程变量中注意: 结果变量会包含⼀个对象列表,如果没有指定输出变量名称,默认会使⽤ org.activiti.engine.rules.OUTPUT<process id="simpleBusinessRuleProcess"><startEvent id="theStart" /><sequenceFlow sourceRef="theStart" targetRef="businessRuleTask" /><businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}"activiti:resultVariable="rulesOutput" /><sequenceFlow sourceRef="businessRuleTask" targetRef="theEnd" /><endEvent id="theEnd" /></process>业务规则任务也可以配置成只执⾏部署的.drl⽂件中的⼀些规则.这时要设置逗号分隔的规则名,只会执⾏rule1和rule2:<businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}"activiti:rules="rule1, rule2" />定义哪些规则不⽤执⾏:除了rule1和rule2以外,所有部署到流程定义同⼀个BAR⽂件中的规则都会执⾏:<businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}"activiti:rules="rule1, rule2" exclude="true" />可以⽤⼀个选项修改BusinessRuleTask的实现:<businessRuleTask id="businessRuleTask" activiti:class="${MyRuleServiceDelegate}" />BusinessRuleTask的功能和ServiceTask⼀样,但是使⽤BusinessRuleTask的图标来表⽰在这⾥要执⾏业务规则邮件任务Activiti强化了业务流程,⽀持⾃动邮件任务: 可以发送邮件给⼀个或多个参与者,包括⽀持cc,bcc,HTML内容等等邮件任务不是BPMN 2.0规范定义的官⽅任务,Activiti中邮件任务是⽤专门的服务任务实现的邮件服务器配置Activiti引擎要通过⽀持SMTP功能的外部邮件服务器发送邮件为了实际发送邮件,引擎穾知道如何访问邮件服务器.下⾯的配置可以设置到activiti.cfg.xml配置⽂件中:属性是否必须描述mailServerHost否邮件服务器的主机名(⽐如:).默认为localhostmailServerPort 是如果没有使⽤默认端⼝邮件服务器上的SMTP传输端⼝.默认为25mailServerDefaultFrom否如果⽤户没有指定发送邮件的邮件地址,默认设置的发送者的邮件地址。
activiti 工作流用法
工作流引擎是现代企业中常用的一种技术工具,它能够帮助组织自动化和优化业务流程。
Activiti 是一个开源的工作流引擎,它基于 Java 平台,并且提供了强大的功能和灵活的工作流管理能力。
使用 Activiti 工作流引擎可以带来以下几方面的好处:
1. 自动化流程管理:Activiti 允许您将复杂的业务流程通过可视化设计器进行建模,并且可以将模型转换为可执行的流程实例。
这样可以有效地简化和自动化组织内部的业务流程,提高工作效率和准确性。
2. 任务分配和追踪:Activiti 提供了灵活的任务管理功能,可以根据不同的角色和权限分配任务给不同的用户或用户组。
同时,它还提供了任务追踪功能,可以实时监控任务的执行情况,确保任务按时完成。
3. 异常处理和流程优化:在工作流引擎中,您可以定义异常处理策略和流程分支条件,以便在流程执行过程中处理各种异常情况。
这样可以在保证流程的顺利进行的同时,及时解决问题,优化流程。
4. 高度可扩展:Activiti 是一个基于开源技术的工作流引擎,它提供了丰富的扩展接口和插件机制,可以方便地集成到现有的企业应用系统中。
同时,它还支持水平扩展和集群部署,以应对高并发和大规模应用场景。
总之,Activiti 是一个功能强大且灵活的工作流引擎,可以帮助企业实现自动化流程管理、任务分配和追踪、异常处理和流程优化等目标。
它的开源特性使得它可以与其他系统无缝集成,并且具有高度可扩展性。
如果您的企业正在寻找一种优秀的工作流引擎,那么 Activiti 绝对值得一试。
工作流Activiti介绍与应用工作流(workflow)就是工作流程的计算模型,即将工作流程中的工作如何前后组织在一起的逻辑和规则在计算机中以恰当的模型进行表示并对其实施计算。
我的理解就是:将部分或者全部的工作流程、逻辑让计算机帮你来处理,实现自动化。
1Activiti简介Activiti是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理,工作流,服务协作等领域的一个开源,灵活的,易扩展的可执行流程语言框架。
它实现了BPMN 规范,可以发布设计好的流程定义,并通过api进行流程调度。
1.1Activiti基础编程框架Activiti的基础编程框架如下:Activiti基于Spring,ibatis等开源中间件作为软件平台,在此之上构建了非常清晰的开发框架。
上图列出了Activiti的核心组件。
:流程引擎的抽象,对于开发者来说,它是我们使用Activiti的外观(fa?ade),通过它可以获得我们需要的一切服务。
(TaskService,RuntimeService,RepositoryService...):Activiti按照流程的生命周期(定义,部署,运行)把不同阶段的服务封装在不同的Service中,用户可以非常清晰地使用特定阶段的接口。
通过ProcessEngine能够获得这些Service实例。
1.2Activiti重要服务类ProcessEngine:流程引擎的抽象,通过它我们可以获得我们需要的一切服务。
RepositoryService: Activiti中每一个不同版本的业务流程的定义都需要使用一些定义文件,部署文件和支持数据(例如 XML文件,表单定义文件,流程定义图像文件等),这些文件都存储在Activiti内建的Repository中。
RepositoryService提供了对 repository 的存取服务。
TaskService:在Activiti业务流程定义中每一个执行节点都被称作一个Task,流程运行过程中,与每个任务节点相关的接口,比如complete, delete,delegate等等都是TaskService提供的。
Activiti工作流一:Activiti1:工作流的概念2:工作流的执行过程演示程序:Activiti控制台3:Activiti介绍Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。
Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss jBPM的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务流程图。
3.1:工作流引擎ProcessEngine对象,这是Activiti工作的核心。
负责生成流程运行时的各种实例及数据、监控和管理流程的运行。
3.2:BPMN业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)3.3:数据库(先学后看)Activiti数据库支持:Activiti的后台是有数据库的支持,所有的表都以ACT_开头。
第二部分是表示表的用途的两个字母标识。
用途也和服务的API对应。
ACT_RE_*: 'RE'表示repository。
这个前缀的表包含了流程定义和流程静态资源(图片,规则,等等)。
ACT_RU_*: 'RU'表示runtime。
这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。
Activiti只在流程实例执行过程中保存这些数据,在流程结束时就会删除这些记录。
这样运行时表可以一直很小速度很快。
ACT_ID_*: 'ID'表示identity。
这些表包含身份信息,比如用户,组等等。
ACT_HI_*: 'HI'表示history。
activiti 工作原理
activiti是一个开源的工作流引擎,用于管理和协调各种商业流程。
它的工作原理是基于BPMN(Business Process Model and Notation)标准来定义和执行流程。
在activiti中,流程被建模为一系列的任务和活动,这些任务和活动通过连线连接起来,形成一个完整的流程图。
每个任务和活动都有相应的属性和行为,如任务名称、任务处理人、任务表单等。
当一个流程实例被启动时,activiti会根据流程定义中的节点顺序逐步执行每个任务和活动。
每个任务和活动的执行结果会保存在activiti的数据库中,以便随时查询和跟踪。
在执行过程中,activiti还提供了一系列的监听器和事件触发机制。
通过监听器,可以在流程的不同阶段执行自定义的业务逻辑。
同时,activiti也支持异步执行和并行处理,提高流程的效率和灵活性。
除了流程的执行,activiti还提供了一系列的管理和监控功能。
通过activiti的控制台,可以对流程进行部署、启动、挂起等操作。
同时,activiti还提供了各种报表和监控指标,方便用户对流程的性能和效果进行评估和优化。
总的来说,activiti工作原理是基于BPMN标准的流程定义和执行。
它通过任务和活动的连线和属性来描述流程的顺序和行为,通过事件触发和监听器来实现业务逻辑的扩展和定制。
同
时,它还提供了丰富的管理和监控功能,方便用户对流程进行控制和评估。
activiti学习笔记:Activiti工作流教程Activiti5 流程实例觉得activiti设计得简单而强大,尝试翻译一下他的10分钟入门指南:10分钟入门指南通过一个(非常简单的)业务流程,介绍一些基本的Activiti工作流感念和API接口。
使用案例这个用例叫干脆(straightfoward):有一个公司,暂且叫它BPMCorp。
在BPMCorp内部,会计部门每个月都要写一份财务报告给公司的股东。
但在发送给所有股东之前必须经过上级部门的批准。
下面涉及的所有文件及代码片段均可以通过Activiti分发的examples范例包中找到,请查看包ertask的内容。
推荐Activiti工作流教程:基于Activiti5工作流实战企业协同OA办公系统(spring-data-jpa、uur前台组件)/goods-343.html流程图如上所述的业务流程可以使用Activiti的可视化流程编辑器 Activiti Modeler查看及编辑。
使用BPMN2.0的标准符号则如下图所示:这里没有什么特殊的东西,图中看到的是一个none start event(左边的圆圈),其次是两个user tasks:"撰写财务报告"和”批准财务报告",以 none end event (右边边框加粗型的圆圈)结束。
XML表示上述业务流程的XML表示形式如下所示(FinancialReportProcess.bpmn20.xml). 流程中包含一些主要的元素(通过点击链接可以查看更详细的BPMN 2.0 元素的说明):∙none start event 让我们认识到要开始一个流程。
∙user tasks声明一个基于用户操作的流程任务. 注意第一个任务是分派用户组accountancy的, 而第二个任务是分派到用户组management的. 查看分派用户任务章节可以得到更多怎样分派任务到用户或组的信息。
activiti工作流原理Activiti是一个强大和受欢迎的开源工作流系统。
它由世界领先的公司和开发者社区维护,提供了可靠的、易用的工作流引擎。
Activiti提供了一种灵活可靠的方法来启动、管理和跟踪每一个流程中的任务,有助于提高工作流程的办公效率和组织整体质量水平。
Activiti工作流是一种可以自动执行的流程,它用于统一组织中的业务流程,以确保按计划完成每个任务。
它是一个基于事件的系统,可以响应特定的事件,从而释放特定的流程步骤。
它可以帮助组织整理和优化业务流程,跟踪步骤和人员,提高整体的工作效率。
Activiti的功能是通过许多模块来实现的,其中包括:(1)BPMN引擎:用于创建和管理Activiti工作流,该引擎使用基于XML的BPMN规范,该规范描述了流程的各个步骤和任务。
(2)组件框架:用于扩展新的流程,它提供可以与核心引擎完全集成的组件,如任务提供者、存储实现、表单引擎和数据网关。
(3)控制台:用于管理和监控工作流运行,可以用于监控流程流向,并及时发现和解决问题。
(4)API:供用于连接Activiti引擎的API,这使用户能够将Activiti引擎与其它应用程序或服务集成。
(5)开发模块:提供了一个基于Eclipse环境的可视化工具,可以构建流程,设计存储实现,和开发用于流程执行的捕获脚本。
Activiti的核心原理是基于BPMN的事件驱动的模型,其中模型的拓扑为活动、网关以及数据结构。
模型被编码为XML,它们作为来自外部应用的事件流传递给Activiti引擎。
Activiti引擎对流程的执行有强大的控制,每当收到事件流时,它都将处理流程的下一个步骤。
Activiti会检查已完成任务的状态,并根据所定义的规则更新状态,以激活下一个任务。
Activiti支持在流程运行时动态增加或删除组件,并可以追踪特定任务的完成情况。
Activiti框架可以运行在任何可行的部署环境中,如REST或Cloud。
A c t i v i t i工作流详细讲解完整教程-CAL-FENGHAI-(2020YEAR-YICAI)_JINGBIANActiviti教程详解完整教程1.A ctiviti介绍Activiti是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理.工作流.服务协作等领域的一个开源.灵活的.易扩展的可执行流程语言框架。
Activiti基于Apache许可的开源BPM平台.创始人Tom Baeyens是JBoss JBPM的项目架构师.它的特色是提供了eclipse插件.开发人员可以通过插件直接绘画出业务流程图。
1.1工作流引擎ProcessEngine对象.这是Activiti工作的核心。
负责生成流程运行时的各种实例及数据.监控和管理流程的运行。
1.2BPMN业务流程建模与标注(Business Process Model and Notation,BPMN).描述流程的基本符号.包括这些图元如何组合成一个业务流程图(Business Process Diagram)2.准备环境2.1Activiti软件环境1) JDK1.6或者更高版本2)支持的数据库有:h2,mysql,oracle,mysql,db2等3)支持Activiti运行的jar包.可以通过maven依赖引入4)开发环境为Eclipse3.7或者以上版本.myeclipse为8.6版本2.2安装流程设计器(eclipse插件)1)打开Help ?Install New Software ?Add输入 Name: Activiti DesignerLocation: /designer/update/输入完成后.单击OK按钮等待下载完成后安装。
安装完成后在菜单选项中会出现Activiti的目录选项2.3 设置eclipse activit插件的画流程图选项打开菜单Windows --> Preferences --> Activiti -->Save 下流程图片的生成方式勾选上Create process definition image when saving the diagram操作.勾选上这个操作后在画流程图后保存eclipse会自动生成对应的流程图片。
activiti工作流使用手册一、简介activiti是一个轻量级的Java开源工作流引擎,广泛应用于各类企业应用系统中。
本手册旨在为用户提供一份全面的activiti工作流使用指南,帮助用户快速上手并灵活应用activiti工作流。
二、安装与配置1. 下载activitiactiviti官网提供最新的稳定版本下载,在官网下载页面选择合适的版本,并解压到指定目录。
2. 导入activiti库在项目中导入activiti库,可以使用Maven或其他依赖管理工具,或者手动导入activiti相关的jar包。
3. 配置数据库activiti使用数据库来存储工作流相关的数据,需要配置数据库连接信息。
在项目的配置文件中,根据使用的数据库类型,配置相应的数据源。
4. 配置activiti核心引擎在项目的配置文件中,配置activiti核心引擎。
可以配置引擎的缓存设置、任务执行器等参数,以满足具体业务需求。
三、工作流定义1. 设计流程图使用activiti提供的流程图设计器,或者其他工具设计流程图。
流程图应包含各个环节、任务和流程流转条件。
2. 定义流程根据设计好的流程图,使用activiti提供的API编写Java代码来定义流程。
流程定义包括流程的启动、流程实例的创建、任务分配等。
四、工作流执行1. 启动流程使用activiti提供的API,启动流程实例。
根据流程定义的启动条件,可以设置流程实例的变量、业务参数等。
2. 处理任务根据流程的执行情况,系统将生成一系列待处理的任务。
使用activiti提供的API,查询并处理这些任务。
任务的处理包括任务的审批、任务的分派、任务的执行等。
3. 流程流转处理任务后,根据任务处理结果,流程会自动流转到下一个环节,或者根据设置的流转条件,执行流程中的分支和合并。
5. 监控流程在流程的执行过程中,可以使用activiti提供的监控工具,实时查看流程的执行情况,包括流程实例的状态、任务的处理情况、历史记录等。
文件代码:<?xml version="1.0"encoding="UTF-8"?><definitions xmlns="/spec/BPMN/20100524/MODEL"xmlns:xsi="http://ww /2001/XMLSchema-instance"xmlns:xsd="/2001/XMLSchema"xmlns:activiti="/b pmn"xmlns:bpmndi="/spec/BPMN/20100524/DI"xmlns:omgdc="http://ww /spec/DD/20100524/DC"xmlns:omgdi="/spec/DD/20100524/DI" typeLanguage="/2001/XMLSchema"expressionLanguage="http://www.w3. org/1999/XPath"targetNamespace="/test"><process id="accruedexpense"name="预提申请"isExecutable="true"><startEvent id="startevent1"name="Start"activiti:initiator="applyUserId"></startEvent><userTask id="usertask1"name="经理审批"activiti:candidateUsers="${userInfoService.getCandidateUsers(companyUUID,departmentU UID,'部门经理')}"activiti:formKey="redirect:/accruedexpense/doTask1?f=1"></userTask><userTask id="usertask2"name="财务审批"activiti:candidateUsers="${userInfoService.getCandidateUsers(companyUUID,'','财务总监')}"activiti:formKey="redirect:/accruedexpense/doTask2?f=1"></userTask> <sequenceFlow id="flow2"sourceRef="usertask1"targetRef="exclusivegateway2"></sequ enceFlow><exclusiveGateway id="exclusivegateway2"name="Exclusive Gateway"></exclusiveGatew ay><sequenceFlow id="flow7"name="同意"sourceRef="exclusivegateway2"targetRef="usertask2"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${task1aggree==true}]]></ conditionExpression></sequenceFlow><sequenceFlow id="flow8"sourceRef="startevent1"targetRef="usertask1"></sequenceFlo w><sequenceFlow id="flow9"name="不同意"sourceRef="exclusivegateway2"targetRef="usertask3"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${task1aggree==false}]]> </conditionExpression></sequenceFlow><userTask id="usertask3"name="修改申请"activiti:assignee="${applyUserId}"activiti:formKey="redirect:/accruedexpense/modifyApply?f =1"></userTask><exclusiveGateway id="exclusivegateway3"name="Exclusive Gateway"></exclusiveGatew ay><sequenceFlow id="flow13"sourceRef="usertask2"targetRef="exclusivegateway3"></seq uenceFlow><sequenceFlow id="flow14"name="不同意"sourceRef="exclusivegateway3"targetRef="usertask3"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${task2aggree==false}]]> </conditionExpression></sequenceFlow><sequenceFlow id="flow15"sourceRef="usertask3"targetRef="usertask1"></sequenceFlo w><userTask id="usertask4"name="导出凭证"activiti:candidateUsers="${userInfoService.getCandidateUsers(companyUUID,'','核算中心主管')}"activiti:formKey="redirect:/accruedexpense/exportProof?f=1"></userTask><sequenceFlow id="flow16"name="同意"sourceRef="exclusivegateway3"targetRef="usertask4"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${task2aggree==true}]]></ conditionExpression></sequenceFlow><endEvent id="endevent1"name="End"></endEvent><sequenceFlow id="flow19"name="成功"sourceRef="waitTask"targetRef="endevent1"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${eviResult==true}]]></co nditionExpression></sequenceFlow><sequenceFlow id="flow20"name="失败"sourceRef="waitTask"targetRef="usertask4"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${eviResult==false}]]></c onditionExpression></sequenceFlow><receiveTask id="waitTask"name="等待反馈"></receiveTask><sequenceFlow id="flow21"sourceRef="usertask4"targetRef="waitTask"></sequenceFlow> </process><bpmndi:BPMNDiagram id="BPMNDiagram_accruedexpense"><bpmndi:BPMNPlane bpmnElement="accruedexpense"id="BPMNPlane_accruedexpense"> <bpmndi:BPMNShape bpmnElement="startevent1"id="BPMNShape_startevent1"><omgdc:Bounds height="35.0"width="35.0"x="32.0"y="178.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask1"id="BPMNShape_usertask1"><omgdc:Bounds height="55.0"width="105.0"x="120.0"y="168.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask2"id="BPMNShape_usertask2"><omgdc:Bounds height="55.0"width="105.0"x="428.0"y="168.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="exclusivegateway2"id="BPMNShape_exclusivega teway2"><omgdc:Bounds height="40.0"width="40.0"x="309.0"y="175.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask3"id="BPMNShape_usertask3"><omgdc:Bounds height="55.0"width="105.0"x="277.0"y="40.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="exclusivegateway3"id="BPMNShape_exclusivega teway3"><omgdc:Bounds height="40.0"width="40.0"x="589.0"y="175.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask4"id="BPMNShape_usertask4"><omgdc:Bounds height="55.0"width="105.0"x="680.0"y="168.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="endevent1"id="BPMNShape_endevent1"><omgdc:Bounds height="35.0"width="35.0"x="1000.0"y="178.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="waitTask"id="BPMNShape_waitTask"><omgdc:Bounds height="55.0"width="105.0"x="830.0"y="168.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="flow2"id="BPMNEdge_flow2"><omgdi:waypoint x="225.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="309.0"y="195.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow7"id="BPMNEdge_flow7"><omgdi:waypoint x="349.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="428.0"y="195.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="24.0"x="369.0"y="195.0"></omgdc:Bounds></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow8"id="BPMNEdge_flow8"><omgdi:waypoint x="67.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="120.0"y="195.0"></omgdi:waypoint><bpmndi:BPMNEdge bpmnElement="flow9"id="BPMNEdge_flow9"><omgdi:waypoint x="329.0"y="175.0"></omgdi:waypoint><omgdi:waypoint x="329.0"y="95.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="36.0"x="335.0"y="141.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow13"id="BPMNEdge_flow13"><omgdi:waypoint x="533.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="589.0"y="195.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow14"id="BPMNEdge_flow14"><omgdi:waypoint x="609.0"y="175.0"></omgdi:waypoint><omgdi:waypoint x="609.0"y="67.0"></omgdi:waypoint><omgdi:waypoint x="382.0"y="67.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="36.0"x="560.0"y="71.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow15"id="BPMNEdge_flow15"><omgdi:waypoint x="277.0"y="67.0"></omgdi:waypoint><omgdi:waypoint x="172.0"y="67.0"></omgdi:waypoint><omgdi:waypoint x="172.0"y="168.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow16"id="BPMNEdge_flow16"><omgdi:waypoint x="629.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="680.0"y="195.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="24.0"x="639.0"y="195.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow19"id="BPMNEdge_flow19"><omgdi:waypoint x="935.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="1000.0"y="195.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="24.0"x="949.0"y="195.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow20"id="BPMNEdge_flow20"><omgdi:waypoint x="882.0"y="168.0"></omgdi:waypoint><omgdi:waypoint x="882.0"y="80.0"></omgdi:waypoint><omgdi:waypoint x="731.0"y="80.0"></omgdi:waypoint><omgdi:waypoint x="732.0"y="168.0"></omgdi:waypoint><omgdc:Bounds height="14.0"width="24.0"x="796.0"y="84.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow21"id="BPMNEdge_flow21"><omgdi:waypoint x="785.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="830.0"y="195.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions>定时器代码(直接eclipse复制下来的格式不太好,可以直接复制到eclipse里面看起来方便):package .newglobe.oa.job;import java.util.HashMap;import java.util.List;import java.util.Map;import org.activiti.engine.RepositoryService;import org.activiti.engine.RuntimeService;import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.process.ActivityImpl;import org.activiti.engine.runtime.Execution;import org.activiti.engine.runtime.ProcessInstance;import org.springframework.beans.factory.annotation.Autowired;import ponent;import .newglobe.oa.db.mybatis.BaseDao;@Componentpublic class FlowJob {@Autowiredprivate BaseDao baseDao;@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate RepositoryService repositoryService;public void updateFlowByEvidenc(){//查询所有有结果的导出凭证Map<String,Object> paramMap = new HashMap<String,Object>();paramMap.put("sqlId","EvidenceReadDao.selectEvidenceByResult");List<Map<String,Object>> eviList =baseDao.selectList(paramMap);//查询业务list数据for(Map<String, Object> evi : eviList){String businessNo = (String) evi.get("evi_no");//业务编号,导出凭证节点的时候作为流程参数传递给流程的,所以可以根据业务编号查询唯一流程实例String result = (String)evi.get("result");//业务反馈结果//根据凭证号查询流程实例ProcessInstance processInstance =runtimeService.createProcessInstanceQuery().variableValueEquals("businessNo", businessNo).singleResult();//根据业务编号查询流程实例if(null != processInstance){String processDefinitionId = processInstance.getProcessDefinitionId();//流程定义idStringprocessInstanceId=processInstance.getProcessInstanceId();//流程实例id//判断是不是等待反馈节点ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processDefinitionI d);//流程定义实体String activitiId = processInstance.getActivityId();//活动节点idActivityImpl activity =definitionEntity.findActivity(activitiId);//得到节点实例String activName = (String)activity.getProperty("name");//得到name名称if("等待反馈".equals(activName)){//如果是则需要处理Execution execution =runtimeService.createExecutionQuery().processInstanceId(processInstanceId).activityId(activitiId).singleResult();Map<String,Object> variables = new HashMap<String,Object>();if("1".equals(result)){//导出成功,eviResult作为判断流程走向的条件参数variables.put("eviResult", true);}else if("2".equals(result)){//导出失败variables.put("eviResult", false);}runtimeService.signal(execution.getId(), variables);//完成等待反馈节点,推动流程,并且放参数}}}}}。
activiti5流程跟踪一、主要是实现跟踪当前流程执行情况,主要是查看当前流程图,以及流程目前已经执行到了哪个节点,主要原理如下:通过API 中的ProcessDiagramGenerator 类的静态方法generateDiagram 获取到当前流程图的字节流InputStream,然后读取流信息,将图片绘制到页面上,其中generateDiagram 方法有三个参数:第一个是ProcessDefinitionEntity:当前流程定义实体;第二个参数:绘制的图片类型String,eg:png;第三个参数:List highLightList,是高亮显示的节点,也就是那几个节点需要高亮显示,中是节点的 id。
a).第一个参数的获取:通过流程的key 值,获取到当前的流程定义对象ProcessDefinition,进而获取到流程定义实体对象 b).第二个参数的获取:可以直接给定值为:png c).第三个参数的获取:RuntimeService runtimeService = processEngine.getRuntimeService();// 获取运行时服务 List exectionList = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list(); For(Execution execution:exectionList){ ExecutionEntity execution = (ExecutionEntity)runtimeService .createExecutionQuery().executionId(execution.getI d()).singleResu lt();// 执行实例,execId为当前正在执行的实体ID String activitiId = execution.getActivityId();// 当前实例的执行到哪个节点 //将activitiId 存到高亮显示的中 highLightList.add(activitiId); }效果如图:。
Activiti命令拦截器和设计模式Activiti命令拦截器和责任链设计模式使用场景每个对流程的操作都可以看成一个命令command,Activiti会对每个命令进行拦截处理,Activiti的命令拦截用到了命令模式和责任链模式,命令模式的本质在于将命令进行封装,发出命令和执行命令分离;职责链模式只需要将请求放入职责链上,其处理细节和传递都不需要考虑;执行入口commandExecutor是命令执行的入口。
在命令来临时,service会调用commandExecutor的execute方法,例如runtimeService。
所以commandExecutor是命令执行的第一步。
那么Activiti是什么时候给service注入commandExecutor的呢?在ProcessEngineConfigurationImpl中init方法中会initServices,其又在初始化的时候注入commandExecutor,源码如下:public void initServices() {initService(repositoryService);initService(runtimeService);initService(historyService);initService(identityService);initService(taskService);initService(formService);initService(managementService);initService(dynamicBpmnService);}public void initService(Object service) {if (service instanceof ServiceImpl) {((ServiceImpl) service).setCommandExecutor(commandExecutor);//注入了commandExecutor}}命令模式的表现上面分析了命令执行的第一步,就是调用CommandExecutor.execute方法,然后我们跟踪去看这个execute方法,在子类CommandExecutorImpl中看到了实际的调用。
文件代码:<?xml version="1.0"encoding="UTF-8"?><definitions xmlns="/spec/BPMN/20100524/MODEL"xmlns:xsi="http://ww /2001/XMLSchema-instance"xmlns:xsd="/2001/XMLSchema"xmlns:activiti="/b pmn"xmlns:bpmndi="/spec/BPMN/20100524/DI"xmlns:omgdc="http://ww /spec/DD/20100524/DC"xmlns:omgdi="/spec/DD/20100524/DI" typeLanguage="/2001/XMLSchema"expressionLanguage="http://www.w3. org/1999/XPath"targetNamespace="/test"><process id="accruedexpense"name="预提申请"isExecutable="true"><startEvent id="startevent1"name="Start"activiti:initiator="applyUserId"></startEvent><userTask id="usertask1"name="经理审批"activiti:candidateUsers="${userInfoService.getCandidateUsers(companyUUID,departmentU UID,'部门经理')}"activiti:formKey="redirect:/accruedexpense/doTask1?f=1"></userTask><userTask id="usertask2"name="财务审批"activiti:candidateUsers="${userInfoService.getCandidateUsers(companyUUID,'','财务总监')}"activiti:formKey="redirect:/accruedexpense/doTask2?f=1"></userTask> <sequenceFlow id="flow2"sourceRef="usertask1"targetRef="exclusivegateway2"></sequ enceFlow><exclusiveGateway id="exclusivegateway2"name="Exclusive Gateway"></exclusiveGatew ay><sequenceFlow id="flow7"name="同意"sourceRef="exclusivegateway2"targetRef="usertask2"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${task1aggree==true}]]></ conditionExpression></sequenceFlow><sequenceFlow id="flow8"sourceRef="startevent1"targetRef="usertask1"></sequenceFlo w><sequenceFlow id="flow9"name="不同意"sourceRef="exclusivegateway2"targetRef="usertask3"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${task1aggree==false}]]> </conditionExpression></sequenceFlow><userTask id="usertask3"name="修改申请"activiti:assignee="${applyUserId}"activiti:formKey="redirect:/accruedexpense/modifyApply?f =1"></userTask><exclusiveGateway id="exclusivegateway3"name="Exclusive Gateway"></exclusiveGatew ay><sequenceFlow id="flow13"sourceRef="usertask2"targetRef="exclusivegateway3"></seq uenceFlow><sequenceFlow id="flow14"name="不同意"sourceRef="exclusivegateway3"targetRef="usertask3"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${task2aggree==false}]]> </conditionExpression></sequenceFlow><sequenceFlow id="flow15"sourceRef="usertask3"targetRef="usertask1"></sequenceFlo w><userTask id="usertask4"name="导出凭证"activiti:candidateUsers="${userInfoService.getCandidateUsers(companyUUID,'','核算中心主管')}"activiti:formKey="redirect:/accruedexpense/exportProof?f=1"></userTask><sequenceFlow id="flow16"name="同意"sourceRef="exclusivegateway3"targetRef="usertask4"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${task2aggree==true}]]></ conditionExpression></sequenceFlow><endEvent id="endevent1"name="End"></endEvent><sequenceFlow id="flow19"name="成功"sourceRef="waitTask"targetRef="endevent1"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${eviResult==true}]]></co nditionExpression></sequenceFlow><sequenceFlow id="flow20"name="失败"sourceRef="waitTask"targetRef="usertask4"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${eviResult==false}]]></c onditionExpression></sequenceFlow><receiveTask id="waitTask"name="等待反馈"></receiveTask><sequenceFlow id="flow21"sourceRef="usertask4"targetRef="waitTask"></sequenceFlow> </process><bpmndi:BPMNDiagram id="BPMNDiagram_accruedexpense"><bpmndi:BPMNPlane bpmnElement="accruedexpense"id="BPMNPlane_accruedexpense"> <bpmndi:BPMNShape bpmnElement="startevent1"id="BPMNShape_startevent1"><omgdc:Bounds height="35.0"width="35.0"x="32.0"y="178.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask1"id="BPMNShape_usertask1"><omgdc:Bounds height="55.0"width="105.0"x="120.0"y="168.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask2"id="BPMNShape_usertask2"><omgdc:Bounds height="55.0"width="105.0"x="428.0"y="168.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="exclusivegateway2"id="BPMNShape_exclusivega teway2"><omgdc:Bounds height="40.0"width="40.0"x="309.0"y="175.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask3"id="BPMNShape_usertask3"><omgdc:Bounds height="55.0"width="105.0"x="277.0"y="40.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="exclusivegateway3"id="BPMNShape_exclusivega teway3"><omgdc:Bounds height="40.0"width="40.0"x="589.0"y="175.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="usertask4"id="BPMNShape_usertask4"><omgdc:Bounds height="55.0"width="105.0"x="680.0"y="168.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="endevent1"id="BPMNShape_endevent1"><omgdc:Bounds height="35.0"width="35.0"x="1000.0"y="178.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="waitTask"id="BPMNShape_waitTask"><omgdc:Bounds height="55.0"width="105.0"x="830.0"y="168.0"></omgdc:Bounds> </bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="flow2"id="BPMNEdge_flow2"><omgdi:waypoint x="225.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="309.0"y="195.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow7"id="BPMNEdge_flow7"><omgdi:waypoint x="349.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="428.0"y="195.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="24.0"x="369.0"y="195.0"></omgdc:Bounds></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow8"id="BPMNEdge_flow8"><omgdi:waypoint x="67.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="120.0"y="195.0"></omgdi:waypoint><bpmndi:BPMNEdge bpmnElement="flow9"id="BPMNEdge_flow9"><omgdi:waypoint x="329.0"y="175.0"></omgdi:waypoint><omgdi:waypoint x="329.0"y="95.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="36.0"x="335.0"y="141.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow13"id="BPMNEdge_flow13"><omgdi:waypoint x="533.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="589.0"y="195.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow14"id="BPMNEdge_flow14"><omgdi:waypoint x="609.0"y="175.0"></omgdi:waypoint><omgdi:waypoint x="609.0"y="67.0"></omgdi:waypoint><omgdi:waypoint x="382.0"y="67.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="36.0"x="560.0"y="71.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow15"id="BPMNEdge_flow15"><omgdi:waypoint x="277.0"y="67.0"></omgdi:waypoint><omgdi:waypoint x="172.0"y="67.0"></omgdi:waypoint><omgdi:waypoint x="172.0"y="168.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow16"id="BPMNEdge_flow16"><omgdi:waypoint x="629.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="680.0"y="195.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="24.0"x="639.0"y="195.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow19"id="BPMNEdge_flow19"><omgdi:waypoint x="935.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="1000.0"y="195.0"></omgdi:waypoint><bpmndi:BPMNLabel><omgdc:Bounds height="14.0"width="24.0"x="949.0"y="195.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow20"id="BPMNEdge_flow20"><omgdi:waypoint x="882.0"y="168.0"></omgdi:waypoint><omgdi:waypoint x="882.0"y="80.0"></omgdi:waypoint><omgdi:waypoint x="731.0"y="80.0"></omgdi:waypoint><omgdi:waypoint x="732.0"y="168.0"></omgdi:waypoint><omgdc:Bounds height="14.0"width="24.0"x="796.0"y="84.0"></omgdc:Bounds> </bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow21"id="BPMNEdge_flow21"><omgdi:waypoint x="785.0"y="195.0"></omgdi:waypoint><omgdi:waypoint x="830.0"y="195.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions>定时器代码(直接eclipse复制下来的格式不太好,可以直接复制到eclipse里面看起来方便):package .newglobe.oa.job;import java.util.HashMap;import java.util.List;import java.util.Map;import org.activiti.engine.RepositoryService;import org.activiti.engine.RuntimeService;import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.process.ActivityImpl;import org.activiti.engine.runtime.Execution;import org.activiti.engine.runtime.ProcessInstance;import org.springframework.beans.factory.annotation.Autowired;import ponent;import .newglobe.oa.db.mybatis.BaseDao;@Componentpublic class FlowJob {@Autowiredprivate BaseDao baseDao;@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate RepositoryService repositoryService;public void updateFlowByEvidenc(){//查询所有有结果的导出凭证Map<String,Object> paramMap = new HashMap<String,Object>();paramMap.put("sqlId","EvidenceReadDao.selectEvidenceByResult");List<Map<String,Object>> eviList =baseDao.selectList(paramMap);//查询业务list数据for(Map<String, Object> evi : eviList){String businessNo = (String) evi.get("evi_no");//业务编号,导出凭证节点的时候作为流程参数传递给流程的,所以可以根据业务编号查询唯一流程实例String result = (String)evi.get("result");//业务反馈结果//根据凭证号查询流程实例ProcessInstance processInstance =runtimeService.createProcessInstanceQuery().variableValueEquals("businessNo", businessNo).singleResult();//根据业务编号查询流程实例if(null != processInstance){String processDefinitionId = processInstance.getProcessDefinitionId();//流程定义idStringprocessInstanceId=processInstance.getProcessInstanceId();//流程实例id//判断是不是等待反馈节点ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processDefinitionI d);//流程定义实体String activitiId = processInstance.getActivityId();//活动节点idActivityImpl activity =definitionEntity.findActivity(activitiId);//得到节点实例String activName = (String)activity.getProperty("name");//得到name名称if("等待反馈".equals(activName)){//如果是则需要处理Execution execution =runtimeService.createExecutionQuery().processInstanceId(processInstanceId).activityId(activitiId).singleResult();Map<String,Object> variables = new HashMap<String,Object>();if("1".equals(result)){//导出成功,eviResult作为判断流程走向的条件参数variables.put("eviResult", true);}else if("2".equals(result)){//导出失败variables.put("eviResult", false);}runtimeService.signal(execution.getId(), variables);//完成等待反馈节点,推动流程,并且放参数}}}}}。