Activiti学习资料(组件,API,部署)

Activiti学习资料14(组件介绍,API)

Activiti 组件介绍

activiti 项目由三种类型的组件组成, 分别是: 专用工具 (Dedicated Tools) 、 存储内容(St 具 ored Content) 、协作工(Collaboration Tool) 。

Activiti学习资料(组件,API,部署)_第1张图片


专用工具( 专用工具(Dedicated Tools)组件 )
此类组件,包括(内容管理)Alfresco、建模器(Activiti Modeler) 、设计器(Activiti Designer (Eclipse plugin)、管理及监控(Activiti probe) ) 、任务管理(Activiti Explorer)五个工具组件。 Alfresco—为 Alfresco 公司的企业级内容管理产品 Alfresco 是 Alfresco 公司的内容管理产品的名称(同时也是公司名称) ,它是一个开源的、企业级 的内容管理系统, 功能包括: 文档管理、 协作、 记录管理、 知识库管理、 Web 内容管理等功能。 infoWorld 被 评为了 2010 年的最佳开源应用程序。现在 Alfresco 公司作为 Activiti 项目的主要赞助厂商,自然会将其 内容管理产品与 Activiti 进行深入的集成。实际上流程中的所有资源,包括流程本身,都是被内容管理产 品所管理的资源。 Activiti Modeler—建模器 Activiti 建模器是基于开源的 Signavio 流程编辑器的一个定制版本,它提供了对 BPMN2.0 图形化 规范的支持,建模后的流程以文件格式进行存储 文件格式进行存储。在后端提供导入导出 BPMN2.0 流程定义文件的功能。 文件格式进行存储 此 建 模 器 的 优 点 是 , 它 是 基 于 web 浏 览 器 的 。 其 设 计 器 界 面 如 下 图 所 示 :

Activiti Designer—Eclipse 插件形式的设计器 此组件提供了 Eclipse 的插件,可以使得开发人员,在 Eclipse 开发工具中,进行流程的建模。建模 功能上与 Signavio 相同。 Activiti probe—管理及监控组件 它是一个对流程引擎运行期实例提供管理及监控的 web 应用程序。包含部署的管理、流程定义的管 理、数据库表的检视、日志查看、事务的平均执行时间、失败多次的工作等功能。其示意界面如下:

这是一个对于数据库表记录的查看界面,基本上是一个 demo 级别的,没有多大意义。 Activiti Explorer—任务管理组件 它是一个 web 的应用程序,提供任务管理功能和对基于历史数据的统计分析及流程实例的检查 而产生的报表功能。如下图所示:

存储内容( 存储内容(Stored Content)组件 )

此类组件包含:

 文档仓库 (Documents Repository) 模型仓库 、 (Model Repository) 、 SVN 仓库(SVN Repository) 、MVN 仓库(MVN Repository) 、Activiti 引擎(Activiti Engine) 。

其中文档仓库、SVN 仓库、MVN 仓库三个组件是为协作工具(Activiti Cycle) 提供底层的支撑。例如 BPM 开发过程中的文档,采用 Alfresco 文档仓库进行存储,采用 SVN 进行版本管理,采用 MVN(maven)作为项目构建和管理工具。模型仓库(Model Repository)实际上就是 Activiti 建模器的后端存储组件,它负责对 Activiti 建模器建模 后的流程定义文件进行存储管理。 Activiti Engine—Activiti BPM 的核心引擎 运行时核心组件,解析流程定义文件 (.bpmn20.xml 文件 ) ,将其转化为纯粹的内 存 Java 对象,以供运行时各个功能使用; Activiti 引擎,基于流程虚拟机(PVM)进行构建(关于 PVM 的详细介绍,参见 8.1.2 章节),是 Activiti 项目的绝对的底层核心组件。它可以直接运行原生的 BPMN2.0 规范格 式的流程定义。是业内目前第一个,也是唯一的一个从建模到执行,完全按照 BPMN2.0 规范进行实现的 BPM 项目。这也是笔者选择它作为 BPM 开源产品介绍的最直接原因。 Activiti 引擎具备三个重要的特性。首先就是事件监听器 事件监听器。这个特性允许引擎可以直接 事件监听器 执行一个动作(即为流程图中的某个特定的事件,定义的一段 java 代码或脚本)。这意味 着, 开发人员可以利用特定的技术细节来装饰完善一个流程, 而这个细节不会在流程图中显 示。 此特性提高了业务人员与技术人员之间的协作, 而业务人员不用面对流程图中的技术问 题。 第二个特性是定制活动 定制活动。Activiti 引擎实现了对 BPMN 的支持,有很多可直接使用的活 定制活动 动类型。 但是业务人员仍旧有可能需要一些与这些已定义的活动不匹配的活动类型。 在这种 情景下,开发人员可以采用 java 代码编写一个定制的活动,用来实现业务人员所描述的复 杂行为。这个功能应该说是非常好用的功能,因为对于商业产品来讲,活动类型都是定义好 的。是一个封装的黑盒子,是不可能提供定制功能的。 另一个创新的特性是,它提供了对某些冗长的 BPMN 规范进行实现的快捷方式或捷 提供了对某些冗长的 例如采用比 BPMN 的 XML 格式更紧凑的 XML 描述格式。 而这种 XML 格式不是 Activiti 径。


的专有扩展,它可以被转换为有效的 BPMN XML。所以说,Activiti 的流程定义,并不是 百分百的 BPMN 的 XML 格式。 协作工具( 协作工具(Collaboration Tool)组件 ) Activiti Cycle 完全是一种新类型的 BPM 组件。它是一个用来促进业务人员、开发人员 和 IT 操作人员协作的 web 应用程序。目前,大多数的 BPM 产品都关注于怎样将业务人员 创建的分析流程模型转换为可执行流程模型。实际的情况就是,这些 BPM 产品为业务人员 和开发人员提供独立的工具,但是对于他们之间的协作并没有提供很好的支持。 在现实的 场景中,业务文档有业务人员所持有,而软件程序由开发团队所管理,被部署的软件应用则 被 IT 管理人员所管理。三者之间不能很好的协作。我们可以想象这样一个场景,业务经理 用文档来维护需求和 visio 格式的流程图,开发人员管理可执行的流程和大量的 java 源文 件,IT 维护人员管理部署在 tomcat 中的.war 文件和存储在 Activiti 数据库中的流程。

Activiti Cycle 首先分为左右两个区域,左侧区域是所有交付物的浏览器,这些交付物存储在仓库中。

括: 

·一个网络驱动器,例如 Vision 图,图片,word 文档,excel 图表等; ·一个业务模型仓库,例如 Signavio 建模器中包含的 BPMN 流程模型; 

·一个 SVN 仓库,包含 java 源文件和可执行的 BPMN 流程; ·一个包含业务文档的 maven 仓库; ·Activiti 实例,包含一系列被部署的各个版本的交付组件; 右侧区域,则分为上中下三个部分,分别是左侧选中交付物的具体明细(包含查看、设定所有人、增 加关联链接) 、工作区域和讨论区。现在业务分析员、开发人员和维护人员,可以在为他们自己提供的区域 内,利用相关工具进行工作,而 Activiti Cycle 则负责组织他们的协作。


Activiti API
1. 2. 3. 4.
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService(); 
RepositoryService repositoryService = processEngine.getRepositoryService();
5. 6.
TaskService taskService = processEngine.getTaskService(); 
ManagementService managementService = processEngine.getManagementService();
7. 8. 9.
IdentityService identityService = processEngine.getIdentityService(); 
HistoryService historyService = processEngine.getHistoryService(); 
FormService formService = processEngine.getFormService();

通过 ProcessEngineBuilder 读取 activiti 的配置文件,就可以生成流程 引擎实例。 通过流程引擎实例 processEngine, 我们就可以通过 getXXXService() 取 得各种包含 workflow/BPM 方法的 service 。 

RepositoryService : 提供方法获取各种流程和部署文件的信息 .

 TaskService : 提供对任务相关的各种操作 

identityService : 管理用户和用户组。 

FormService : 获取或者绑定数据到流程实例上


RuntimeService : 提供操作部署文件,流程文件和流程实例的方法 . 

ManagementService : 提供管理员对流程引擎的监控,和流程引擎服务应用无 关。 

HistoryService : 提供正在执行和过去执行的各种流程实例信息

Activiti.cfg.xml 文件内必须包含一个 Id 为’ processEngineConfiguration’ bean。 的 processEngineConfiguration 对象可以通过解析 xml 文件得到也可以通过 java 代码得 到
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration ();

processEngineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver") ; processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:330 6/activitiautoReconnect=true"); processEngineConfiguration.setJdbcUsername("root"); processEngineConfiguration.setJdbcPassword("0000"); processEngineConfiguration.setDatabaseSchemaUpdate("true"); processEngineConfiguration.setJobExecutorActivate(false); ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();

System.out.println(processEngine.toString());



要根据你在 build.*.properties 文件指定的属性来创建数据的配置文件,在 setup 文 件内运行 ant cfg.create, 可以在 setup/build/activiti.cfg 内找到生成的配置文件。 processEngine 以及那些服务对象都是线程安全的。 ProcessEngines.getDefaultProcessEngine()会在第一次被调用时初始并构建 process engine,接下来对该方法的调用返回的都是同一个流程引擎。利用 ProcessEngines.init()、ProcessEngines.destroy()可以正确创建、关闭流程引擎。 流程初始化:xml 文件中流程定义的 id 属性(这个 id 接下来可以通过 RuntimeService 的 startProcessInstanceByKey 方法来启动该流程定义的一个新流程实例。这个方法 总是选取流程定义的最新部署版本)作为流程定义的 key 属性;xml 文件中流程定义的 name 属性作为流程定义的 name 属性,如果不指定 name 属性,那么 id 属性作为 name; 带有特定 key 的流程第一次被部署时,被分配的版本号为 1,同一 key 值的流程定义的 后续部署,版本号会被设置为比当前最大的部署版本号大 1 的值,key 属性用来区分流 程定义;流程定义的 id 属性被设置为{ processDefinitionKey } :

{ processDefinitionVersion } : { generated-id },其中 generated-id 是唯一性的 数字,用来确保缓存在集群环境下流程定义 id 的唯一性。 部署流程:

1.流程定义将存储到为 Activiti 引擎配置好了的持久化数据仓库中。因此 通过我们的部署业务流程,就确保了在重启引擎后也能获得该流程定义。

2.BPMN2.0 流 程定义文件会被解析到一个内存对象模型,可以通过 Activiti API 对它进行操作。 部署“ 1. 使用 activiti Probe 部署 2. 编程式部署 String barFileName = "path/to/process-one.bar"; ZipInputStream inputStream = new ZipInputStream(new FileInputStream(barFileName));

repositoryService.createDeployment() .name("process-one.bar") .addZipInputStrea m(inputStream) .deploy(); 

3. 使用 ant 部署 <taskdef name="deploy-bar" classname="org.activiti.engine.impl.ant.DeployBarTask"> <classpath> <fileset dir="..."> <include name="activiti-cfg.jar"/> <include name="your-db-driver.jar"/> </fileset> <fileset dir="${activiti.home}/lib"> <include name="activiti-engine-${activiti.version}.jar"/> <include name="ibatis-sqlmap-*.jar"/> </fileset> </classpath> </taskdef> <deploy-bar file=".../yourprocess.bar" /> ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("financialReport");

将创建一个流程 实例,并首先通过 start 事件。通过 start 事件后,流程会沿着 start 事件的所有输出 流执行,执行到第一个任务。此时 activiti 引擎会向持久化数据库中存储一个任务。 此时, 关联在该任务上的用户或组的分配得以解析, 并且也被存储到数据库中。 Activiti 引擎会继续流程的执行步骤直到流程进入一种等待状态, 比如用户任务。 在这样的一种 状态, 流程实例的当前状态被存储到数据库中。 流程会保持该状态直到所有用户决定完 成其任务。 那时, 流程引擎会继续执行流程直到流程进入一个新的等待状态或流程终点。


事件用于对发生在流程生命周期的事情进行建模。 

事件总是被形象成一个圆圈。 存在两 种主要的事件类型:捕获事件和抛出事件。 捕获:流程执行到该事件时,会等待事件触发。事件触发类型由内部图标或 xml 中的类型声明来定义。捕获事件视觉上可以通过白色的图标区分 抛出:流程执行到该事件时,事件就会触发。该事件触发的类型由内部图标或 xml 中的类型声明来定义。黑色图标区分。 Start 事件:总是捕获型的,从概念上将,该事件会一直等待直到触发发生。 Activiti 特有属性:formKey 和 initiator Activiti:formKey 指向一个用户必须在启动新流程实例时填写的表单模板。可以包含任何 可以包含任何 文本,用于标示你的表单。但对于内置的表单渲染,Activiti:formKey 的值最好是所在的 文本 同一个流程归档文件内的资源的引用。 <startEvent id="request" activiti:formKey="org/activiti/request.form" /> None Start 事件:没有为启动流程实例指定触发器,这意味着流程引擎不能预期什么 时候流程实例要被启动。None start 事件使用在通过调用 startProcessInstanceByXXX 方法启动流程实例 ProcessInstance processInstance = runtimeService.startProcessInstanceByXXX(); 事件。 子流程总是使用 none start 事件。由不带内图标的圆表示 表示: 事件声明: Xml 表示:不带子元素的普通 start 事件声明: <startEvent id="start" name="my start event" /> 它可以用在只启动一次的流程中, Timer start 事件用于在给定的时间点创建流程实例。 也可以用你在特定时间间隔下启动的流程。子流程不能用 timer start 事件。 子流程不能用 事件。 <startEvent id="theStart"> <timerEventDefinition> <timeDate>2011-03-11T12:13:14</timeDate> </timerEventDefinition> </startEvent> 总是抛出型的。这意味着当流程执行到结束事件时,有一个结果会 End 事件:结束事件总是抛出型 总是抛出型 被抛出。结果的类型是以事件的内部黑色图标来表示的。 None End 事件:意味着没有指定在进入该事件时抛出的结果。这样,流程引擎除了结 束当前的执行路径不会在执行任何其他操作。 Xml 表示为没有子元素的普通的 end 事件的声明。不带内部图标的粗边框圆: <endEvent id="end" name="my end event" /> 当流程执行到 error end 事件时, 会结束当前的执行路径, 并抛出 error。 Error End 事件: Error 可以被与之匹配的中间边界 error 事件捕获。如果没有找到匹配的边界 error 事 件,默认会使用 none end 事件。 Xml 表示为带有 errorEventDefinition 子元素的 end 事件。图标为内有 error 图标的特殊


end 事件 <endEvent id="myErrorEndEvent"> <errorEventDefinition errorRef="myError" /> </endEvent> 定时器事件:Timer 事件是被定义的定时器触发的事件。可以作为 start 事件、 定时器事件 executor internediate 事件或 boundary 事件来使用。只有开启 job executor 时,定时器事件 只有开启 才能被触发(即,需要在 activiti.cfg.xml 中将 jobExecutorActivat 设置为 true,默 才能被触发 认为 false)。定时器只能有一个下面的元素: 定时器只能有一个下面的元素: 定时器只能有一个下面的元素 1. timeDate imeDate:该格式以 ISO 8601 格式指定了触发事件的确定时间 imeDate <timerEventDefinition> <timeDate>2011-03-11T12:13:14</timeDate> </timerEventDefinition> 2. timeDuration timeDuration:指定定时器事件在触发前运行多长时间, <timerEventDefinition> <timeDuration>P10D</timeDuration> </timerEventDefinition> 3. timeCycle timeCycle:指定循环的时间间隔 <timerEventDefinition> <timeCycle>R3/PT10H</timeCycle> </timerEventDefinition> 示例: <boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport"> <timerEventDefinition> <timeDuration>${duration}</timeDuration> </timerEventDefinition> </boundaryEvent> 顺序流 <sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" /> 带条件的顺序流:可以在顺序流上定义条件。当顺序流左侧是 BPMN2.0 的活动时,就会 带条件的顺序流 计算输出顺序流上的条件。选取条件成立的输出顺序流来执行。 带条件的顺序流是以 xml 中含有 conditionExpression 子元素的普通流来表示。 目前仅支持 tFormalExpression,目前 conditionExpression 只能使用 UEL UEL,在此使用的表达式的解析 的结果必须是布尔类型的值。 <sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask"> <conditionExpression xsi:type="tFormalExpression"> <![CDATA[${order.price > 100 && order.price < 250}]]>

</conditionExpression> </sequenceFlow> 默认顺序流: 只有当没 默认顺序流 所有的 BPMN2.0 任务以及 getways 都可以有一个默认的顺序流。 有其他顺序流被选取的情况下,才选取该顺序流。 <exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" default default="flow2" /> <sequenceFlow id="flow1" sourceRef="exclusiveGw" targetRef="task1"> <conditionExpression xsi:type="tFormalExpression">${conditionA}</conditionExpression> </sequenceFlow> <sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="task2"/> <sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="task3"> <conditionExpression xsi:type="tFormalExpression">${conditionB}</conditionExpression> </sequenceFlow> 单一分支( Gateway) 单一分支(Exclusive Gateway)当多个顺序流条件为 true 的情况下,xml 中最先定义 的那个被选取来继续流程的执行。如果没有选取到任何顺序流,就会抛出异常。 <exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" /> <sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="theTask1"> <conditionExpression xsi:type="tFormalExpression">${input == 1}</conditionExpression> </sequenceFlow> <sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="theTask2"> <conditionExpression xsi:type="tFormalExpression">${input == 2}</conditionExpression> </sequenceFlow> <sequenceFlow id="flow4" sourceRef="exclusiveGw" targetRef="theTask3"> <conditionExpression xsi:type="tFormalExpression">${input == 3}</conditionExpression> </sequenceFlow> 并行分支( gateway) 并行分支(parallel gateway) 如果 parallel gateway 有多个输入流和输出流,那 么它可以同时具有 fork 和 Join 行为。那样,gateway 会在拆分出多个并发的执行路径 前,首先合并所有的输入流。parallel gateway 不会计算条件,如果在连接 parallel parallel 不会计算条件, gateway 上定义了条件,那么那些条件会被简单的忽略掉。 <startEvent id="theStart" /> <sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

<parallelGateway id="fork /> fork" fork

<sequenceFlow sourceRef="fork" targetRef="receivePayment" /> <sequenceFlow sourceRef="fork" targetRef="shipOrder" />

<userTask id="receivePayment" name="Receive Payment" /> <sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask id="shipOrder" name="Ship Order" /> <sequenceFlow sourceRef="shipOrder" targetRef="join" />

<parallelGateway id="join /> join" join <sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask id="archiveOrder" name="Archive Order" /> <sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent id="theEnd" /> 用户任务: 行当流程执到这样的用户任务 用户任务 用来对那些需要人参与完成的工作进行建模。 时,会在分配任务的用户或用户组的任务列表中创建新的任务。 <userTask id="theTask" name="Schedule meeting" > <documentation> Schedule an engineering meeting for next week with the new hire. </documentation> Documentation 用来定义描述,可以在 Java 中获得:task.getDescription() 1.到期时间: 1.到期时间:有个 activity 的扩展,允许在创建任务时,在任务定义中指定一个表达式来 到期时间 设置任务初始的超期时间。该表达式结果必须为 java.util.Date 或 null。 <userTask id="theTask" name="Important task" activiti:dueDate="${dateVariable}"/> 2.用户的分配,通过 humanPerformer 子元素来完成的,需要 resourceAssignmentExpression 元素 <userTask id='theTask' name='important task' > <humanPerformer humanPerformer> humanPerformer <resourceAssignmentExpression> <formalExpression>kermit</formalExpression> </resourceAssignmentExpression> </humanPerformer> </userTask> 执行者分配到任务上 代理人, 只能有一个用户作为执行者分配到任务上,该用户称为代理人,存在代理人的任务在其他 代理人 只能有一个用户作为执行者分配到任务上 人的任务列表中是不可见的, 这些任务存在于所谓的代理人个人任务列表中。 直接分配给用

户的任务可以通过 TaskService 来获取。 taskService.createTaskQuery().taskAssignee("kermit").list(); List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list(); 也可以把任务放进所谓的人员候选任务列表 候选任务列表中。需要用到 potentialOwner。 候选任务列表 <userTask id='theTask' name='important task' > <potentialOwner> <resourceAssignmentExpression> <formalExpression>user(kermit), group(management)</formalExpression> </resourceAssignmentExpression> </potentialOwner> </userTask> 获取: List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit"); 如果不给文本字符串指定是用户还是用户组, 流程引擎默认认为是用户组。 因此下面这与声 明为 group(accountancy)效果是一样的。 <formalExpression>accountancy</formalExpression> Activiti 对于任务分配的扩展 1. assignee 属性 属性:这个自定义扩展允许将用户任务直接分配给用户 <userTask id="theTask" name="my task" activiti:assignee="kermit" /> 2. candidateUsers 属性 属性:这个自定义扩展可以使用户成为任务的候选者 <userTask id="theTask" name="my task" activiti:candidateUsers="kermit, gonzo" /> 3. candidateGroups 属性 属性:这个自定义扩展允许为任务定义一组候选者。 <userTask id="theTask" name="my task" activiti:candidateGroups="management, accountancy" /> 如果以上方案仍然不够,那么可以委托给使用了 create 事件上的任务监听器的自定义分配 逻辑: <userTask id="task1" name="My task" > <extensionElements> <activiti:taskListener event="create" class="org.activiti.MyAssignmentHandler /> MyAssignmentHandler" MyAssignmentHandler </extensionElements> </userTask>

public class MyAssignmentHandler implements TaskListener {

public void notify(DelegateTask delegateTask) { // 在此执行自定义的身份查找

// 接下来,例如调用以下方法: delegateTask.setAssignee("kermit"); delegateTask.addCandidateUser("fozzie"); delegateTask.addCandidateGroup("management"); ... } } 下面的例子中,代理人是通过调用 Spring bean ldapService 中的方法 findManagerOfEmployee 来设置的。 <userTask id="task" name="My Task" activiti:assignee="${ldapService.findManagerForEmployee(emp)}"/> 只有当被调用的方法返回类型是 String 或 Collection<String> 对于候选用户和候选组) (对于候选用户和候选组) 才能生效。 才能生效。 脚本任务是自动的活动,当流程执行到脚本任务时,执行相应的脚本。 脚本任务 通过指定 script 和 scriptFormat 来定义脚本任务 <scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy"> <script> sum = 0 for ( i in inputArray ) { sum += i } </script> </scriptTask> 服务任务用来调用外部 java 类,要实现在流程执行期间调用类,该类需要实现 Java 服务任务 org.activiti.engine.delegate.javaDelegate 接口,在 excute 方法中提供必要的逻 辑,当流程执行到此步时,会执行定义在该方法中的逻辑。 1. 指定实现了 javaDelegate 或 ActivitiBehavior 的类 <serviceTask id="javaService" name="ServiceTask"

activiti:class="org.activiti.MyJavaDelegate" /> activiti:class 2. 解析结果为对象的表达式,delegateExpression 是一个定义在 Spring 容器中的实现了 javaDelegate 接口的 bean。 <serviceTask id="serviceTask" activiti:delegateExpression="${delegateExpressionBean}" /> activiti:delegateExpression 3. 调用方法表达式,UEL 方法表达式 <serviceTask id="javaService" name="My Java Service Task"

activiti:expression="#{printer.printMessage()}" /> activiti:expression 4. 值表达式

<serviceTask id="javaService"

name="My Java Service Task"

activiti:expression="#{split.ready}" /> activiti:expressio 5. 只会创建定义在 serviceTask 上的 java 类的一个实例 类的一个实例。所有流程实例共享同一个用于 调用 execute(DelegateExecution)的类的实例, 这意味着, 该类中一定不要使用成员变 量,并且必须是线程安全的,因为可能会在不同的线程中同时执行该方法。 6. 流程定义中引用的类在部署时不会被实例化 部署时不会被实例化。只有当流程第一次执行到该类的时候,才 部署时不会被实例化 创建该类的实例。如果找不到该类,会抛出 ActivitiException。 处理异常:在执行自定义的逻辑时,常常需要捕获某种异常。一个常见的用例是一旦某 处理异常 条路径上发生异常,将流程导向另一条路径 <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" />

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); }

} 任务:用于同步调用外部 web 服务。待续 WebService 任务 待续 业务规则任务:用于同步执行一个或更多规则集或规则。Activiti 使用 Drools Expert 业务规则任务 和 Drool 规则引擎来执行业务规则。为此,包含着业务规则的.drl 文件必须与定义了

业务规则任务的流程定义一同部署才能执行这些规则。 这意味着流程中使用的所有.drl 文件必须像任务表单一样被打包到流程的 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 文件中定义的一组规则,由逗号分开 <businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}" activiti:rules="rule1, rule2" /> 定义除了某些规则外其他的执行,例:除了 rule1 和 rule2 之外都执行 <businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}" activiti:rules="rule1, rule2" exclude="true" /> Email 任务:其不是 BPMN2.0 规范中的“办公”任务。因此,activiti 中 mail 任务是 任务 作为特有服务任务来实现的。Activiti 引擎使用外部的 SMTP 邮件服务器来发送 e-mails,需要在文件 activiti.cfg.xml 中配置: 属性 mailServerHost MailServerPort mailServerDefaultFrom 是否必须? 否 是 否 描述 邮件服务器主机名,默认是 localhost SMTP 通信端口,默认是 25 在不提供发件人 e-mail 时,默认是 [email protected] mailServerUsername mailServerPassword 如果适合你的服务器 如果适合你的服务器 默认不设置 默认不设置

Email 任务是作为特有的服务任务来实现的 <serviceTask id="sendMail" activiti:type="mail" type="mail"> type="mail"

Email 任务是通过字段注入来配置的。 所有那些属性的值都可以含有流程执行期间解析的 EL 表达式。 <serviceTask id="sendMail" activiti:type="mail"> <extensionElements> <activiti:field name="from stringValue="[email protected]" /> from" from <activiti:field name="to expression="${recipient}" /> to" to <activiti:field name="subject expression="Your order ${orderId} has been subject" subject shipped" /> <activiti:field name="html html"> html <activiti:expression> <![CDATA[ <html> <body> Hello ${male 'Mr.' : 'Mrs.' } ${recipientName},<br/><br/>

As of ${now}, your order has been <b>processed and shipped</b>.<br/><br/>

Kind regards,<br/>

TheCompany. </body> </html> ]]> </activiti:expression> </activiti:field> </extensionElements> </serviceTask> 手动任务定义了 BPM 引擎之外的任务。 用来对那些需要人来完成的工作进行建模, 引擎 手动任务 不需要知道他是系统还是 UI 接口。对引擎而言,手动任务是作为直接通过的活动 直接通过的活动处理 直接通过的活动 的,流程执行到此会自动继续流程的执行。 <manualTask id="myManualTask" name="Call client for more information" /> 接收任务: 目前, 我们仅实现了该任务的 java 语义。 Java 接收任务 是等着消息到来的简单任务。 当流程执行到接受任务时,流程状态被提交到持久化数据库中。这意味着,流程将进入 一种等待状态,直到引擎接收到明确的消息,来触发流程通过接收任务继续执行。 <receiveTask id="waitState" name="wait" />

执行(execution)监听器:允许在流程执行期间发生某些事件时执行外部 java 代码或 执行(execution)监听器 (execution)监听器 计算表达式。可捕获的事件: 流程实例的启动或结束 迁移 活动的开始和结束 <process id="executionListenersProcess">

<extensionElements> <activiti:executionListener activiti:executionListener class="org.activiti.examples.bpmn.executionlistener.ExampleExecutionListenerOne " event="start" /> </extensionElements>

<startEvent id="theStart" /> <sequenceFlow sourceRef="theStart" targetRef="firstTask" />

<userTask id="firstTask" /> <sequenceFlow sourceRef="firstTask" targetRef="secondTask"> <extensionElements> <activiti:executionListener activiti:executionListener class="org.activiti.examples.bpmn.executionListener.ExampleExecutionListenerTwo " /> </extensionElements> </sequenceFlow>

<userTask id="secondTask" > <extensionElements> <activiti:executionListener activiti:executionListener expression="${myPojo.myMethod(execution.event)}" event="end" /> </extensionElements> </userTask> <sequenceFlow sourceRef="secondTask" targetRef="thirdTask" /> <userTask id="thirdTask" /> <sequenceFlow sourceRef="thirdTask" targetRef="theEnd" /> <endEvent id="theEnd" /> </process>

监听器是个外部类需要实现 org.activiti.engine.delegate.ExecutionListener 接口,当 事件发生时,调用方法 notify(ExecutionListenerExecution execution)。 public class ExampleExecutionListenerOne implements ExecutionListener {

public void notify(ExecutionListenerExecution execution) throws Exception { execution.setVariable("variableSetInExecutionListener", "firstValue"); execution.setVariable("eventReceived", execution.getEventName()); } 迁移(第二个监听器)上的监听器的 event 属性值会被忽略掉。 任务监听器:用来执行自定义的 java 逻辑或事件相关的表达式。任务监听器只能作为 任务监听器 用户任务的子元素添加到流程定义中。 <userTask id="myTask" name="My Task" > <extensionElements> <activiti:taskListener event="create" activiti:taskListener class="org.activiti.MyTaskCreateListener" /> </extensionElements> </userTask> 属性:触发调用任务监听器的任务事件的类型。可能有的类型有 Event 属性 Create:在创建任务、并且任务的所有属性被设置后发生。 reate Assignment: 在任务分配给某人后发生。 userTask, 当流程执行到 userTask, 首先触发 assignment 事件, 事件。 事件,然后触发 create 事件。 Complete:在任务完成,并且任务从运行时的数据中被删除之前发生。 omplete 属性:被调用的代理类。需实现 Class 属性 org.activiti.engine.impl.pvm.delegate.TaskListener 接口。 属性:指定事件发生时执行的表达式。不能与 class 属性一块使用 Expression 属性 <activiti:taskListener event="create" expression="${myObject.callMethod(task, task.eventName)}" /> 属性:允许指定一个结果是实现了 TaskListener 接口对象的表达式。 delegateExpression 属性 <activiti:taskListener event="create" delegateExpression="${myTaskListenerBean}" /> 多实例:为流程中某个步骤定义重复的一种方式。Gateway 和事件不能是多实例的。按 多实例 照规范要求,每个被创建出来的执行路径实例的父执行路径都有如下的变量: nrOfInstances:实例总数 nrOfActiveInstances:当前活跃的实例,也就是还没完成的实例的个数。顺序的 多实例,该值总是 1. nrOfCompleteInstances:当前完成的实例的个数。

loopConter:表示 for-each 循环中的实例的索引。 被创建出来的执行路径的都有一 个执行路径本地的变量(即,对其他执行路径是不可见的。)。 如果一个活动是多实例的,这可以用活动底部的三条短线来表示。3 条垂直竖线表 示并行执行,而 3 条水平线表示顺序执行。 <multiInstanceLoopCharacteristics isSequential="false|true"> ... </multiInstanceLoopCharacteristics> isSequential 表示是否按顺序执行。 一旦进入该活动,就计算实例的个数。 一旦进入该活动,就计算实例的个数。 其一是使用 loopCardinality 子元素直接指定个数 <multiInstanceLoopCharacteristics isSequential="false|true"> <loopCardinality>5</loopCardinality> </multiInstanceLoopCharacteristics> 也可以用结果是正数的表达式 <multiInstanceLoopCharacteristics isSequential="false|true"> <loopCardinality>${nrOfOrders-nrOfCancellations}</loopCardinality> </multiInstanceLoopCharacteristics> 另一种定义实例个数的方式是指定变量名, 另一种定义实例个数的方式是指定变量名,它是一个利用 loopDataInputRef 子元素的集 合。会为集合中的每一项创建一个实例。作为一个选择,可以使用 inputDataItem 子元素 会为集合中的每一项创建一个实例。作为一个选择, 将集合中某项设置给相应的执行实例。 例子展示的: 将集合中某项设置给相应的执行实例。如下面的 XML 例子展示的: <userTask id="miTasks" name="My Task ${loopCounter}" activiti:assignee="${assignee}"> isSequential="false"> <loopDataInputRef>assigneeList</loopDataInputRef> <inputDataItem name="assignee" /> </multiInstanceLoopCharacteristics> </userTask> 或 <userTask id="miTasks" name="My Task" activiti:assignee="${assignee}"> <multiInstanceLoopCharacteristics isSequential="true" activiti:collection="${myService.resolveUsersForTask()}" activiti:collection activiti:elementVariable activiti:elementVariable="assignee" > entVariable </multiInstanceLoopCharacteristics> </userTask> 当所有实例完成后,多实例活动就结束了。然而,可以指定一个表达式每次实例结束时就对 其进行计算。当表达式值为 true 时,就会销毁所有剩余的实例,并结束该多实例活动,向 下继续执行流程。。这样的表达式必须定义在子元素 completionCondition 内。 <multiInstanceLoopCharacteristics

<userTask id="miTasks" name="My Task" activiti:assignee="${assignee}"> <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee" > <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.6 }</completionCondition> </multiInstanceLoopCharacteristics> </userTask> 边界事件: 边界事件 关联在活动上的捕获型的事件(不能将边界事件抛出)。 这意味着会一直监听 着某一类型的触发器。当捕获到事件时,活动被打断,沿事件输出的顺序流继续执行。 定义边界事件要有: 唯一的标识符(流程全局性的) 使用 attachedToRef 属性定义的该事件依附到的活动的引用。 边界事件定义的层次与它们关 联的活动在同一层(活动内部不包含边界事件) <boundaryEvent id="myBoundaryEvent" attachedToRef attachedToRef="theActivity"> <XXXEventDefinition XXXEventDefinition/> XXXEventDefinition </boundaryEvent> 定时器边界事件:当执行到边界事件关联到的活动时,启动定时器。当触发定时器时, 定时器边界事件 活动被打断,沿着定时器边界事件输出流顺序继续执行。 <boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport"> <timerEventDefinition> <timeDuration>PT4H</timeDuration> </timerEventDefinition> </boundaryEvent> 边界事件:捕获定义该活动的作用域内的抛出的 errors。 当捕获到 error 事件后, Error 边界事件 定义边界事件的活动就会被销毁, 同时也销毁其内所有的执行路径。 流程沿着边界事件 的输出流继续执行。 <boundaryEvent id="catchError" attachedToRef="mySubProcess"> <errorEventDefinition errorRef="myError"/> </boundaryEvent> 如果省略 errorRef, 边界 error 事件将捕获任何 error 事件, 不管该 error 的 errorCode 是什么。 如果提供了 errorRef,并指向了一个现有的 error,那么此边界事件将只捕获同样出错码 的 errors。 如果提供了 errorRef,但没有在 BPMN 2.0 文件中定义任何 error,那么 errorRef 做为 errorCode 来使用(类似于 error end 事 件 )。

定时器中间媒介捕获事件:流程执行到捕获事件的活动时,启动定时器,定时器被触发 定时器中间媒介捕获事件 后,会沿着定时器中间媒介事件的输出顺序流执行。 <intermediateCatchEvent id="timer"> <timerEventDefinition> <timeDuration>PT5M</timeDuration> </timerEventDefinition> </intermediateCatchEvent> 子流程:含有其他活动、gateways、事件等的活动。他是一个有它自己形式的流程,作 子流程 为更大流程的一部分。 子流程为事件创建了新的作用域。 子流程执行期间抛出事件可以 被子流程边界上的边界事件捕获,因此针对事件创建的作用域只局限在子流程内。 子流程是通过 subprocess 元素来定义的。所有属于子流程的活动、gateways、事件等都要 封装在这个元素内 <subProcess id="subProcess"> <startEvent id="subProcessStart" /> ... other subprocess elements ... <endEvent id="subProcessEnd" /> </subProcess> 调用活动(子流程) 调用活动引用的是流程定义之外的流程, 而子流程是嵌入在流程定 调用活动(子流程): 义内的。调用活动的主要用例是创建可供其它多个流程定义调用的可重用的流程定义。 传递参数 <callActivity id="callSubProcess" calledElement calledElement="checkCreditProcess" > <extensionElements> <activiti:in source="someVariableInMainProcess" activiti:in target="nameOfVariableInSubProcess" /> <activiti:out source="someVariableInSubProcss" activiti:out target="nameOfVariableInMainProcess" /> </extensionElements> </callActivity>

activiti-explorer源码下载地址:https://github.com/HSSC/activiti-explorer

你可能感兴趣的:(api,活动,任务,transition,引擎,subprocess)