Activiti 工作流完整教程
目录
- 第一部分:Activiti 基础入门
- 1 什么是工作流和 BPMN?
- 2 什么是 Activiti?
- 3 为什么选择 Activiti?
- 4 核心概念(流程引擎、服务、部署、流程定义、流程实例等)
- 5 环境搭建:第一个 "Hello World" 程序
- 第二部分:核心 API 与服务
- 1
ProcessEngine:流程引擎 - 2
Service层详解:RepositoryService,RuntimeService,TaskService,HistoryService等 - 3 使用
Service进行基本操作
- 1
- 第三部分:BPMN 2.0 基础元素
- 1 流程图基本结构:
<process>,<startEvent>,<endEvent> - 2 任务:
<userTask>(用户任务),<serviceTask>(服务任务) - 3 网关:
<exclusiveGateway>(排他网关),<parallelGateway>(并行网关) - 4 流程变量:
<sequenceFlow>的条件表达式
- 1 流程图基本结构:
- 第四部分:实战案例:一个简单的请假流程
- 1 需求分析
- 2 使用 Activiti Designer 绘制流程图
- 3 部署流程定义
- 4 启动流程实例
- 5 查询和处理任务
- 6 完成任务并结束流程
- 第五部分:进阶特性
- 1 表单与任务:使用
TaskListener和ExecutionListener - 2 嵌套流程与调用活动
- 3 事件监听器
- 4 多实例任务(会签/或签)
- 5 Spring/Spring Boot 集成
- 1 表单与任务:使用
- 第六部分:最佳实践与总结
- 1 项目结构建议
- 2 版本管理
- 3 学习资源推荐
第一部分:Activiti 基础入门
1 什么是工作流和 BPMN?
- 工作流:对业务流程进行自动化管理,将工作从一个参与者传递到另一个参与者,直至完成,它关注的是“业务流程的自动化”。
- BPMN (Business Process Model and Notation):一种为业务流程建模而设计的图形化标准,它使用一套标准化的符号来绘制流程图,使得业务人员和技术人员能够无障碍地沟通,Activiti 完全支持 BPMN 2.0 标准。
2 什么是 Activiti?
Activiti 是一个开源的、灵活的、轻量级的 业务流程管理 和 工作流引擎,它基于 Apache 2.0 许可证,完全实现了 BPMN 2.0 规范,你可以用它来创建、执行、管理和监控业务流程。

3 为什么选择 Activiti?
- 标准规范:基于 BPMN 2.0,流程图可读性强,易于维护。
- 轻量级:核心 jar 包小,易于集成到任何 Java 应用中。
- 功能强大:支持丰富的流程元素,如用户任务、服务任务、网关、事件、多实例等。
- 活跃的社区:拥有庞大的用户和开发者社区,文档和案例丰富。
- 与企业级集成:可以与 Spring、Spring Boot 等主流框架无缝集成。
4 核心概念
在开始编码前,必须理解这几个核心概念:
- 流程引擎:Activiti 的核心,负责管理和执行所有流程,通过
ProcessEngine类来创建和获取。 - 部署:将你的流程定义(通常是
.bpmn20.xml文件)发布到 Activiti 中,使其可以被引擎识别和执行。 - 流程定义:一次部署的产物,描述了一个业务流程的静态结构,可以理解为流程的“蓝图”。
- 流程实例:流程定义的一次具体执行。“请假流程”是流程定义,“张三提交的请假申请”就是流程实例。
- 任务:流程执行过程中的一个工作单元,通常需要人来处理(用户任务)或系统自动处理(服务任务)。
- 服务:Activiti 提供的 API 接口,用于与引擎交互,如
RuntimeService(运行时)、TaskService(任务)等。
5 环境搭建:第一个 "Hello World" 程序
目标:部署一个最简单的流程,并启动它。
步骤 1:添加 Maven 依赖
在 pom.xml 中添加 Activiti 的核心依赖:

<dependencies>
<!-- Activiti Core -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>7.0.0.GA</version> <!-- 建议使用较新稳定版 -->
</dependency>
<!-- MySQL 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
</dependencies>
步骤 2:配置 activiti.cfg.xml
在 src/main/resources 目录下创建 activiti.cfg.xml 文件,这是 Activiti 的配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<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:mysql://localhost:3306/activiti7?characterEncoding=UTF-8&serverTimezone=UTC" />
<property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="password" />
<!-- 如果数据库表不存在,则自动创建 -->
<property name="databaseSchemaUpdate" value="true" />
<!-- 指定我们的流程定义文件部署位置 -->
<property name="deploymentResources" value="classpath*:/diagrams/*.bpmn20.xml" />
</bean>
<!-- 配置流程引擎 -->
<bean id="processEngine" class="org.activiti.engine.impl.ProcessEngineImpl" factory-bean="processEngineConfiguration" factory-method="buildProcessEngine" />
</beans>
步骤 3:创建一个简单的 BPMN 流程
在 src/main/resources/diagrams 目录下创建 hello.bpmn20.xml 文件。

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
targetNamespace="http://www.activiti.org/test">
<process id="helloWorld" name="Hello World Process">
<startEvent id="startEvent" name="Start Event"/>
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="endEvent"/>
<endEvent id="endEvent" name="End Event"/>
</process>
</definitions>
这个流程图只有一个开始事件和一个结束事件,通过一个顺序流连接。
步骤 4:编写 Java 代码
创建一个 Main 类来启动流程。
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
public class HelloWorld {
public static void main(String[] args) {
// 1. 创建流程引擎
// 默认会加载 classpath 下的 activiti.cfg.xml 文件
ProcessEngine processEngine = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResourceDefault()
.buildProcessEngine();
// 2. 获取 RepositoryService,用于部署流程
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3. 部署流程定义(如果配置了 deploymentResources,这一步可以省略)
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("diagrams/hello.bpmn20.xml")
.deploy();
System.out.println("流程部署成功,ID: " + deployment.getId());
// 4. 获取 RuntimeService,用于启动流程实例
RuntimeService runtimeService = processEngine.getRuntimeService();
// 5. 启动流程实例,key 对应 bpmn 文件中的 process id
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("helloWorld");
System.out.println("流程实例启动成功,ID: " + processInstance.getId());
System.out.println("流程实例是否结束: " + processInstance.isEnded());
}
}
运行结果:
- 程序会自动在 MySQL 数据库中创建 25 张 Activiti 相关的表。
- 控制台会输出流程部署 ID 和流程实例 ID。
- 查看
act_ru_execution表,可以看到一条流程实例正在运行的记录。 - 由于流程只有一个开始和结束节点,实例会立即结束,再次运行
processInstance.isEnded()会返回true。
第二部分:核心 API 与服务
Activiti 的 API 被组织成一系列的 Service,每个 Service 负责一个特定的功能领域。
1 ProcessEngine:流程引擎
这是所有操作的入口,通过 ProcessEngineConfiguration 构建,在 Spring/Spring Boot 环境中,通常由容器管理。
2 Service 层详解
| 服务名称 | 作用 | 主要方法 |
|---|---|---|
RepositoryService |
仓库服务,管理流程定义(部署、删除、查询等),不涉及运行时数据。 | createDeployment(), deploy(), deleteDeployment(), createProcessDefinitionQuery() |
RuntimeService |
运行时服务,管理流程实例(启动、查询、变量设置等)。 | startProcessInstanceByKey(), startProcessInstanceById(), createExecutionQuery(), setVariable() |
TaskService |
任务服务,管理用户任务(查询、完成、认领、委派等)。 | createTaskQuery(), completeTask(), claim(), addCandidateUser() |
HistoryService |
历史服务,查询历史数据(已完成的流程实例、任务等),只读。 | createHistoricProcessInstanceQuery(), createHistoricTaskInstanceQuery() |
ManagementService |
管理服务,管理和查询引擎信息(如数据库表信息、作业等)。 | getDatabaseTableNames(), createJobQuery() |
3 使用 Service 进行基本操作
以 TaskService 为例,处理任务:
// 假设我们已经有一个流程实例在运行,并且生成了一个任务
// 1. 查询当前用户的任务
List<Task> tasks = taskService.createTaskQuery()
.taskAssignee("zhangsan") // 指定处理人
.list();
for (Task task : tasks) {
System.out.println("任务ID: " + task.getId());
System.out.println("任务名称: " + task.getName());
System.out.println("任务处理人: " + task.getAssignee());
System.out.println("流程实例ID: " + task.getProcessInstanceId());
}
// 2. 完成任务
if (!tasks.isEmpty()) {
String taskId = tasks.get(0).getId();
// 可以在完成任务时设置变量
taskService.complete(taskId, "comment", "任务已完成,审批通过。");
System.out.println("任务 " + taskId + " 已完成。");
}
第三部分:BPMN 2.0 基础元素
1 流程图基本结构
<process>:流程的根元素,id是唯一标识。<startEvent>:流程的起点。<endEvent>:流程的终点,可以有多个。
2 任务
<userTask>:用户任务,需要人工处理。- 属性:
id(唯一),name(显示名),assignee(默认处理人)。 - 示例:
<userTask id="submitLeave" name="提交请假申请" assignee="employee"/>
- 属性:
<serviceTask>:服务任务,由系统自动执行。- 通常需要指定
class属性,指向一个 Java 类(该类需实现JavaDelegate接口)。 - 示例:
<serviceTask id="sendEmail" name="发送邮件" activiti:class="com.example.SendEmailTask"/>
- 通常需要指定
3 网关
网关用来控制流程的流向。
-
<exclusiveGateway>:排他网关,相当于if-else,必须有一个出口条件为true。- 通过
<sequenceFlow>的conditionExpression设置条件。 - 示例:
<exclusiveGateway id="decision" name="请假天数判断"/> <sequenceFlow id="flow_to_manager" sourceRef="decision" targetRef="managerTask"> <conditionExpression xsi:type="tFormalExpression">${days > 3}</conditionExpression> </sequenceFlow> <sequenceFlow id="flow_to_hr" sourceRef="decision" targetRef="hrTask"> <conditionExpression xsi:type="tFormalExpression">${days <= 3}</conditionExpression> </sequenceFlow>
- 通过
-
<parallelGateway>:并行网关,将流程分成多个分支,所有分支都执行完后才汇聚。
4 流程变量
流程变量是贯穿整个流程实例的数据,用于在任务间传递信息和控制流程流向。
-
设置变量:在启动流程或完成任务时设置。
// 启动时设置 Map<String, Object> variables = new HashMap<>(); variables.put("employee", "zhangsan"); variables.put("days", 5); variables.put("reason", "年假"); runtimeService.startProcessInstanceByKey("leaveProcess", variables); // 完成任务时设置 taskService.complete(taskId, "approved", true); -
使用变量:在 BPMN 表达式中使用
${variableName}来引用。
第四部分:实战案例:一个简单的请假流程
目标:实现一个员工提交申请 -> 经理审批 -> 流程结束的完整流程。
1 需求分析
- 员工(
employee)提交请假申请,需要指定请假天数。 - 如果请假天数 > 3 天,由部门经理(
manager)审批。 - 如果请假天数 <= 3 天,由人力资源(
hr)审批。 - 审批通过后,流程结束。
2 使用 Activiti Designer 绘制流程图
-
新建 BPMN 2.0 Diagram。
-
拖拽元素,绘制如下流程图:
-
关键配置:
- 任务节点:
提交请假申请:assignee=${employee}(动态指定处理人)经理审批:assignee=managerHR审批:assignee=hr
- 网关节点:
请假天数判断:类型为Exclusive Gateway。- 连接到
经理审批的流:条件为${days > 3}。 - 连接到
HR审批的流:条件为${days <= 3}。
- 任务节点:
-
将画好的流程图保存为
leaveProcess.bpmn20.xml,并放入src/main/resources/diagrams目录。
3 部署流程定义
这部分代码与 "Hello World" 类似,确保你的 activiti.cfg.xml 配置正确。
// ... 获取 processEngine ...
RepositoryService repositoryService = processEngine.getRepositoryService();
// 如果配置了 deploymentResources,部署会自动完成
// repositoryService.createDeployment().addClasspathResource("diagrams/leaveProcess.bpmn20.xml").deploy();
System.out.println("请假流程部署成功。");
4 启动流程实例
RuntimeService runtimeService = processEngine.getRuntimeService();
// 设置流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("employee", "zhangsan"); // 员工
variables.put("manager", "lisi"); // 经理
variables.put("hr", "wangwu"); // HR
variables.put("days", 5); // 请假5天
variables.put("reason", "结婚纪念日");
// 启动流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveProcess", variables);
System.out.println("请假流程实例启动成功,ID: " + processInstance.getId());
5 查询和处理任务
lisi(经理)应该能看到一个待办任务。
// 1. 经理查询自己的任务
TaskService taskService = processEngine.getTaskService();
List<Task> managerTasks = taskService.createTaskQuery()
.taskAssignee("lisi") // 指定经理
.list();
System.out.println("经理的任务数量: " + managerTasks.size());
for (Task task : managerTasks) {
System.out.println("经理任务ID: " + task.getId() + ", 任务名: " + task.getName());
// 2. 经理完成任务(审批通过)
taskService.complete(task.getId());
System.out.println("经理已审批通过任务: " + task.getId());
}
6 完成任务并结束流程
经理完成任务后,流程会走向 结束事件,整个流程实例结束。
你可以通过 HistoryService 来查询历史记录,验证流程是否正确执行。
HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstance.getId())
.singleResult();
System.out.println("流程实例最终状态: " + historicProcessInstance.getEndTime()); // 如果有结束时间,说明流程已结束
第五部分:进阶特性
1 表单与任务
在实际应用中,任务通常关联一个表单,Activiti 本身不管理表单数据,但可以通过流程变量来传递。
-
获取任务变量:
Map<String, Object> variables = taskService.getVariables(taskId); String reason = (String) variables.get("reason"); -
使用监听器:可以在任务创建或完成时执行自定义逻辑。
- 实现
TaskListener接口。 - 在
userTask中配置<taskListener event="create" class="com.example.MyTaskListener"/>。
- 实现
2 嵌套流程与调用活动
当一个流程比较复杂时,可以将其拆分为多个子流程,然后在主流程中通过 <callActivity> 来调用子流程。
3 事件监听器
Activiti 在流程生命周期中会触发多种事件(如流程开始、任务创建、结束等),你可以实现相应的监听器接口来响应这些事件。
ExecutionListener: 监听流程执行事件。TaskListener: 监听任务事件。EventListener: 监听所有事件。
4 多实例任务
用于实现“会签”(所有人都需同意)或“或签”(只要有一个人同意即可)的场景。
通过配置 multiInstanceLoopCharacteristics 实现。
5 Spring/Spring Boot 集成
这是目前最主流的使用方式,Activiti 提供了与 Spring 深度集成的能力。
- Spring Boot Starter:只需添加
activiti-spring-boot-starter依赖,并配置application.properties,即可自动配置ProcessEngine。# application.properties spring.activiti.database-schema-update=true spring.activiti.process-definition-location-pattern=classpath*:/diagrams/*.bpmn20.xml
- 优点:无需手动管理
ProcessEngine,Service会自动注入为 Spring Bean,事务管理也更加方便。
第六部分:最佳实践与总结
1 项目结构建议
src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ ├── activiti/
│ │ │ ├── listener/ // 监听器
│ │ │ ├── service/ // 业务服务
│ │ │ └── task/ // JavaDelegate 任务类
│ │ └── Application.java // Spring Boot 启动类
│ └── resources/
│ ├── activiti.cfg.xml // 如果不使用 Spring Boot
│ ├── application.properties // Spring Boot 配置
│ └── diagrams/
│ ├── hello.bpmn20.xml
│ └── leaveProcess.bpmn20.xml
2 版本管理
- 流程定义是会迭代的,当流程修改后,重新部署会生成一个新的版本。
- 使用
ProcessDefinitionQuery可以查询不同版本的流程定义。 - 启动流程实例时,可以指定版本号,或者使用最新的版本(
startProcessInstanceByKey默认使用最新版本)。
3 学习资源推荐
- 官方文档:Activiti User Guide (最重要,最权威)
- 源码:Activiti GitHub
- 书籍:《Activiti in Action》
- 社区:Stack Overflow, Activiti 官方论坛。
Activiti 是一个功能强大且灵活的工作流引擎,掌握它的关键在于:
- 理解核心概念:流程定义、实例、任务、服务等。
- 精通 BPMN 2.0:学会用图形化语言描述业务逻辑。
- 熟练使用 API:知道在什么场景下使用哪个
Service。 - 动手实践:从简单的 "Hello World" 开始,逐步构建复杂的业务流程。
希望这份教程能帮助你顺利开启 Activiti 之旅!
