news 2026/9/18 12:56:23

Camunda 7 External Task Client Spring Boot Starter 实战指南:基于 REST API 实现外部任务 Worker

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Camunda 7 External Task Client Spring Boot Starter 实战指南:基于 REST API 实现外部任务 Worker

Camunda 7 External Task Client Spring Boot Starter 实战指南:基于 REST API 实现外部任务 Worker

【免费下载链接】camunda-bpm-platformCamunda 7 CE is End of Life (EoL). Please check out Camunda 8 instead (https://github.com/camunda/camunda) or read about Camunda 7 Enterprise End of Life (https://camunda.com/blog/2025/02/camunda-7-enterprise-end-of-life-extension/) – Camunda 7 CE was a flexible framework for workflow and decision automation using BPMN and DMN.项目地址: https://gitcode.com/GitHub_Trending/ca/camunda-bpm-platform

本文以 Camunda 7 平台的camunda-bpm-spring-boot-starter-external-task-client为核心,系统讲解如何通过 Spring Boot Starter 将外部系统接入 Camunda 工作流引擎:Worker 通过引擎 REST API 完成外部服务任务的 fetch(拉取)、lock(锁定)与 complete(完成)。读完本文,你将掌握依赖引入、application.yml属性配置、注解式 Topic 订阅、纯 Spring 集成方式,以及客户端自动装配与属性合并的底层实现原理。

概述:External Task 模式与 Starter 的定位

在 Camunda 的 BPMN 流程建模中,Service Task既可以由引擎内部委托代码(JavaDelegate)执行,也可以被建模为外部任务(External Task),交给运行在引擎之外的 Worker 进程处理。这种"外部任务"模式将业务系统与流程引擎解耦:流程引擎只负责发布任务、锁定任务、接收结果,而真正的业务逻辑(如调用第三方接口、执行耗时计算)由独立部署的 Worker 完成。

本 Starter 正是为此而生。仓库中的 spring-boot-starter/starter-client/README.md 明确指出:该 Starter 允许你实现一个 Camunda External Task Worker,它使用 Camunda REST API 来 fetch、lock 和 complete 外部服务任务,并基于 Java External Task Client(即 clients/java 目录下的camunda-external-task-client-java客户端)构建。因此它具备以下特点:

  • 无需在 Worker 侧部署引擎,只需能访问引擎的 REST 端点;
  • 天然适合微服务架构、多语言/异构系统参与工作流;
  • Worker 可水平扩展,多个 Worker 实例可同时订阅同一 Topic,由引擎按锁机制分发任务。

引入依赖

在 Spring Boot 项目中添加如下 Maven 依赖即可开始使用:

<dependency> <groupId>org.camunda.bpm.springboot</groupId> <artifactId>camunda-bpm-spring-boot-starter-external-task-client</artifactId> <version>...</version> </dependency>

该坐标与仓库中的实际模块一致:模块目录为 spring-boot-starter/starter-client/spring-boot,其pom.xml中的 artifactId 正是camunda-bpm-spring-boot-starter-external-task-client。从该模块的pom.xml可以确认,它会传递依赖camunda-external-task-client-spring(Spring 集成层)、spring-boot-autoconfigurespring-boot-starter,因此你无需额外手工引入 REST 客户端或 JSON 序列化相关依赖。

在 application.yml 中配置客户端与订阅

Starter 的核心配置入口是camunda.bpm.client前缀,绑定到 ClientProperties.java(标注了@ConfigurationProperties(prefix = "camunda.bpm.client")),由 ClientAutoConfiguration.java 中的@EnableConfigurationProperties({ClientProperties.class})自动启用。

README 给出了一个最小可用示例,其中base-url指向 Camunda 引擎 REST API,subscriptions以 Topic 名为 key 配置订阅过滤条件:

camunda.bpm.client: base-url: http://localhost:8080/engine-rest subscriptions: creditScoreChecker: process-definition-key: loan_process include-extension-properties: true variable-names: defaultScore

客户端级(Client 级)配置项

ClientProperties继承自 ClientConfiguration.java,以下属性可配置在camunda.bpm.client下(YAML 中采用 kebab-case,如base-urlworker-idmax-tasks):

配置项类型/默认值说明
base-urlString,必填Camunda Runtime REST API 的基础地址,例如http://localhost:8080/engine-rest
worker-idString,默认自动生成引擎感知的 Worker 标识。若未指定,会自动生成"主机名 + 随机 128 位 UUID"的组合,参见 EnableExternalTaskClient.java 中workerId()的 Javadoc。多实例部署时建议显式配置唯一值。
max-tasksint,默认 10单次请求最多拉取的任务数。
use-priorityboolean,默认true是否按任务优先级取任务。
use-create-timeboolean,默认false是否按任务创建时间取任务。
order-by-create-timeasc/desc配合use-create-time指定排序方向,常量见 EnableExternalTaskClient.java 中的STRING_ORDER_BY_ASC_VALUE/STRING_ORDER_BY_DESC_VALUE
async-response-timeoutlong(毫秒)长轮询(异步响应)超时。设置后 fetch-and-lock 请求会挂起等待任务到来,避免空轮询对引擎造成压力;不设置则同步立即返回。
lock-durationlong(毫秒),默认 20000客户端全局锁定时长,必须大于 0。会被订阅级lock-duration覆盖。
date-formatString,默认yyyy-MM-dd'T'HH:mm:ss.SSSZ日期类型变量的序列化/反序列化格式。
default-serialization-formatString,默认application/json未显式指定格式时对象的默认序列化格式。
disable-auto-fetchingboolean,默认falsetrue时客户端启动后不立即拉取任务,需手动调用ExternalTaskClient#start()
disable-backoff-strategyboolean,默认falsetrue时禁用客户端退避策略(Backoff)。注意:禁用退避可能对引擎造成较大负载,建议同时配置async-response-timeout
basic-auth对象见下文"Basic Auth 认证"一节。

订阅级(Subscription 级)配置项

subscriptions是一个以Topic 名为 key 的 Map,value 绑定到 SubscriptionConfiguration.java。每个订阅支持以下属性:

配置项类型/默认值说明
topic-nameString订阅的 Topic 名,通常对应 BPMN 模型中 Service Task 的camunda:topic扩展属性;也可以不写,因为 Map 的 key 就是 Topic 名。
auto-openboolean,默认truetrue表示应用启动后立即开始拉取任务;false表示需要手动调用SpringTopicSubscription#open()打开订阅。
lock-durationlong(毫秒),默认 20000该订阅的锁定时长,覆盖客户端级配置。
variable-namesList<String>,默认全部变量只拉取指定名称的流程变量;不配置则拉取全部可见变量。
local-variablesboolean,默认false是否只拉取外部任务局部作用域的变量(true),否则拉取任务可见范围内的所有变量。
business-keyString按业务键过滤要拉取的任务。
process-definition-idString按流程定义 ID 过滤。
process-definition-id-inList<String>按多个流程定义 ID 过滤。
process-definition-keyString按流程定义 Key 过滤,README 示例中的loan_process即此用法。
process-definition-key-inList<String>按多个流程定义 Key 过滤。
process-definition-version-tagString按流程定义版本标签过滤。
process-variablesMap<String, Object>按流程变量名值对过滤(fetch 条件),例如要求某变量等于指定值。
without-tenant-idboolean,默认false只拉取无租户(tenant)的任务。
tenant-id-inList<String>按租户 ID 列表过滤。
include-extension-propertiesboolean,默认false是否在任务中附带 Service Task 的自定义扩展属性(camunda:extensionProperties),README 示例中设置为true

上述全部属性均可在PropertiesAwareSpringTopicSubscription的合并逻辑中找到对应处理(见下文),说明它们是受支持并会被逐一注入订阅配置的。

编写 Topic 订阅 Handler

配置好属性后,实现一个 Bean 并标注@ExternalTaskSubscription("topicName")即可订阅对应 Topic。README 的示例使用"类级注解 + 实现ExternalTaskHandler"的方式:

@Configuration @ExternalTaskSubscription("creditScoreChecker") public class CreditScoreCheckerHandler implements ExternalTaskHandler { @Override public void execute(ExternalTask externalTask, ExternalTaskService externalTaskService) { // add your business logic here } }

其中ExternalTaskExternalTaskService来自底层 Java 客户端(clients/java/client 的org.camunda.bpm.client.task包)。在execute方法内你可以:

  • 通过externalTask.getAllVariables()/getVariable(name)读取流程变量;
  • 通过externalTaskService.complete(externalTask, variables)完成任务并回写变量;
  • 通过externalTaskService.handleFailure(...)报告处理失败,引擎会按 BPMN 中的错误处理配置决定重试;
  • 通过externalTaskService.handleBpmnError(...)抛出 BPMN 错误,驱动边界事件(Boundary Event)等流程路径。

注解的两种放置位置

ExternalTaskSubscription注解的@Target同时包含TYPEMETHOD(见 ExternalTaskSubscription.java),因此有两种写法:

  • 类级注解:标注在实现ExternalTaskHandler@Configuration/@Component类上,如上例;
  • 方法级注解:标注在返回ExternalTaskHandler@Bean方法上。

仓库测试中的 FullSubscriptionConfiguration.java 展示了方法级注解的完整用法,几乎穷举了注解的所有属性,可作为编写复杂订阅的参考模板:

@Configuration public class FullSubscriptionConfiguration { @ExternalTaskSubscription( autoOpen = true, topicName = "topic-one", variableNames = {"annotated-variable-one", "annotated-variable-two"}, lockDuration = 1111, localVariables = true, businessKey = "annotated-business-key", processDefinitionId = "annotated-process-definition-id", processDefinitionIdIn = {"annotated-id-one", "annotated-id-two"}, processDefinitionKey = "annotated-key", processDefinitionKeyIn = {"annotated-key-one", "annotated-key-two"}, processDefinitionVersionTag = "annotated-version-tag", processVariables = { @ProcessVariable(name = "annotated-var-name-foo", value = "annotated-var-val-foo"), @ProcessVariable(name = "annotated-var-name-bar", value = "annotated-var-val-bar") }, withoutTenantId = true, tenantIdIn = {"annotated-tenant-id-one", "annotated-tenant-id-two"}, includeExtensionProperties = true ) @Bean public ExternalTaskHandler handler() { return (externalTask, externalTaskService) -> { // interact with the external task }; } }

注意注解约定:字符串类型属性默认值为保留字$null$,long 类型默认值为Long.MIN_VALUE,int 类型默认值为Integer.MIN_VALUE,注解解析时会将这些哨兵值视为"未设置"(见 ExternalTaskSubscription.java 与 EnableExternalTaskClient.java 的 Javadoc 说明)。

属性合并机制:注解与 yml 如何协同

使用 Starter 时,订阅配置可以同时来自注解和application.yml。二者的合并逻辑由 PropertiesAwareSpringTopicSubscription.java 的mergeSubscriptionWithProperties()实现:

  1. 先从注解(或@Bean定义)中解析出订阅配置merge
  2. 以 Topic 名调用clientProperties.findSubscriptionPropsByTopicName(topicName)取出 yml 中对应订阅的属性;
  3. autoOpenlockDurationvariableNamesbusinessKeyprocessDefinitionIdprocessDefinitionIdInprocessDefinitionKeyprocessDefinitionKeyInprocessDefinitionVersionTagprocessVariableswithoutTenantIdtenantIdInincludeExtensionProperties等每一项,只要 yml 中显式设置了非空值,就覆盖注解中的值

这意味着一个务实的使用策略是:把"硬编码"的静态配置(如 Topic 名、过滤条件)放在注解中,把与环境相关的配置(如端点、凭据、是否开启扩展属性)放在application.yml,便于不同环境(dev/test/prod)通过外部化配置覆盖。仓库测试 MergeSubscriptionConfigurationTest.java 与 PropertiesOverrideSubscriptionConfigurationTest.java 专门验证了这一覆盖语义。

订阅的启动时机

底层 Spring 集成的订阅实现通过监听应用事件来决定何时打开订阅。Starter 将允许启动订阅的事件限定为ApplicationStartedEvent(见PropertiesAwareSpringTopicSubscription.isEventThatCanStartSubscription()),即应用完全启动完成后才开始拉取任务,避免在 Bean 尚未就绪时就开始消费任务。若auto-openfalse,则可通过注入SpringTopicSubscription并调用其open()手动开启。

Basic Auth 认证与请求拦截器

Starter 内置了对引擎 REST API 的 Basic Auth 支持。在application.yml中配置:

camunda.bpm.client: base-url: http://localhost:8080/engine-rest basic-auth: username: demo password: demo

绑定类为 BasicAuthProperties.java,包含usernamepassword两个字段。装配逻辑位于 PropertiesAwareClientFactory.java 的addBasicAuthInterceptor():当basic-auth非空时,会创建BasicAuthProvider(username, password)并添加到客户端的请求拦截器列表(getRequestInterceptors().add(...))。BasicAuthProvider来自底层 Java 客户端的org.camunda.bpm.client.interceptor.auth包。

由于它走的是请求拦截器机制,你同样可以自定义实现ClientRequestInterceptorClientRequestInterceptorBean 来为每个 REST 请求附加自定义头(如 OAuth Token、自定义 Header),仓库测试 RequestInterceptorConfigurationTest.java 与 BasicAuthAndInterceptorConfigurationTest.java 即覆盖了此类场景。

纯 Spring 集成(不使用 Spring Boot)

如果你的项目使用的是 Spring(非 Spring Boot),可以退而求其次只引入 Spring 集成层依赖:

<dependency> <groupId>org.camunda.bpm</groupId> <artifactId>camunda-external-task-client-spring</artifactId> <version>...</version> </dependency>

对应模块位于 spring-boot-starter/starter-client/spring。随后用@EnableExternalTaskClient注解启用客户端,并显式配置 REST API 端点等选项:

@Configuration @EnableExternalTaskClient(baseUrl = "http://localhost:8080/engine-rest") public class SimpleConfiguration { }

@EnableExternalTaskClient定义于 EnableExternalTaskClient.java,它通过@Import(PostProcessorConfiguration.class)引入客户端与订阅的后处理器(ClientPostProcessorSubscriptionPostProcessor),这两个处理器由 ClientAutoConfiguration.java 在 Spring Boot 场景下自动注册为 Bean(@ConditionalOnMissingBean保证可被用户自定义 Bean 覆盖)。

@EnableExternalTaskClient支持的全部注解属性(即上一节 Client 级配置项的注解形态)包括:baseUrl(必填,别名value)、workerIdmaxTasks(默认 10)、usePriority(默认true)、useCreateTime(默认false)、orderByCreateTimeasyncResponseTimeoutlockDurationdisableAutoFetchingdisableBackoffStrategydateFormatdefaultSerializationFormat。订阅注解@ExternalTaskSubscription与 Starter 场景完全一致,可照常使用。纯 Spring 场景下没有application.yml自动绑定,因此所有配置均通过注解或编程方式提供。

底层工作流程:从自动配置到任务消费

将 README 描述与仓库源码结合,一个 Worker 的完整生命周期如下:

  1. 自动装配ClientAutoConfiguration在应用启动时生效,注册SubscriptionPostProcessor(使用PropertiesAwareSpringTopicSubscription实现)与ClientPostProcessor(使用PropertiesAwareClientFactory实现);
  2. 客户端构建PropertiesAwareClientFactory.afterPropertiesSet()ClientProperties中的baseUrlworkerIdmaxTasksusePrioritylockDurationasyncResponseTimeoutdateFormatdefaultSerializationFormat等属性应用到底层ExternalTaskClient,并注册 Basic Auth 拦截器(见 PropertiesAwareClientFactory.java);
  3. 订阅合并:每个@ExternalTaskSubscriptionBean 在初始化时通过mergeSubscriptionWithProperties()将 yml 属性与注解属性合并,生成最终的订阅配置;
  4. 启动消费:监听ApplicationStartedEvent,应用启动完成后自动打开订阅;
  5. 持续循环:客户端通过 REST API 周期性调用 fetch-and-lock 拉取并锁定任务 → 调用ExternalTaskHandler.execute()执行业务逻辑 → 通过ExternalTaskService完成/报错/抛 BPMN 错误;客户端内置退避策略(Backoff)与长轮询(asyncResponseTimeout)机制以减轻引擎轮询压力。

底层 REST 交互(fetch-and-lock、complete、handleFailure、handleBpmnError、extendLock、unlock 等请求 DTO 与执行器)实现于 clients/java/client 的org.camunda.bpm.client.implorg.camunda.bpm.client.task.impl包,例如 FetchAndLockRequestDto.java、CompleteRequestDto.java。集成测试 ClientIT.java 与 TopicSubscriptionIT.java 验证了真实引擎环境下的拉取、锁定与完成链路。

测试与验证

仓库为 Spring 与 Spring Boot 两种集成都提供了完善的测试覆盖,可供你在接入时参考验证自己的配置:

  • Spring 集成层测试:spring-boot-starter/starter-client/spring/src/test 下的ConfigurationTestSimpleConfigurationTestDefaultConfigurationTestSubscriptionTestBackoffStrategyConfigurationTestMultipleClientAnnotationsExceptionTest等,覆盖注解解析、订阅生命周期(autoOpen为 false 时的NotOpenedException)、退避策略 Bean 等;
  • Spring Boot Starter 测试:spring-boot-starter/starter-client/spring-boot/src/test 下的ClientConfigurationTestSubscriptionConfigurationTestMergeSubscriptionConfigurationTestPropertiesOverrideSubscriptionConfigurationTestBasicAuthConfigurationTest、集成测试 ClientAutoConfigurationIT.java 等,覆盖属性绑定与自动装配行为。

小结

camunda-bpm-spring-boot-starter-external-task-client将 External Task 模式的接入成本降到了最低:加一个依赖、写一段application.yml、实现一个ExternalTaskHandler并标注@ExternalTaskSubscription,一个可水平扩展的 Worker 就完成了。其"注解声明 + 外部化属性覆盖 + 应用就绪后自动开启订阅"的设计,既保证了开发效率,也保留了多环境部署的灵活性。若你正在 Spring Boot 项目中集成 Camunda 外部任务,可将本 Starter 作为首选接入方式;纯 Spring 项目则可退而使用camunda-external-task-client-spring@EnableExternalTaskClient的等价方案。

值得一提的是,本 Starter 起源于社区扩展(最初由 Oliver Steinhauer 创建),后并入 Camunda 官方仓库(见 README.md 的 Credits 说明),这也解释了它"面向真实业务场景、开箱即用"的设计取向。需要说明的是,Camunda 7 CE 已进入 EoL(生命周期结束)状态,新项目建议评估 Camunda 8 平台,但理解该 Starter 所体现的外部任务模式与 Spring 集成范式,对迁移与维护存量系统仍有直接的参考价值。

【免费下载链接】camunda-bpm-platformCamunda 7 CE is End of Life (EoL). Please check out Camunda 8 instead (https://github.com/camunda/camunda) or read about Camunda 7 Enterprise End of Life (https://camunda.com/blog/2025/02/camunda-7-enterprise-end-of-life-extension/) – Camunda 7 CE was a flexible framework for workflow and decision automation using BPMN and DMN.项目地址: https://gitcode.com/GitHub_Trending/ca/camunda-bpm-platform

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 12:54:38

计算机网络实验报告怎么写:从抓包证据到Word自动化生成

简介&#xff1a;这是一份聚焦TCP协议迭代开发的计算机网络实验报告&#xff0c;覆盖RDT 2.0、RDT 2.2、RDT 3.0、选择响应协议以及Reno拥塞控制等关键知识点&#xff0c;适合计算机网络课程学生、备考者以及希望深入理解传输层可靠传输机制的开发者参考。报告结合代码与LOG文件…

作者头像 李华
网站建设 2026/9/18 12:53:52

SPSS数据分析报告自动化:从OMS导出到Word组装实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 12:53:50

OpenRouter 上的 MiniMax M3:TaoToken 当默认供应商跑一次 function call

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 12:52:34

温度传感器校准与补偿:从NTC到热电偶的精度提升指南

1. 先把概念理清楚&#xff1a;校准、补偿、标定的区别与联系1.1 传感器不准确的根源做嵌入式或者仪器仪表的朋友&#xff0c;几乎都跟温度传感器打过交道。DS18B20、NTC热敏电阻、PT100、热电偶&#xff0c;这几种是最常见的。很多人接上传感器&#xff0c;读到一个数就直接用…

作者头像 李华
网站建设 2026/9/18 12:51:22

Electron构建跨平台语音工作台:Web Audio与Node.js协同实践

1. VoiceStudio 是什么&#xff1a;一个跨平台语音工作台的底层逻辑VoiceStudio 这个名字乍一听像某家音频厂商的商业软件&#xff0c;但结合 Electron、macOS、Windows、Linux 这组关键词&#xff0c;它实际指向一个典型的现代桌面应用开发实践——用 Web 技术栈构建专业级语音…

作者头像 李华
网站建设 2026/9/18 12:49:41

SCMA稀疏码多址接入:从原理到工程落地的实用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华