准备工作
JDK 5+
JDK1.5以上版本
Ant 1.8.1+
Ant1.8.1以上版本,运行自带的Demo必须。开发不要求。
Eclipse 3.6.2
Eclipse3.6.2以上版本,Activiti5可视化流程设计插件必须。开发不要求。
Activiti5
下载
http://activiti.org/download.html,当前使用版本5.4。
包含的内容
下载的Activiti发布文件包含如下内容,先关注doc、dependencies下内容。
├─docs
│ ├─javadocs API DOC
│ └─userguide 用户手册
├─setup 演示程序的配置脚本
│ └─files
│ ├─cfg.activiti
│ ├─cfg.cycle
│ ├─cfg.modeler
│ ├─demo
│ ├─dependencies 依赖JAR包说明
│ │ └─libs Activiti5可能用到的所有JAR包,具体什么环境下用什么包参照上级目录的说明文件。
│ ├─h2
│ ├─tomcat
│ └─webapps
└─workspace 源代码
├─activiti-cxf-examples
├─activiti-cycle-examples
├─activiti-engine-examples
├─activiti-groovy-examples
├─activiti-modeler-examples
└─activiti-spring-examples
Activiti的持久化方式
Activiti使用Mybatis3做持久化工作,可以在配置中设置流程引擎启动时创建表。
Activiti使用到的表都是ACT_开头的。
ACT_RE_*:流程定义存储。
ACT_RU_*:流程执行记录,记录流程启动到结束的所有动作,流程结束后会清除相关记录。
ACT_ID_*:用户记录,流程中使用到的用户和组。
ACT_HI_*:流程执行的历史记录。
ACT_GE_*:通用数据及设置。
使用到的表:
ACT_GE_BYTEARRAY:流程部署的数据。
ACT_GE_PROPERTY:通用设置。
ACT_HI_ACTINST:流程活动的实例。
ACT_HI_ATTACHMENT:
ACT_HI_COMMENT:
ACT_HI_DETAIL:
ACT_HI_PROCINST:流程实例。
ACT_HI_TASKINST:任务实例。
ACT_ID_GROUP:用户组。
ACT_ID_INFO:
ACT_ID_MEMBERSHIP:
ACT_ID_USER:用户。
ACT_RE_DEPLOYMENT:部署记录。
ACT_RE_PROCDEF:流程定义。
ACT_RU_EXECUTION:流程执行记录。
ACT_RU_IDENTITYLINK:
ACT_RU_JOB:
ACT_RU_TASK:执行的任务记录。
ACT_RU_VARIABLE:执行中的变量记录。
Activiti自带的几个组件简介和配置说明
activiti-administrator
自带的用户管理系统,维护用户和组,需要配置数据连接参数,在activiti-administrator\WEB-INF\applicationContext.xml中,并加入JDBC驱动包。
activiti-cycle
PVM活动检测的,由activiti-rest提供服务,不需配置。
activiti-explorer
可以查看用户任务和启动流程,由activiti-rest提供服务,不需配置。
activiti-kickstart
简单的点对点流程定义维护工具,需要配置数据连接,把activiti.cfg.xml文件放在classes下,并加入驱动包。
activiti-modeler
在线编辑和维护流程定义的工具,最后以文件夹方式部署,需要配置activiti-modeler\WEB-INF\classes\configuration.properties文件。
activiti-probe
PVM的观测服务,由activiti-rest提供服务,不需配置,可以查看deployment、processdefinition、processinstance、database。
其他几个应用的服务提供者,需要配置数据连接,把activiti.cfg.xml文件放在classes下,并加入驱动包。
数据库
Activiti支持的数据库
Activiti database type | Versions tested | Notes |
h2 | 1.2.132 | Default configured database |
mysql | 5.1.11 |
|
oracle | 10.2.0 |
|
postgres | 8.4 |
|
db2 | DB2 9.7 using db2jcc4 | |
mssql | 2008 using JDBC jtds-1.2.4 |
名词解释
关键对象
Deployment:流程部署对象,部署一个流程是创建。
ProcessDefinitions:流程定义,部署成功后自动创建。
ProcessInstances:流程实例,启动流程是创建。
Task:任务,在Activiti中的Task仅指有角色参与的任务,即定义中的UserTask。
Execution:执行计划,流程实例和流程执行中的所有节点都是Execution,如UserTask、ServiceTask等。
服务接口
ProcessEngine:流程引擎接口,提供流程管理和运作的所有接口。
RuntimeService:运行时服务接口,提供流程启动服务,运行中流程查询,运行变量设置和获取。
TaskService:用户任务接口(UserTask),提供运行时任务查询、领取、完成、删除及变量设置用户管理等服务。
IdentityService:用户和组管理接口。
ManagementService:流程引擎管理接口。
HistoryService:流程处理查询接口,包括执行中流程查询和历史流程查询。
Activiti使用
流程定义
l 流程图如下:
l 流程定义如下:
<definitions id="definitions"
targetNamespace="http://activiti.org/bpmn20"
xmlns:activiti="http://activiti.org/bpmn"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">
<process id="financialReport" name="Monthly financial report reminder 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>
</definitions>
配置文件
默认文件名称:activiti.cfg.xml
,放在classpath下。
内容如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
<property name="jdbcDriver" value="org.h2.Driver" />
<property name="jdbcUsername" value="sa" />
<property name="jdbcPassword" value="" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
<property name="mailServerHost" value="mail.my-corp.com" />
<property name="mailServerPort" value="5025" />
</bean>
</beans>
结合Spring
l Spring中定义数据连接及事务管理
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/boss?autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
l 定义Activiti配置
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
<property name="mailServerHost" value="mail.xxxx.com" />
<property name="mailServerPort" value="25" />
<property name="mailServerDefaultFrom" value="hrj@xxxx.com" />
<property name="mailServerUsername" value="xxxx" />
<property name="mailServerPassword" value="xxxx" />
</bean>
l 定义流程引擎
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
l 定义流程中使用的对象
<bean id="myServiceTask" class="hrj.activiti.MyServiceTask">
<property name="processEngine" ref="processEngine" />
</bean>
<bean id="myActivityBehavior" class="hrj.activiti.MyActivityBehavior">
<property name="processEngine" ref="processEngine" />
</bean>
<bean id="myExecutionListener" class="hrj.activiti.MyExecutionListener">
</bean>
<bean id="valueBean" class="hrj.activiti.ValueBean">
<property name="value" value="张三李四" />
</bean>
创建流程引擎
l 根据默认的配置文件创建默认的流程引擎。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
l 也可以通过代码由ProcessEngineConfiguration创建一个流程引擎,这种方式不需要配置文件,可以在ProcessEngineConfiguration中设置配置文件中有的所有参数。
ProcessEngine processEngine = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResourceDefault()
.setMailServerHost("gmail.com")
.setJdbcUsername("mickey")
.setJdbcPassword("mouse")
.buildProcessEngine();
l 由Spring创建流程引擎。见结合Spring
部署流程
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("FinancialReportProcess.bpmn20.xml")
.deploy();
还可以通过字符串,zip包,inputStream等方式部署流程。
启动流程
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("financialReport");
启动流程使用流程定义中的process id="financialReport",可以绑定一个String
类型的businessKey和 Map类型的流程变量集合
查询任务
流程定义中,第一个任务是指定accountancy角色处理的。
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>accountancy</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
取得任务接口
TaskService taskService = processEngine.getTaskService();
查询流转到accountancy的任务
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
领取任务
如果fozzie是accountancy下的一个用户
for (Task task : tasks) {
// fozzie领取任务
taskService.claim(task.getId(), "fozzie");
}
完成任务
查询用户fozzie可处理的任务
tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
for (Task task : tasks) {
//完成任务
taskService.complete(task.getId());
}
查询
流程部署查询
DeploymentQuery deploymentQuery = repositoryService.createDeploymentQuery();
List<Deployment> deploymentList = deploymentQuery.list();
流程定义查询
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.orderByProcessDefinitionId().asc().list();
处理中的流程实例查询
RuntimeService runtimeService = processEngine.getRuntimeService();
List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().list();
处理完成的流程实例查询
HistoricProcessInstanceQuery historicProcessInstanceQuery = processEngine.getHistoryService()
.createHistoricProcessInstanceQuery();
List<HistoricProcessInstance> historicProcessInstanceList = historicProcessInstanceQuery.finished().orderByProcessInstanceStartTime().asc().list();
流程处理记录查询
l 仅得到流程中的UserTask节点
HistoricTaskInstanceQuery historicTaskInstanceQuery = processEngine.getHistoryService()
.createHistoricTaskInstanceQuery();
List<HistoricTaskInstance> historicTaskInstanceList = historicTaskInstanceQuery.processInstanceId(processInstanceId)
.orderByHistoricActivityInstanceStartTime().asc().list();
l 查询流程中所有节点
HistoricActivityInstanceQuery historicActivityInstanceQuery=processEngine.getHistoryService().createHistoricActivityInstanceQuery();
List<HistoricActivityInstance> historicActivityInstanceList = historicActivityInstanceQuery.processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
常用的节点
Start events
流程的开始,必须。
Timer start event
用于定时启动的流程,可定时启动一次,或按时重复启动流程。
定时启动一次的流程:
<startEvent id="theStart">
<timerEventDefinition>
<timeDate>2011-03-11T12:13:14</timeDate>
</timerEventDefinition>
</startEvent>
重复启动的流程:
<startEvent id="theStart">
<timerEventDefinition>
<timeCycle>R4/2011-03-11T12:13:00/PT5M</timeCycle>
</timerEventDefinition>
</startEvent>
时间格式定义参照ISO8601。
R4:重复4次。
2011-03-11T12:13:00:启动的时间。
P:重复。
T5M:每5分钟,T表示时间,5M是5分钟,05S是5秒。
Sequence flow
顺序流
描述当前的节点(开始事件,任务,子流程、结束事件等)完成后流转到哪里。
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />
有条件的顺序流
当前节点在满足定义条件后的流转方向。
<sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${order.price > 100 && order.price < 250}]]>
</conditionExpression>
</sequenceFlow>
默认的顺序流
用于关口(Gateway)之后,和条件顺序流同时存在,不满足所有条件的时候流转去哪里。
<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" 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>
Gateways
Exclusive gateway
互斥关口,流程经过关口后只会走一个顺序流,即使关口后的顺序流都是无条件的。
<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>
Parallel Gateway
并行关口,用在开头,流程经过关口后会同时经过所有顺序流,用在结尾,所有流程完成后会一起通过并行关口。
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />
<parallelGateway id="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" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />
<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />
<endEvent id="theEnd" />
User task
人工任务,必须要有人或人的组参与。
<userTask id='theTask' name='important task' >
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>kermit</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
</userTask>
Script Task
脚本任务,可以执行一段脚本,Javascript,grove都可以使用,可以在脚本中定义或修改变量,来控制流程的流转。
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy">
<script>
sum = 0
for ( i in inputArray ) {
sum += i
}
def scriptVar = "test123" //局部变量,当前脚本可用。
execution.setVariable("myVar", scriptVar) //设置变量,整个流程可用。
</script>
</scriptTask>