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 groupIdorg.camunda.bpm.springboot/groupId artifactIdcamunda-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-springSpring 集成层、spring-boot-autoconfigure与spring-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 APIsubscriptions以 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-url、worker-id、max-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-ddTHH:mm:ss.SSSZ日期类型变量的序列化/反序列化格式。default-serialization-formatString默认application/json未显式指定格式时对象的默认序列化格式。disable-auto-fetchingboolean默认false为true时客户端启动后不立即拉取任务需手动调用ExternalTaskClient#start()。disable-backoff-strategyboolean默认false为true时禁用客户端退避策略Backoff。注意禁用退避可能对引擎造成较大负载建议同时配置async-response-timeout。basic-auth对象见下文Basic Auth 认证一节。订阅级Subscription 级配置项subscriptions是一个以Topic 名为 key 的 Mapvalue 绑定到 SubscriptionConfiguration.java。每个订阅支持以下属性配置项类型/默认值说明topic-nameString订阅的 Topic 名通常对应 BPMN 模型中 Service Task 的camunda:topic扩展属性也可以不写因为 Map 的 key 就是 Topic 名。auto-openboolean默认truetrue表示应用启动后立即开始拉取任务false表示需要手动调用SpringTopicSubscription#open()打开订阅。lock-durationlong毫秒默认 20000该订阅的锁定时长覆盖客户端级配置。variable-namesListString默认全部变量只拉取指定名称的流程变量不配置则拉取全部可见变量。local-variablesboolean默认false是否只拉取外部任务局部作用域的变量true否则拉取任务可见范围内的所有变量。business-keyString按业务键过滤要拉取的任务。process-definition-idString按流程定义 ID 过滤。process-definition-id-inListString按多个流程定义 ID 过滤。process-definition-keyString按流程定义 Key 过滤README 示例中的loan_process即此用法。process-definition-key-inListString按多个流程定义 Key 过滤。process-definition-version-tagString按流程定义版本标签过滤。process-variablesMapString, Object按流程变量名值对过滤fetch 条件例如要求某变量等于指定值。without-tenant-idboolean默认false只拉取无租户tenant的任务。tenant-id-inListString按租户 ID 列表过滤。include-extension-propertiesboolean默认false是否在任务中附带 Service Task 的自定义扩展属性camunda:extensionPropertiesREADME 示例中设置为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 } }其中ExternalTask与ExternalTaskService来自底层 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同时包含TYPE与METHOD见 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_VALUEint 类型默认值为Integer.MIN_VALUE注解解析时会将这些哨兵值视为未设置见 ExternalTaskSubscription.java 与 EnableExternalTaskClient.java 的 Javadoc 说明。属性合并机制注解与 yml 如何协同使用 Starter 时订阅配置可以同时来自注解和application.yml。二者的合并逻辑由 PropertiesAwareSpringTopicSubscription.java 的mergeSubscriptionWithProperties()实现先从注解或Bean定义中解析出订阅配置merge以 Topic 名调用clientProperties.findSubscriptionPropsByTopicName(topicName)取出 yml 中对应订阅的属性对autoOpen、lockDuration、variableNames、businessKey、processDefinitionId、processDefinitionIdIn、processDefinitionKey、processDefinitionKeyIn、processDefinitionVersionTag、processVariables、withoutTenantId、tenantIdIn、includeExtensionProperties等每一项只要 yml 中显式设置了非空值就覆盖注解中的值。这意味着一个务实的使用策略是把硬编码的静态配置如 Topic 名、过滤条件放在注解中把与环境相关的配置如端点、凭据、是否开启扩展属性放在application.yml便于不同环境dev/test/prod通过外部化配置覆盖。仓库测试 MergeSubscriptionConfigurationTest.java 与 PropertiesOverrideSubscriptionConfigurationTest.java 专门验证了这一覆盖语义。订阅的启动时机底层 Spring 集成的订阅实现通过监听应用事件来决定何时打开订阅。Starter 将允许启动订阅的事件限定为ApplicationStartedEvent见PropertiesAwareSpringTopicSubscription.isEventThatCanStartSubscription()即应用完全启动完成后才开始拉取任务避免在 Bean 尚未就绪时就开始消费任务。若auto-open为false则可通过注入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包含username与password两个字段。装配逻辑位于 PropertiesAwareClientFactory.java 的addBasicAuthInterceptor()当basic-auth非空时会创建BasicAuthProvider(username, password)并添加到客户端的请求拦截器列表getRequestInterceptors().add(...)。BasicAuthProvider来自底层 Java 客户端的org.camunda.bpm.client.interceptor.auth包。由于它走的是请求拦截器机制你同样可以自定义实现ClientRequestInterceptor的ClientRequestInterceptorBean 来为每个 REST 请求附加自定义头如 OAuth Token、自定义 Header仓库测试 RequestInterceptorConfigurationTest.java 与 BasicAuthAndInterceptorConfigurationTest.java 即覆盖了此类场景。纯 Spring 集成不使用 Spring Boot如果你的项目使用的是 Spring非 Spring Boot可以退而求其次只引入 Spring 集成层依赖dependency groupIdorg.camunda.bpm/groupId artifactIdcamunda-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)引入客户端与订阅的后处理器ClientPostProcessor、SubscriptionPostProcessor这两个处理器由 ClientAutoConfiguration.java 在 Spring Boot 场景下自动注册为 BeanConditionalOnMissingBean保证可被用户自定义 Bean 覆盖。EnableExternalTaskClient支持的全部注解属性即上一节 Client 级配置项的注解形态包括baseUrl必填别名value、workerId、maxTasks默认 10、usePriority默认true、useCreateTime默认false、orderByCreateTime、asyncResponseTimeout、lockDuration、disableAutoFetching、disableBackoffStrategy、dateFormat、defaultSerializationFormat。订阅注解ExternalTaskSubscription与 Starter 场景完全一致可照常使用。纯 Spring 场景下没有application.yml自动绑定因此所有配置均通过注解或编程方式提供。底层工作流程从自动配置到任务消费将 README 描述与仓库源码结合一个 Worker 的完整生命周期如下自动装配ClientAutoConfiguration在应用启动时生效注册SubscriptionPostProcessor使用PropertiesAwareSpringTopicSubscription实现与ClientPostProcessor使用PropertiesAwareClientFactory实现客户端构建PropertiesAwareClientFactory.afterPropertiesSet()将ClientProperties中的baseUrl、workerId、maxTasks、usePriority、lockDuration、asyncResponseTimeout、dateFormat、defaultSerializationFormat等属性应用到底层ExternalTaskClient并注册 Basic Auth 拦截器见 PropertiesAwareClientFactory.java订阅合并每个ExternalTaskSubscriptionBean 在初始化时通过mergeSubscriptionWithProperties()将 yml 属性与注解属性合并生成最终的订阅配置启动消费监听ApplicationStartedEvent应用启动完成后自动打开订阅持续循环客户端通过 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.impl与org.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 下的ConfigurationTest、SimpleConfigurationTest、DefaultConfigurationTest、SubscriptionTest、BackoffStrategyConfigurationTest、MultipleClientAnnotationsExceptionTest等覆盖注解解析、订阅生命周期autoOpen为 false 时的NotOpenedException、退避策略 Bean 等Spring Boot Starter 测试spring-boot-starter/starter-client/spring-boot/src/test 下的ClientConfigurationTest、SubscriptionConfigurationTest、MergeSubscriptionConfigurationTest、PropertiesOverrideSubscriptionConfigurationTest、BasicAuthConfigurationTest、集成测试 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),仅供参考