本教程适用于Activiti7.0.0.Beta1版本
1. Activiti 环境
1.1 Pom文件
Activiti 下载地址: http://activiti.org/download.html
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-model</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-layout</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.activiti.cloud</groupId>
<artifactId>activiti-cloud-services-api</artifactId>
<version>7.0.0.Beta1</version>
</dependency>
1.2 Activiti 支持的数据库
Activiti 数据库类型 | 测试版本 | JDBC URL 实例 | 备注 |
---|---|---|---|
h2 | 1.3.168 | jdbc:h2:tcp://localhost/activiti | 默认配置的数据库 |
mysql | 5.1.21 | jdbc:mysql://localhost:3306/activiti?autoReconnect=true | 使用 mysql-connector-java驱动测试 |
oracle | 11.2.0.1.0 | jdbc:oracle:thin:@localhost:1521:xe | |
postgres | 8.1 | jdbc:postgresql://localhost:5432/activiti | |
db2 | DB2 10.1 using db2jcc4 | jdbc:db2://localhost:50000/activiti | |
mssql | 2008 using sqljdbc4 | jdbc:sqlserver://localhost:1433/activiti |
1.3 activiti.cfg.xml
在 classpath 下创建 activiti.cgf.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/activiti_demo" />
<property name="username" value="root" />
<property name="password" value="572900" />
<property name="maxActive" value="3" />
<property name="maxIdle" value="1" />
</bean>
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="dataSource" ref="dataSource"></property>
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
关于 processEngineConfiguration 中的 databaseSchemaUpdate 参数, 通过此参数设计 activiti
数据表的处理策略,参数如下:
false(默认):检查数据库表的版本和依赖库的版本, 如果版本不匹配就抛出异常。
true: 构建流程引擎时,执行检查,如果需要就执行更新。 如果表不存在,就创建。
create-drop: 构建流程引擎时创建数据库表, 关闭流程引擎时删除这些表。
drop-create:先删除表再创建表。
create: 构建流程引擎时创建数据库表, 关闭流程引擎时不删除这些表。
2. 开始编码
2.1 数据库的创建(Java代码方式)
ProcessEngineConfiguration configuration =
ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
System.out.println(processEngine);
说明:
1、运行以上程序段即可完成 activiti 数据库创建,通过改变 activiti.cfg.xml 中
databaseSchemaUpdate 参数的值执行不同的数据表处理策略。
2 、 上 边 的 方法 createProcessEngineConfigurationFromResource 在执行时在
activiti.cfg.xml 中找固定的名称 processEngineConfiguration也可以使用重载方法调用,这时可以不用限定 processEngineConfiguration 名称
数据库表命名规则
Activiti 的表都以 ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的 API 对
应。
- ACT_RE_*: 'RE'表示 repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,
规则,等等)。 - ACT_RU_*: 'RU'表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,
等运行中的数据。 Activiti 只在流程实例执行过程中保存这些数据, 在流程结束时就会删
除这些记录。 这样运行时表可以一直很小速度很快。 - ACT_HI_*: 'HI'表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任务等
等。 - ACT_GE_*: GE 表示 general。 通用数据, 用于不同场景下。
2.2 Service
2.2.1 Service创建方式
通过 ProcessEngine 创建 Service, Service 是工作流引擎提供用于进行工作流部署、执行、管理的服务接口。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
runtimeService = processEngine.getRuntimeService();
repositoryService = processEngine.getRepositoryService();
taskService = processEngine.getTaskService();
historyService = processEngine.getHistoryService();
2.2.2 Service 总览
Service | 说明 |
---|---|
RepositoryService | activiti 的资源管理类 |
RuntimeService | activiti 的流程运行管理类 |
TaskService | activiti 的任务管理类 |
HistoryService | activiti 的历史管理类 |
ManagerService | activiti 的引擎管理类 |
-
RepositoryService是 activiti 的资源管理类, 提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工具设计的业务流程图需要使用此 service 将流程定义文件的内容部署到计算机.
除了部署流程定义以外还可以:
查询引擎中的发布包和流程定义。
暂停或激活发布包,对应全部和特定流程定义。 暂停意味着它们不能再执行任何操作了,激活是对应的反向操作。
获得多种资源,像是包含在发布包里的文件, 或引擎自动生成的流程图。
获得流程定义的 pojo 版本, 可以用来通过 java 解析流程,而不必通过 xml。 -
RuntimeService它是 activiti 的流程运行管理类。可以从这个服务类中获取很多关于流程执行相关的信息
-
TaskService
是 activiti 的任务管理类。可以从这个类中获取任务的信息。 -
HistoryService是 activiti 的历史管理类,可以查询历史信息, 执行流程时,引擎会保存很多数据(根据配置),比如流程实例启动时间,任务的参与者, 完成任务的时间,每个流程实例的执行路径,等等。 这个服务主要通过查询功能来获得这些数据。
-
ManagementService是 activiti 的引擎管理类, 提供了对 Activiti 流程引擎的管理和维护功能,这些功能不在工作流驱动的应用程序中使用,主要用于 Activiti 系统的日常维护。
3. 入门体验
3.1 流程定义
3.1.1 什么是流程定义
流程定义是线下按照 bpmn2.0 标准去描述 业务流程,通常使用 activiti-explorer(web 控制台)
或 activiti-eclipse-designer 插件对业务流程进行建模,这两种方式都遵循 bpmn2.0 标准。本教程使用activiti-eclipse-designer 插件完成流程建模。使用 designer 设计器绘制流程,会生成两个文件: .bpmn和.png
3.1.2 流程定义删除
// 流程部署id
String deploymentId = "8801";
// 通过流程引擎获取repositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
//删除流程定义, 如果该流程定义已有流程实例启动则删除时出错
repositoryService.deleteDeployment(deploymentId);
//设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式
//repositoryService.deleteDeployment(deploymentId, true);
说明:
- 使用 repositoryService 删除流程定义
- 如果该流程定义下没有正在运行的流程,则可以用普通删除。
- 如果该流程定义下存在已经运行的流程,使用普通删除报错,可用级联删除方法将流程及相关记录全部删除。 项目开发中使用级联删除的情况比较多, 删除操作一般只开放给超级管理员使用。
3.2 流程定义部署
3.2.1 什么是流程定义部署
将线下定义的流程部署到 activiti 数据库中,这就是流程定义部署,通过调用 activiti 的 api 将流程定义的 bpmn 和 png 两个文件一个一个添加部署到 activiti 中,也可以将两个文件打成 zip 包进行部署。
3.2.2 单个文件部署
分别将 bpmn 文件和 png 图片文件部署。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService =
processEngine.getRepositoryService();
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("config/ys-work.bpmn")
.addClasspathResource("config/ys-work.png")
.name("营山绩效考核111")
.deploy();
System.out.println(deploy.getDeploymentTime());
System.out.println(deploy.getId());
3.2.3 压缩包部署
// 定义zip输入流
InputStream inputStream = this
.getClass()
.getClassLoader()
.getResourceAsStream("diagram/holiday.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
// 流程部署
Deployment deployment = repositoryService.createDeployment()//
.addZipInputStream(zipInputStream)
.deploy();
System.out.println("流程部署id: " + deployment.getId());
System.out.println("流程部署名称: " + deployment.getName());
3.3 流程实例
3.3.1 什么是流程实例
参与者(可以是用户也可以是程序)按照流程定义内容发起一个流程,这就是一个流程实例。是动
态的。
流程定义与流程实例:
流程定义相当于Java写的一个类,流程实例相当于new 出来的Java对象;
他们是一个一对多的关系。
3.3.2 启动流程实例
流程定义部署在 activiti 后,就可以在系统中通过 activiti 去管理该流程的执行,执行流程表示流
程的一次执行。比如部署系统请假流程后,如果某用户要申请请假这时就需要执行这个流程,如果另外一个用户也要申请请假则也需要执行该流程,每个执行互不影响,每个执行是单独的流程实例
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 启动流程实例
ProcessInstance instance = runtimeService
.startProcessInstanceByKey("ys-work-demo");
System.out.println(instance.getName());
System.out.println(instance.getId());
3.3.3 Businesskey(业务标识)
启动流程实例时,指定的businesskey,就会在act_ru_execution #流程实例的执行表中存储businesskey。
Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业
务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据。
比如: 请假流程启动一个流程实例,就可以将请假单的 id 作为业务标识存储到 activiti 中,将来查询activiti 的流程实例信息就可以获取请假单的 id 从而关联查询业务系统数据库得到请假单信息。
代码:
// 根据流程定义的key启动一个流程实例
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey(processDefinitionKey,businessKey);
3.3.4 查询流程实例
流程在运行过程中可以查询流程实例的状态,当前运行结点等信息。
@Test
public void queryProcessInstance() {
// 流程定义key
String processDefinitionKey = "holiday";
// 获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
List<ProcessInstance> list = runtimeService
.createProcessInstanceQuery()
.processDefinitionKey(processDefinitionKey)//
.list();
for (ProcessInstance processInstance : list) {
System.out.println("----------------------------");
System.out.println("流程实例id: "
+ processInstance.getProcessInstanceId());
System.out.println("所属流程定义id: "
+ processInstance.getProcessDefinitionId());
System.out.println("是否执行完成: "
+ processInstance.isEnded());
System.out.println("是否暂停: "
+ processInstance.isSuspended());
System.out.println(" 当 前 活 动 标 识 : "
+ processInstance.getActivityId());
}
}
3.3.5 挂起、激活流程实例
某些情况可能由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行。
3.3.5.1 全部流程实例挂起
操作流程定义为挂起状态,该流程定义下边所有的流程实例全部暂停:
流程定义为挂起状态该流程定义将不允许启动新的流程实例,同时该流程定义下所有的流程实例将全部挂起暂停执行。
@Test
public void suspendOrActivateProcessDefinition() {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionId("ys-work-demo:1:2504").singleResult();
String processDefinitionId = processDefinition.getId();
// 是否挂起
boolean suspended = processDefinition.isSuspended();
if (suspended) {
//如果暂停则激活,这里将流程定义下的所有流程实例全部激活
repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
System.out.println("流程定义: " + processDefinitionId + "激活");
} else {
//如果激活则挂起,这里将流程定义下的所有流程实例全部挂起
repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
System.out.println("流程定义: " + processDefinitionId + "挂起");
}
}
3.3.5.2 单个流程实例挂起
操作流程实例对象,针对单个流程执行挂起操作,某个流程实例挂起则此流程不再继续执行, 完成该流程实例的当前任务将报异常。
@Test
public void suspendOrActiveProcessInstance() {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId("12501").singleResult();
boolean suspend = processInstance.isSuspended();
String processInstanceId = processInstance.getId();
if (suspend) {
//如果暂停则激活
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程实例: " + processInstanceId + "激活");
} else {
//如果激活则挂起
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程实例: " + processInstanceId + "挂起");
}
}
3.4 任务查询
流程启动后,各各任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户
的待办任务
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
List<Task>zhangxin = taskService.createTaskQuery()
.processDefinitionKey("ys-work-demo")
// 指定查询用户
.taskAssignee("lipeng").list();
for (Task task : zhangxin) {
System.out.println(task.getTaskDefinitionKey());
System.out.println(task.getId());
}
3.5 任务处理
任务负责人查询待办任务,选择任务进行处理,完成任务
//任务id
String taskId = "8305";
// 创建TaskService
TaskService taskService = processEngine.getTaskService();
//完成任务
taskService.complete(taskId);
System.out.println("完成任务id="+taskId)