Activiti6 中文用户指南:从环境搭建到 REST API 的实战避坑手册 简介这份资源是 Activiti6 工作流引擎的中文用户指南文档面向需要基于 BPMN 2.0 标准设计、部署与执行业务流程的 Java 开发者、架构师及流程平台运维人员。内容覆盖系统要求、快速入门、ProcessEngine 与数据库配置、Job Executor、邮件服务器与历史记录配置、Process Engine API 与查询、Spring 与 Spring Boot 集成、BAR 部署与版本控制以及 BPMN 2.0 构造中的各类事件、边界事件、中间捕获与抛出事件等目录结构完整适合从入门到进阶系统学习。资源包内共 1 个 docx 文件大小约 4.22MB为纯文档型资料便于离线查阅与检索。目前已有 1816 人学习下载读者可借助它快速掌握流程引擎配置、API 调用、Spring 整合与 BPMN 元素用法减少查阅英文原版的时间成本适合作为日常开发与排错时的案头参考。1. 从一份离线文档说起Activiti6 中文用户指南到底能帮你省下多少时间如果你正在做企业审批流、工单流转或者 OA 系统大概率绕不开 Activiti6 这个开源工作流引擎。它基于 BPMN 2.0 标准能设计、部署、执行整套业务流程Java 生态里算是老牌选手了。但真正上手时你会发现官方英文文档散落在各个版本之间搜索引擎翻出来的教程又经常对不上 6.0.0 的 API——尤其是 Job Executor 从 6.0.0 才开始独立配置很多老文章还在讲 5.x 的写法照着抄直接翻车。这份《Activiti6 中文 用户指南.docx》就是针对 6.0.0 版本整理的中文参考覆盖了从环境搭建、ProcessEngine 配置、数据库选型到 BPMN 2.0 构造、Spring 集成、REST API 的完整链路。它适合两类人一是刚接触工作流引擎、需要一份能对着敲的入门手册的开发者二是已经在用 Activiti但被某个事件边界或监听器配置卡住、需要快速查参数的老手。下面我按实际落地顺序把这份文档里最值得先啃的部分拆开讲。2. 环境搭建与 ProcessEngine 初始化从零跑通第一条流程2.1 JDK、IDE 与依赖版本怎么选文档里写得很明确JDK 7 就能跑但实际项目里我建议直接上 JDK 8 或 11因为 Activiti6 内部大量用了 Java 8 的 Lambda 和 StreamJDK 7 虽然能编译但某些表达式解析会出玄学问题。IDE 用 Eclipse 或 IntelliJ IDEA 都行文档里提到的 Eclipse Designer 插件是 12 章的内容如果你不打算在 Eclipse 里画流程图用 IDEA 配合 bpmn-js 在线编辑器也完全够。Maven 依赖是第一步。Activiti6 的核心包是activiti-engine如果你要用 Spring 集成再加activiti-spring要用 REST API 再加activiti-rest。注意版本号必须统一6.0.0 就是 6.0.0混用 6.0.0 和 6.1.0 的包会出现ProcessEngineConfiguration类找不到的报错。!-- pom.xml 核心依赖版本必须锁死 -- dependency groupIdorg.activiti/groupId artifactIdactiviti-engine/artifactId version6.0.0/version /dependency dependency groupIdorg.activiti/groupId artifactIdactiviti-spring/artifactId version6.0.0/version /dependency !-- 默认 H2 内存数据库生产环境换成 MySQL/Oracle 驱动 -- dependency groupIdcom.h2database/groupId artifactIdh2/artifactId version1.4.190/version /dependency逻辑说明activiti-engine是核心包含流程解析、执行、任务管理activiti-spring只在用 Spring 管理事务时才需要。H2 依赖是为了让默认配置能直接跑起来文档 2.3 节提到的“内存数据库”就是它。参数上H2 的版本不要低于 1.4.190否则 Activiti 建表时ACT_GE_PROPERTY表的字段长度会报错。2.2 用代码创建 ProcessEngine 并验证建表文档 3.1 节给了两种创建方式独立运行用ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration()Web 环境用createStandaloneInMemProcessEngineConfiguration()。我一般先用独立模式验证数据库连通性确认表能建出来再切到 Spring 配置。// 独立模式创建 ProcessEngine自动建表 ProcessEngineConfiguration cfg ProcessEngineConfiguration .createStandaloneProcessEngineConfiguration() .setJdbcUrl(jdbc:h2:mem:activiti;DB_CLOSE_DELAY1000) .setJdbcUsername(sa) .setJdbcPassword() .setJdbcDriver(org.h2.Driver) .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); ProcessEngine processEngine cfg.buildProcessEngine(); System.out.println(ProcessEngine 创建成功 processEngine.getName());逻辑说明setDatabaseSchemaUpdate(DB_SCHEMA_UPDATE_TRUE)是关键参数它让 Activiti 启动时自动检查并创建 25 张核心表ACT_RE_*、ACT_RU_*、ACT_HI_*、ACT_ID_*等。如果设成DB_SCHEMA_UPDATE_FALSE表不存在就直接抛异常。DB_CLOSE_DELAY1000是 H2 内存库的参数保证 JVM 不退出时数据库连接不断开否则建完表一关连接数据就没了。跑完这段代码控制台会打印建表日志最后输出ProcessEngine 创建成功default。这时候你用 H2 的 Web Console 或者命令行去查能看到ACT_RE_DEPLOYMENT、ACT_RU_EXECUTION这些表已经就位。文档 3.7 节专门列了表名说明比如ACT_HI_*是历史表ACT_RU_*是运行时表排查问题时先看这两类表的数据量就能判断流程卡在哪。2.3 数据库连接池与 JNDI 的取舍文档 3.3 和 3.4 节讲了数据库配置和 JNDI 数据源。实际项目里如果你在 Tomcat 或 WildFly 这类容器里跑用 JNDI 拿数据源是标准做法配置写在context.xml或standalone.xml里Activiti 的ProcessEngineConfiguration只需要设setDataSourceJndiName(java:comp/env/jdbc/activiti)。但如果你用 Spring Boot直接配spring.datasource更省事Activiti 的 Spring Boot Starter 会自动接管。这里有个坑JNDI 模式下setDatabaseSchemaUpdate依然要设成TRUE或者手动执行建表 SQL否则第一次部署流程时ACT_RE_DEPLOYMENT表不存在部署直接失败。我一般会在测试环境开TRUE生产环境用 Flyway 或 Liquibase 管理表结构把DB_SCHEMA_UPDATE设成FALSE避免引擎启动时误改表。3. BPMN 2.0 核心构造事件、网关与任务的实际配置3.1 计时器边界事件与错误边界事件的参数差异文档第 8 章把 BPMN 2.0 构造拆得很细其中边界事件是审批流里用得最多的。计时器边界事件挂在用户任务上用来做超时自动提醒或自动通过错误边界事件挂在服务任务上用来捕获 Java 代码抛出的异常并走补偿逻辑。!-- 计时器边界事件用户任务 30 分钟未处理则触发提醒 -- boundaryEvent idtimerBoundary attachedToRefuserTask1 cancelActivityfalse timerEventDefinition timeDurationPT30M/timeDuration /timerEventDefinition /boundaryEvent !-- 错误边界事件捕获服务任务抛出的 BPMN 错误 -- boundaryEvent iderrorBoundary attachedToRefserviceTask1 errorEventDefinition errorRefmyErrorCode / /boundaryEvent逻辑说明cancelActivityfalse表示计时器触发后不取消原任务只发提醒设成true则原任务被取消流程走边界事件的出口。timeDuration用 ISO 8601 格式PT30M是 30 分钟P1D是 1 天。错误边界事件的errorRef必须和 Java 代码里throw new BpmnError(myErrorCode)的编码一致否则捕获不到流程会直接挂掉。文档 8.2.18 节专门提了“边界事件的已知问题”如果边界事件挂在多实例任务上计时器只会对第一个实例生效。这个坑我在一个工单系统里踩过后来改成在流程变量里记录每个实例的创建时间用中间捕获事件轮询才绕过去。3.2 排他网关与并行网关的表达式写法网关是流程分支的核心。排他网关Exclusive Gateway按条件选一条路走并行网关Parallel Gateway把所有出口都走一遍。文档 8.4 节给了 XML 表示但条件表达式的变量引用方式容易写错。!-- 排他网关根据金额决定审批级别 -- exclusiveGateway iddecisionGateway / sequenceFlow idflow1 sourceRefdecisionGateway targetRefmanagerApprove conditionExpression xsi:typetFormalExpression ![CDATA[${amount 5000}]] /conditionExpression /sequenceFlow sequenceFlow idflow2 sourceRefdecisionGateway targetRefdirectorApprove conditionExpression xsi:typetFormalExpression ![CDATA[${amount 5000}]] /conditionExpression /sequenceFlow逻辑说明${amount 5000}里的amount是流程变量启动流程实例时通过runtimeService.startProcessInstanceByKey(myProcess, variables)传入。注意 XML 里和必须用 CDATA 包起来否则解析器会报错。排他网关如果没有匹配的条件会抛ActivitiException: No outgoing sequence flow found所以最好设一条默认流用defaultflow1属性指定。并行网关不需要条件表达式所有出口都会生成并发执行分支。但要注意并行网关的汇聚点会等待所有分支到达才继续如果某个分支因为异常没走到汇聚点流程就卡住了。文档 8.7 节的“异步延续”和“独占作业”就是解决这类并发问题的把服务任务设成activiti:asynctrue可以让 Job Executor 异步重试避免线程阻塞。3.3 用户任务分配与任务监听器的组合用法用户任务的分配方式文档 8.5.1 节列了三种直接指定assignee、用candidateUsers或candidateGroups做候选、通过任务监听器动态分配。实际项目里最灵活的是第三种比如根据流程变量里的部门 ID 查数据库拿到审批人。// 任务监听器动态设置审批人 public class AssigneeTaskListener implements TaskListener { Override public void notify(DelegateTask delegateTask) { String deptId (String) delegateTask.getVariable(deptId); // 模拟从数据库或远程接口查审批人 String approver lookupApproverByDept(deptId); delegateTask.setAssignee(approver); // 同时添加候选组方便转办 delegateTask.addCandidateGroup(dept_ deptId); } }逻辑说明DelegateTask提供了getVariable、setAssignee、addCandidateGroup等方法可以在任务创建、分配、完成等事件节点触发。监听器类需要在 BPMN XML 里注册userTask iduserTask1 name部门审批 activiti:assignee${approver} extensionElements activiti:taskListener eventcreate classcom.example.AssigneeTaskListener / /extensionElements /userTask参数上event可以是create、assignment、complete、delete。注意监听器里不要做耗时操作因为它在事务里同步执行查数据库太慢会拖长整个流程的响应时间。我一般把远程调用放到异步服务任务里监听器只做本地变量赋值。4. Spring 集成与 REST API把流程引擎嵌进现有系统4.1 ProcessEngineFactoryBean 与事务管理器的绑定文档第 5 章讲 Spring 集成核心是ProcessEngineFactoryBean。它把ProcessEngineConfiguration包装成 Spring Bean让流程引擎的创建和销毁交给容器管理。配置类里最关键的是SpringProcessEngineConfiguration它比独立模式多了一个transactionManager属性。Configuration public class ActivitiConfig { Bean public ProcessEngineFactoryBean processEngine(DataSource dataSource, PlatformTransactionManager txManager) { SpringProcessEngineConfiguration cfg new SpringProcessEngineConfiguration(); cfg.setDataSource(dataSource); cfg.setTransactionManager(txManager); cfg.setDatabaseSchemaUpdate(true); cfg.setAsyncExecutorActivate(true); // 6.0.0 新增激活 Job Executor ProcessEngineFactoryBean factoryBean new ProcessEngineFactoryBean(); factoryBean.setProcessEngineConfiguration(cfg); return factoryBean; } }逻辑说明setAsyncExecutorActivate(true)是 6.0.0 和 5.x 最大的区别之一。5.x 的 Job Executor 默认关闭6.0.0 如果不显式激活所有asynctrue的服务任务都不会执行流程会一直卡在ACT_RU_JOB表里。transactionManager必须和dataSource用同一个事务管理器否则流程操作和业务操作不在一个事务里回滚会出问题。文档 5.7 节的 Spring Boot 集成更简单加activiti-spring-boot-starter-basic依赖然后在application.yml里配spring.activiti.database-schema-update: true和spring.activiti.async-executor-activate: true就行。但要注意 Spring Boot 2.x 和 Activiti6 的兼容性文档 5.7.1 节明确说了只支持 Spring Boot 1.5.x 和 2.0.x用 2.1 以上版本会报NoSuchMethodError。4.2 REST API 的分页查询与变量过滤文档第 13 章的 REST API 是给前端或外部系统调用的。部署后默认路径是/activiti-rest/service/比如查流程定义列表用GET /repository/process-definitions启动流程实例用POST /runtime/process-instances。实际用的时候分页和变量过滤是两个高频需求。# 分页查询流程定义按版本倒序 curl -u admin:test http://localhost:8080/activiti-rest/service/repository/process-definitions?start0size10sortversionorderdesc # 按流程变量过滤流程实例 curl -u admin:test -X POST http://localhost:8080/activiti-rest/service/query/process-instances \ -H Content-Type: application/json \ -d { processDefinitionKey: leaveProcess, variables: [ {name: applyUser, value: zhangsan, operation: equals} ] }逻辑说明start和size是分页参数sort指定排序字段order是asc或desc。变量过滤的operation支持equals、notEquals、like、greaterThan等但注意like只对字符串类型有效数字类型用greaterThan或lessThan。文档 13.1.6 节还提到 JSON 查询变量格式如果变量是日期类型值要传 ISO 8601 字符串否则解析失败。REST API 默认用 Basic Auth用户名密码在activiti-rest/WEB-INF/classes/activiti-rest.properties里配。生产环境记得改掉默认的admin/test并且把application.path从/activiti-rest改成自己的路径避免和其他服务冲突。5. 避坑与排查那些文档没写但一定会遇到的问题5.1 现象流程部署后查不到流程定义ACT_RE_PROCDEF表为空原因BPMN 文件里的process标签id属性重复或者isExecutablefalse。Activiti 部署时不会报错但会跳过不可执行的流程定义。解决检查 BPMN XML 的process idxxx isExecutabletrue确保id全局唯一。部署后查ACT_RE_PROCDEF表的KEY_和VERSION_字段确认版本号递增。5.2 现象异步服务任务不执行ACT_RU_JOB表里堆了一堆记录原因asyncExecutorActivate没设成true或者 Job Executor 的线程池被占满。解决Spring 配置里加cfg.setAsyncExecutorActivate(true)Spring Boot 里加spring.activiti.async-executor-activate: true。如果已经开了还不执行查ACT_RU_JOB的RETRIES_字段如果小于 1 说明重试次数耗尽需要手动重置或查日志找根因。5.3 现象排他网关报No outgoing sequence flow found原因所有条件表达式都不满足且没有配置默认流。解决在排他网关上加defaultflowId属性指向一条无条件流。或者检查变量类型比如${amount 5000}里amount是字符串6000比较时会按字典序而不是数值导致条件判断错误。用${Integer.parseInt(amount) 5000}强制转换。5.4 现象历史表数据量暴涨查询越来越慢原因历史记录级别设成了full每个流程实例的变量、任务、活动都记明细。解决文档 3.12 节和历史配置章节提到historyLevel可以设成none、activity、audit、full。生产环境一般用audit只记流程实例和任务不记变量明细。在ProcessEngineConfiguration里设setHistoryLevel(HistoryLevel.AUDIT)已经跑起来的库改配置后只对新数据生效老数据需要手动归档。5.5 现象Spring Boot 启动报Cannot determine embedded database driver class原因没配数据源Spring Boot 自动配置想用内嵌 H2 但找不到驱动。解决加 H2 依赖或者在application.yml里显式配spring.datasource.url、username、password。如果用的是 MySQL驱动类名是com.mysql.cj.jdbc.DriverURL 后面加?useSSLfalseserverTimezoneUTC否则时区不对会导致流程时间戳差 8 小时。6. 进阶技巧用历史查询做流程审计与性能调优文档第 11 章的历史查询是很多人忽略的部分但它在实际运维里价值很高。比如HistoricProcessInstanceQuery可以按开始时间、结束时间、持续时间过滤用来找出耗时最长的流程实例HistoricTaskInstanceQuery可以按任务负责人和完成时间统计每个人的工作量。// 查询最近 7 天超时未完成的流程实例 ListHistoricProcessInstance overdueList historyService .createHistoricProcessInstanceQuery() .startedAfter(DateUtils.addDays(new Date(), -7)) .unfinished() .orderByProcessInstanceDuration().desc() .listPage(0, 20); for (HistoricProcessInstance hpi : overdueList) { System.out.println(流程实例 hpi.getId() 定义 hpi.getProcessDefinitionKey() 已耗时 hpi.getDurationInMillis() / 1000 / 60 分钟); }逻辑说明unfinished()过滤未结束的实例orderByProcessInstanceDuration().desc()按持续时间倒序listPage(0, 20)取前 20 条。getDurationInMillis()返回毫秒数除以 60000 得到分钟。这个查询在ACT_HI_PROCINST表上执行如果数据量大建议在START_TIME_和END_TIME_字段上加索引。另一个技巧是用HistoricVariableInstanceQuery查某个变量的历史值变化。比如审批金额被修改过几次每次的值和修改时间都能查到。文档 11.1.2 节给了 API 签名但没提性能问题ACT_HI_VARINST表默认没有变量名索引如果变量多、查询频繁手动加一个NAME_字段的索引能把查询从秒级降到毫秒级。我自己的习惯是每次上线新流程前先用历史查询跑一遍测试数据确认ACT_HI_ACTINST表里没有异常跳转再检查ACT_RU_JOB表没有堆积的异步任务。这套检查走完基本能避开 80% 的线上问题。从那以后我每次部署新流程定义都强制走一遍历史查询验证再也没出现过流程卡死到第二天才发现的情况。希望帮到你。本文还有配套的精品资源点击获取