Activiti:轻量级 Java 工作流引擎

FreeGuideOnline 46阅读 2026-07-03

xml org.activiti activiti-spring-boot-starter 7.1.0.M6


Spring Boot 会自动配置 Activiti 引擎,并扫描 `classpath:processes/` 下的 `.bpmn20.xml` 或 `.bpmn` 文件。

### 编写第一个流程:简单请假流程
在 `src/main/resources/processes/` 下创建 `leave.bpmn20.xml`:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:activiti="http://activiti.org/bpmn"
             targetNamespace="http://www.activiti.org/processdef">
  <process id="leaveProcess" name="请假流程" isExecutable="true">
    <startEvent id="start" />
    <sequenceFlow sourceRef="start" targetRef="apply" />
    <userTask id="apply" name="提交请假申请" activiti:assignee="${employee}" />
    <sequenceFlow sourceRef="apply" targetRef="managerAudit" />
    <userTask id="managerAudit" name="经理审批" activiti:assignee="${manager}" />
    <sequenceFlow sourceRef="managerAudit" targetRef="end" />
    <endEvent id="end" />
  </process>
</definitions>

启动流程并完成任务

在服务类中注入 RuntimeServiceTaskService

@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;

public void startLeaveProcess() {
    // 设置流程变量,指定参与者
    Map<String, Object> vars = new HashMap<>();
    vars.put("employee", "张三");
    vars.put("manager", "李经理");

    // 启动流程实例
    ProcessInstance instance = runtimeService
        .startProcessInstanceByKey("leaveProcess", vars);

    // 查询张三的任务并完成
    Task applyTask = taskService.createTaskQuery()
        .taskAssignee("张三").singleResult();
    taskService.complete(applyTask.getId());

    // 查询李经理的任务并完成
    Task auditTask = taskService.createTaskQuery()
        .taskAssignee("李经理").singleResult();
    taskService.complete(auditTask.getId());

    // 此时流程结束
}

流程设计:从简单到复杂

实际项目中流程远比线性复杂,下面介绍常见模式。

排他网关 (Exclusive Gateway)

用于根据条件走不同的分支。例如请假天数小于3天由经理审核,否则由总监审核。

BPMN 片段:

<exclusiveGateway id="gateway1" />
<sequenceFlow sourceRef="gateway1" targetRef="managerAudit">
  <conditionExpression xsi:type="tFormalExpression">${days <= 3}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="gateway1" targetRef="directorAudit">
  <conditionExpression xsi:type="tFormalExpression">${days > 3}</conditionExpression>
</sequenceFlow>

服务任务 (Service Task)

自动执行 Java 代码或调用外部服务。例如在流程中发送邮件、记录日志。

简单实现:activiti:class="com.example.MyJavaDelegate",该类需实现 JavaDelegate 接口:

public class SendEmailDelegate implements JavaDelegate {
    @Override
    public void execute(DelegateExecution execution) {
        String applicant = (String) execution.getVariable("employee");
        // 发送邮件逻辑
        System.out.println("发送邮件给 " + applicant);
    }
}

并行网关 (Parallel Gateway) 与包容网关 (Inclusive Gateway)

用于多任务并行执行或多条件分支。画图时注意分叉与合并配对。

子流程与调用活动

  • 子流程 (Sub Process):在流程内部嵌套一个子流程,适用于复杂任务的分解。
  • 调用活动 (Call Activity):调用另一个独立的流程定义,实现流程复用。

Activiti 核心 API 一览

熟悉以下服务接口是使用 Activiti 的关键。

API 服务 作用
RepositoryService 管理流程定义和部署(部署、查询、删除)
RuntimeService 启动、查询、操作流程实例与执行对象
TaskService 管理用户任务(认领、完成、委派、加签等)
HistoryService 查询历史流程实例、任务和活动记录
ManagementService 引擎管理和维护,如查询作业(Job)、执行命令行

示例:查询当前用户的任务

List<Task> tasks = taskService.createTaskQuery()
    .taskAssignee("李经理")
    .processDefinitionKey("leaveProcess")
    .list();

流程部署与版本管理

部署方式

  • 自动部署:Spring Boot 启动时扫描 processes 文件夹。
  • 编程式部署:通过 RepositoryServiceInputStream 或资源文件部署。
repositoryService.createDeployment()
    .addClasspathResource("processes/leave.bpmn20.xml")
    .deploy();

版本机制

每次部署相同 key 的流程定义会生成新版本。默认启动流程时会使用最新版本,历史运行中的实例继续沿用旧版本定义。

Activiti 与 Spring Boot 深度集成

Spring Boot Starter 为我们做了大量自动配置,可进一步自定义。

配置数据源

Activiti 默认使用项目的数据源,流程数据会与业务数据存储在同一个数据库。可以通过配置 spring.activiti 前缀属性调整行为,例如:

spring.activiti.database-schema-update=true
spring.activiti.db-history-used=true
spring.activiti.history-level=full