当前位置: 首页 > news >正文

简单易懂的springboot整合Camunda 7工作流入门教程

简单易懂的Spring Boot整合Camunda7入门教程

因为关于Spring Boot结合Camunda7的教程在网上比较少,而且很多都写得有点乱,很多概念写得太散乱,讲解不清晰,导致看不懂,本人通过研究学习之后就写出了这篇教学文档。

介绍

Camunda是一个开源平台,专为开发人员设计,用以建模、执行和监控业务流程。它基于BPMN(Business Process Model and Notation,业务流程建模与标记)标准,允许组织自动化其业务流程。Camunda的核心组件包括流程引擎、任务管理器、用户界面组件和管理工具。

官方文档

为什么结合Spring Boot和Camunda?

  1. 简化开发:Spring Boot简化了Java应用的搭建过程,而Camunda则提供了强大的流程自动化工具。两者的结合可以帮助开发者快速搭建带有工作流的应用。
  2. 集成便利:Spring Boot和Camunda都有很好的生态支持,它们之间的集成相对简单,因为Camunda本身也支持Spring环境。
  3. 灵活性和可扩展性:Camunda允许在流程定义中嵌入自定义Java代码,这样可以轻松地与现有的Spring Boot应用集成,实现复杂的业务逻辑。

在这里插入图片描述

快速开始

添加依赖

环境为java17
添加依赖:

        <dependency><groupId>org.camunda.bpm.springboot</groupId><artifactId>camunda-bpm-spring-boot-starter</artifactId><version>7.18.0</version></dependency><dependency><groupId>org.camunda.bpm.springboot</groupId><artifactId>camunda-bpm-spring-boot-starter-rest</artifactId><version>7.18.0</version></dependency><dependency><groupId>org.camunda.bpm.springboot</groupId><artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId><version>7.18.0</version></dependency>
  1. camunda-bpm-spring-boot-starter

这个依赖包是Camunda与Spring Boot集成的基础,包含了启动Camunda BPM引擎所需的基本组件,如Camunda BPM Engine、Spring Integration以及Spring Boot自动配置。它使开发者能够快速启动Camunda BPM引擎,并提供默认配置选项。

  1. camunda-bpm-spring-boot-starter-rest

此依赖包提供了Camunda REST API的支持,允许通过HTTP请求访问Camunda BPM引擎的功能,如启动流程实例、查询状态、管理任务及部署定义。这使得前端应用或其他服务可以通过RESTful方式与Camunda交互。

  1. camunda-bpm-spring-boot-starter-webapp

这个依赖包用于创建集成Camunda Web客户端(如Cockpit)和任务列表(Tasklist)的Web应用程序,方便在浏览器中管理和监控Camunda流程。这提高了开发和运维的效率。

基础配置

# Camunda Engine自动配置
camunda:db:history: full# camunda登录信息配置
camunda.bpm:auto-deployment-enabled: false  # 关闭自动部署,一开始测试的时候可以先不关闭,默认是自动部署admin-user:id: admin  #用户名password: 123456  #密码firstName: sufilter:create: All tasks

至少要配置一个数据库项(mysql,pgsql都支持):

datasource:driver-class-name: org.postgresql.Driverusername: password:url: jdbc:postgresql:
jpa:hibernate:ddl-auto: update

resources下新建BPMN用于存放流程文件:

在这里插入图片描述

启动项目

配置好之后,启动项目,会自动配置好数据库和生成对应表

在这里插入图片描述

通过localhost:端口号/context-path(自己配置的,没有可以忽略)/camunda/app/,可以访问到内置web界面

输入用户名密码即为配置文件里面的 admin,123456

在这里插入图片描述

主控制台

登陆成功后,如下所示,具体的使用在下面介绍
在这里插入图片描述

  • Cockpit:这是Camunda的管理控制台,用于监视和调试流程实例。你可以在这里查看流程定义、流程实例、历史数据等。它是开发人员和管理员的主要工具,用于理解流程行为和诊断问题。
  • Tasklist:这是一个任务列表,用于查看和管理当前待办事项。对于那些需要完成任务的用户来说,这是一个重要的入口点。
  • Admin:这是Camunda的管理工具,用于管理用户、组、权限和数据库连接等。它提供了对系统设置的全面控制。

绘制流程图

下载

首先需要一个工具 Camunda Modeler 来画,下载地址:

https://camunda.com/download/modeler/

选择对应自己电脑的版本下载:

在这里插入图片描述

下载好后,解压双击打开程序:

在这里插入图片描述

新建流程图

在这里插入图片描述

最终绘制一个基础的任务审核流程图:
在这里插入图片描述

介绍

任务分类

介绍最常用的两种

用户任务 (User Task)

在这里插入图片描述

具体来说就是需要手动执行的任务,即需要我们这变写完业务代码后,调用代码,来提交当前任务,当前任务才会被完成,从而走到下一个流程

taskService.complete(taskId, variables);
系统任务(Service Task)

在这里插入图片描述

系统自动完成的任务,而结合springboot 也就是在springboot写好的执行流程,自动执行完成后走到下一个流程。

网关

分为这么几类,会根据我们传入的流程变量及设定的条件走

  • 排他网关(exclusive gateway)

这个网关只会走一个,我们走到这个网关时,会从上到下找第一个符合条件的任务往下走

  • 并行网关(Parallel Gateway)

这个网关不需要设置条件,会走所有的任务

  • 包含网关(Inclusive Gateway)

这个网关会走一个或者多个符合条件的任务

在这里插入图片描述

具体绘制方法

可以从左边直接拖过来,或者直接点击(具体自己尝试,很简单的)

开始

首先需要每个流程都需要有一个流程起点:
在这里插入图片描述

点击新建的流程点可以选择下一个节点是什么:
在这里插入图片描述

系统任务

系统任务推荐指定bean来实现java代码:
在这里插入图片描述

代码实现方法:

@Component
public class SignInDelegate implements JavaDelegate {@Overridepublic void execute(DelegateExecution execution) throws Exception {//执行的系统任务流程}@Bean("指定的bean")public JavaDelegate signIn() {return this::execute; // 返回当前类的 execute 方法}
}

DelegateExecution是Camunda BPM引擎提供的一个接口,用于在流程执行过程中传递上下文信息。它在流程实例执行的过程中充当了一个中心角色,提供了访问流程变量、流程定义、活动实例以及其他与流程执行相关的功能的方法。

补充:右边有个展开,点一下就出来了

在这里插入图片描述

设定网关

设定网关表达式:

在这里插入图片描述

在上一个系统任务中设置传入对应变量,让流程能顺利通过网关:

@Component
public class SignInDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) throws Exception {//执行的系统任务流程// 设置流程变量,以至于能够顺利通过网关,如果没有设置的话会报错execution.setVariable("通过", true);
}
@Bean("指定的bean")
public JavaDelegate signIn() {return this::execute; // 返回当前类的 execute 方法
}}
设定角色任务

在系统任务中指定对应的用户(受理人)来处理该事件:

在这里插入图片描述

@Component
public class SignInDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) throws Exception {//执行的系统任务流程// 设置流程变量,以至于能够顺利通过网关,如果没有设置的话会报错execution.setVariable("通过", true);execution.setVariable("指定的角色", "用户id或者唯一的用户名称");  //指定受理人
}
@Bean("指定的bean")
public JavaDelegate signIn() {return this::execute; // 返回当前类的 execute 方法
}

**注意:**Assignee只能是string类型,不能传入其他类型

完成角色任务

可以通过taskAssignee(“变量值(用户名或id)”) 来查找任务实例

可以通过task.setAssignee(“变量值(用户名或id)”);来修改当前实例的受理人

List<Task> tasks = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskAssignee(userId)//这里两个参数意思是从第几行开始,一共需要几行.listPage(pageNum, pageSize);

(如何获得当前节点任务实例ID的方法后面会讲)

通过某种方法获取到taskId(当前节点任务实例ID),通过这个id去查找任务,然后完成任务:

    // 完成任务@Overridepublic String submitApproval(String taskId, boolean approval,String note) {// 获取任务Task task = taskService.createTaskQuery().taskId(taskId).singleResult();if (task == null){return "不存在该任务";}// 执行业务流程// 设置审批结果runtimeService.setVariable(task.getExecutionId(), "审批情况", approval); //task.getExecutionId()是实例id,设定全局变量能够走到结束流程// 完成任务taskService.complete(taskId);return "审批已完成.";}
设定processDefinitionKey

rocessDefinitionKey是在使用Camunda BPM时的一个重要概念,它用于唯一标识一个流程定义。当您在Camunda Modeler中设计流程并通过BPMN 2.0标准定义了一个流程后,该流程会被赋予一个唯一的键值,这个键就是processDefinitionKey

什么是processDefinitionKey

processDefinitionKey是在流程定义文件(通常是.bpmn文件)中的属性,它用来唯一识别一个特定的流程定义。这个键通常对应于流程定义的ID,并且在流程定义部署到Camunda BPM引擎时会被使用。

在哪里定义?

在BPMN文件中,processDefinitionKey是在<process>元素上的id属性。虽然这不是一个强制性的属性,但在实践中,为了能够通过代码引用流程定义,通常会为其指定一个有意义的id

例如,在BPMN文件中:

<process id="myProcess" name="My Process"><!-- 流程节点定义 -->
</process>

在这个例子中,myProcess就是processDefinitionKey

在绘制流程图,点击空白处就能看到processDefinitionKey,可以自己指定,设定,程序是通过指定的processDefinitionKey来启动对应流程图实例的。

在这里插入图片描述

基本概念

工作流基础变量名词解释

processDefinitionKey(默认流程Key)

解释
processDefinitionKey是一个用来唯一标识某个流程定义的字符串。当你使用Camunda Modeler设计并保存一个流程图时,这个流程图会有一个对应的processDefinitionKey,它实际上就是流程定义文件中的<process>标签的id属性。

用途
当你需要在代码中启动一个流程实例时,就需要使用processDefinitionKey来告诉Camunda BPM引擎你想启动哪一个流程定义。例如,如果你想启动名为orderApproval的流程,就会使用orderApproval作为processDefinitionKey

processInstanceId(流程实例ID)

解释
当你启动一个流程定义时,Camunda BPM引擎会为这个特定的流程实例生成一个唯一的processInstanceId。这个ID用来唯一标识一个具体的流程实例,即使使用同一个流程定义启动多次,每次启动都会生成不同的processInstanceId

用途
使用processInstanceId可以查询特定流程实例的状态,查看流程实例的历史记录,或者继续处理流程实例中的下一步。

nodeId(节点ID)

解释
在BPMN流程定义中,流程由一系列的活动(节点)组成,如开始事件、任务、网关等。每个活动都有一个唯一的标识符,即nodeId

用途
nodeId用于标识流程中的各个活动。在流程执行过程中,可以用来追踪流程当前所处的位置,或者记录流程执行的历史轨迹。

taskId(任务ID)

解释
在流程定义中有许多任务需要用户完成,如审核任务、填写表单等。每个这样的任务都有一个唯一的taskId

用途
taskId用于标识特定的任务实例,用户可以通过taskId来查找和执行分配给他们的任务。

Assignee(受理人)

解释
在流程定义中,有些任务需要指定的用户来完成。Assignee是指定给某个任务的执行者,即谁负责完成这项任务。

用途
Assignee用于指派任务给具体的用户。只有被指派的用户才能看到任务并在任务列表中执行它。

BusinessKey(业务Key)

解释
BusinessKey是用来关联业务对象与流程实例的标识符。它可以用来存储业务相关的信息,以便于后续的流程处理。

用途
使用BusinessKey可以将业务数据关联到流程实例上,这样在流程执行过程中,可以方便地获取到业务相关的数据。比如说一个考勤流程,有人要申请考勤,那么就可以将这个人的唯一工作号码作为BusinessKey,方便查询和定位这个人的申请流程。

流程图讲解:

在这里插入图片描述

流程节点的类型及其意义
  1. 开始事件(Start Event)

    • 意义:标志着流程的开始。可以是普通开始事件、定时器开始事件等。
    • 用法:用于定义流程实例何时启动。例如,当接收到订单时,可以触发订单处理流程的开始事件。
  2. 结束事件(End Event)

    • 意义:标志着流程或分支的结束。可以是普通结束事件、取消结束事件等。
    • 用法:用于定义流程何时终止。例如,当订单处理完毕后,可以触发订单处理流程的结束事件。
  3. 任务(Task)

    • 意义:表示需要完成的工作。可以是用户任务、服务任务等。
    • 用法:用于定义需要执行的具体工作。例如,用户任务可能涉及人工审批,而服务任务则可以调用 Web 服务或执行脚本。
  4. 网关(Gateway)

    • 独占网关(Exclusive Gateway)
      • 意义:用于选择一条单一路径继续流程。
      • 用法:根据条件选择下一个活动。例如,根据订单金额决定是否需要额外审批。
    • 并行网关(Parallel Gateway)
      • 意义:允许多条路径同时进行。
      • 用法:同时执行多个并行任务。例如,同时发送邮件通知客户和更新库存系统。
    • 复杂网关(Complex Gateway)
      • 意义:用于更复杂的路由逻辑。
      • 用法:处理更复杂的流程分支逻辑。
  5. 事件子流程(Event Subprocess)

    • 意义:用于处理特定类型的事件。
    • 用法:可以嵌套在流程中,等待特定事件的发生再执行。
  6. 序列流(Sequence Flow)

    • 意义:连接两个节点,定义流程的流向。
    • 用法:用于定义节点之间的顺序关系。

Services API

当然可以,下面是经过优化后的讲解,旨在让新手更容易理解Camunda引擎中的各个服务及其功能:


Camunda 服务概述

在使用Camunda BPM引擎时,有几个核心服务可以帮助我们管理和执行流程。以下是这些服务的基本介绍以及它们的主要用途:

RepositoryService

简介:RepositoryService是你与Camunda引擎交互的第一个切入点。它主要用于管理流程定义的部署,包括上传流程定义文件(如BPMN文件)到引擎中。

主要功能

  • 部署和管理流程定义。
  • 查询已部署的流程定义和部署信息。
  • 挂起和激活流程定义,控制其是否可以被启动。
  • 检索流程定义中的文件和流程图。
RuntimeService

简介:RuntimeService是用于在流程执行期间与引擎交互的服务。它允许启动流程实例,并且可以查询正在执行的流程实例状态。

主要功能

  • 启动流程实例。
  • 存储和检索流程实例的变量。
  • 查询正在执行的流程实例和执行实例(指向流程实例当前位置的“令牌”)。
  • 处理流程实例的外部触发。
TaskService

简介:TaskService专注于管理流程中的任务,特别是那些需要人为干预的任务。

主要功能

  • 查询分配给用户的任务。
  • 创建新的任务,这些任务可以独立于任何流程实例。
  • 分配任务给用户或组。
  • 认领和完成任务。
IdentityService

简介:IdentityService提供了管理用户和组的功能,但请注意,核心引擎并不会在运行时验证用户身份。

主要功能

  • 创建、更新、删除和查询用户和组。
  • 尽管可以将任务分配给任何用户,但实际的身份验证和授权需在应用层实现。
FormService

简介:FormService是可选的,它支持流程中的表单功能,比如启动流程前展示的表单或任务完成时所需的表单。

主要功能

  • 管理和渲染开始表单和任务表单。
  • 表单数据与流程变量的交互。
HistoryService

简介:HistoryService提供了访问流程执行历史记录的功能。

主要功能

  • 查询流程实例的历史数据,如开始时间、执行用户、任务耗时等。
  • 数据持久化级别可配置。
ManagementService

简介:ManagementService提供了对数据库表元数据的访问,并支持作业的查询和管理。

主要功能

  • 检索数据库表和元数据信息。
  • 管理和查询作业,例如计时器作业。
FilterService

简介:FilterService允许创建和管理过滤器,用于简化常见的查询需求。

主要功能

  • 创建存储的查询,如任务查询。
  • Tasklist应用使用过滤器来筛选任务。
ExternalTaskService

简介:ExternalTaskService专门处理外部任务,即在流程引擎之外执行的工作项。

主要功能

  • 提供对流程外部任务的访问和管理。
  • 支持异步处理模式下的任务领取和完成。
Query API

简介:Camunda引擎提供了多种方式来查询数据。

主要功能

  • Java Queries:使用面向对象的API进行查询,适用于大多数场景。
  • Native Queries:直接构建SQL查询语句,适用于复杂或特定的需求。
示例

下面是一个查询任务的简单示例:

// Java 查询示例
List<Task> tasks = taskService.createTaskQuery().taskAssignee("userOne").processVariableValueEquals("orderId", "8888").orderByDueDate().asc().list();// Native 查询示例
List<Task> tasks = taskService.createNativeTaskQuery().sql("SELECT * FROM " + managementService.getTableName(Task.class) + " T WHERE T.NAME_ = #{taskName}").parameter("taskName", "aOpenTask").list();

Camunda 服务使用示例

在这里插入图片描述

进程过程中的变量数据

在Camunda BPM引擎中,流程实例变量(Process Instance Variables)是非常重要的概念,因为它们贯穿整个流程的生命周期,用于存储流程执行期间的数据。这些变量可以用来传递信息、控制流程逻辑、以及与其他系统集成。下面是一个关于流程变量从设置到使用的完整过程的讲解:

1. 定义变量

首先,在设计流程定义时,你需要考虑哪些数据需要在流程中传递。这些数据可以是输入参数、中间计算结果或者是输出结果。虽然在BPMN模型中没有直接定义变量的地方,但你可以通过流程节点的行为来隐式地定义变量。例如,你可以添加一个服务任务来设置初始变量。

2. 设置变量

一旦流程定义被部署,你就可以在启动流程实例时设置初始变量。这可以通过调用RuntimeServicestartProcessInstanceByKey方法来完成,并且可以传入一个Map类型的参数来设置初始变量。

Map类型是<String,Object>,也就是可以将定义的对象都能传进去

Map<String, Object> variables = new HashMap<>();
variables.put("orderId", "12345");
User user = new User();
variables.put("User",user)
runtimeService.startProcessInstanceByKey("orderApproval", variables);
3. 查询变量

在流程执行过程中,你可能需要查询某些变量的值。这可以通过RuntimeService提供的getVariablegetVariables方法来实现。

Object orderId = runtimeService.getVariable("processInstanceId", "orderId");
User user = (User) runtimeService.getVariable("processInstanceId", "User");
4. 修改变量

随着流程的推进,变量的值可能会发生变化。你可以通过服务任务中的脚本或服务调用来修改变量的值。修改变量可以通过setVariablesetVariables方法来完成。

runtimeService.setVariable("processInstanceId", "status", "approved");
5. 传递变量

变量不仅可以存储在流程实例中,还可以在流程节点之间传递。例如,当一个任务完成后,任务的结果可以作为变量传递给下一个任务或网关。

taskService.complete(taskId, variables);
6. 使用变量控制流程逻辑

流程中的某些决策点(如排他网关)可以根据变量的值来决定流程走向。例如,如果一个订单的金额超过一定阈值,则需要高级经理审批。

<exclusiveGateway id="approvalGateway"><conditionExpression xsi:type="tFormalExpression"evaluatesToType="string">${amount > 1000}</conditionExpression>
</exclusiveGateway>
7. 变量的作用域

需要注意的是,流程变量有不同的作用域,包括流程实例级、执行级(如子流程)和任务级。不同作用域的变量可以在不同的上下文中访问。

8. 清理变量

当流程实例结束时,与之相关的变量也将不再可用。如果你需要长期存储某些数据,应该将其持久化到数据库或其他存储系统中。

示例场景

假设有一个订单审批流程,需要根据订单金额来决定审批流程。订单金额作为一个变量在流程开始时被设置,并在审批过程中被多个节点使用。

// 设置订单金额
Map<String, Object> variables = new HashMap<>();
variables.put("orderAmount", 1500);// 启动流程实例
runtimeService.startProcessInstanceByKey("orderApproval", variables);// 某个服务任务检查订单金额并修改状态
runtimeService.setVariable("processInstanceId", "approvalStatus", "pending");// 用户完成任务时提交结果
Map<String, Object> completionVariables = new HashMap<>();
completionVariables.put("reviewResult", "approved");
taskService.complete(taskId, completionVariables);
通过变量查询任务

通过变量来查询任务或流程实例是Camunda BPM引擎中一个非常实用的功能。这使得开发者可以根据业务逻辑中的条件来动态查询流程的状态。以下是详细的步骤和示例,说明如何使用变量来查询任务或流程实例。

查询任务

假设你想要找到所有分配给了特定用户并且订单ID等于某特定值的任务,可以使用TaskService来执行这样的查询。

// 使用变量查询任务
List<Task> tasks = taskService.createTaskQuery().taskAssignee("johnDoe") // 指定任务的分配者.processVariableValueEquals("orderId", "12345") // 使用变量值来过滤任务.list();for (Task task : tasks) {System.out.println("Task ID: " + task.getId() + ", Name: " + task.getName());
}

在这个例子中,taskAssignee方法用来过滤分配给特定用户johnDoe的任务,而processVariableValueEquals方法则是根据流程实例中的变量orderId的值来进一步筛选任务。

查询流程实例

如果你需要根据变量来查询流程实例,可以使用RuntimeService来进行查询。例如,找出所有订单ID为特定值的流程实例。

// 使用变量查询流程实例
List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery().variableValueEquals("orderId", "12345") // 使用变量值来过滤流程实例.list();for (ProcessInstance instance : processInstances) {System.out.println("Process Instance ID: " + instance.getId() + ", Business Key: " + instance.getBusinessKey());
}

在这个例子中,variableValueEquals方法用来根据变量orderId的值来过滤流程实例。createProcessInstanceQuery方法创建了一个流程实例查询对象,然后通过这个对象可以指定查询条件。

更复杂的查询

如果你需要更复杂的查询条件,比如组合条件(AND/OR)、范围查询等,可以使用多个查询方法来组合条件。例如,你可以根据两个变量来查询任务:

List<Task> tasks = taskService.createTaskQuery().taskAssignee("johnDoe").processVariableValueEquals("orderId", "12345").processVariableValueGreaterThan("amount", 1000).list();

在这里,我们不仅根据orderId查询,而且还添加了一个额外的条件amount大于1000。

查询单一实例或任务

如果你只想获取单个结果而不是列表,可以使用singleResult方法代替list

Task singleTask = taskService.createTaskQuery().taskAssignee("johnDoe").processVariableValueEquals("orderId", "12345").singleResult();if (singleTask != null) {System.out.println("Found task: " + singleTask.getName());
} else {System.out.println("No task found.");
}

RepositoryService部署流程图

部署对象
        // 创建部署对象Deployment deploy = repositoryService.createDeployment().addClasspathResource(requestParam.getResourcePath()) // 添加资源路径.name(requestParam.getBpmnName()) // 设置部署名称.deploy(); // 部署流程定义

部署位置是相对于资源路径来说,比如:BPMN/名称.bpmn

在web中就可以看到部署的实例了:
在这里插入图片描述

在这里插入图片描述

删除部署对象
// 删除部署,默认情况下不会级联删除流程实例和Job
repositoryService.deleteDeployment(deploymentId);// deploymentId = deploy.getId()
获取流程实例
    @Overridepublic String getBpmnModelInstance(String processDefinitionId) {// 获取流程模型实例BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(processDefinitionId);if (ObjectUtil.isNotNull(bpmnModelInstance)) {// 获取模型中的所有用户任务Collection<UserTask> userTasks = bpmnModelInstance.getModelElementsByType(UserTask.class);// 获取模型定义Definitions definitions = bpmnModelInstance.getDefinitions();// 日志输出log.info("获取到流程模型实例:{}", bpmnModelInstance);}return null; // 返回提示信息,这里暂时返回null}

runtimeService开启流程实例

启动流程实例
Map<String, Object> paramMap = request.getVariables();// businessKey用于查询用户对应业务的待办任务
org.camunda.bpm.engine.runtime.ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, request.getBusinessKey(), paramMap);

使用RuntimeService来启动一个新的流程实例,并传递业务键(businessKey)和流程变量(paramMap)。

拒绝流程实例
@Override
public String rejectProcessInstance(RejectInstanceRequest request) {String processInstanceId = request.getProcessInstanceId();ActivityInstance activity = runtimeService.getActivityInstance(processInstanceId);runtimeService.createProcessInstanceModification(processInstanceId).cancelActivityInstance(activity.getId()).setAnnotation("驳回").startBeforeActivity(request.getTargetNodeId()).execute();return "驳回成功";
}

使用RuntimeService来拒绝(即回退)一个流程实例,并将流程重定向到指定的活动节点。

  • .cancelActivityInstance(activity.getId()):取消当前活动实例。
  • .setAnnotation("驳回"):设置注释,用于标记此次操作的原因。
  • .startBeforeActivity(request.getTargetNodeId()):将流程实例重定向到指定的目标节点。
  • .execute():执行流程实例修改操作。
挂起实例

挂起流程实例是指暂停特定流程实例的执行,使其不能继续前进。你可以选择挂起单个流程实例,也可以挂起一组符合特定条件的流程实例。

    /*** 挂起流程定义** @param processDefinitionId 流程定义ID* @return 提示信息*/@Overridepublic String suspendProcessDefinitionById(String processDefinitionId) {// 挂起流程定义repositoryService.suspendProcessDefinitionById(processDefinitionId); //也可以通过processDefinitionKey来挂起实例return "挂起成功";}

TaskService 操作详解

讲解TaskService中的“查询任务列表”和“完成任务”的操作。

查询任务列表
@Override
public List<Task> queryTasks(TaskQueryRequest request) {// 获取查询参数String assignee = request.getAssignee();String candidateGroup = request.getCandidateGroup();// 创建任务查询对象TaskQuery taskQuery = taskService.createTaskQuery().taskAssignee(assignee) // 指定任务的分配者// 执行查询并返回任务列表List<Task> tasks = taskQuery.list();return tasks;
}
完成任务
@Override
public String completeTask(CompleteTaskRequest request) {// 获取任务ID和任务变量String taskId = request.getTaskId();Map<String, Object> taskVariables = request.getVariables();// 完成任务,并传递任务变量taskService.complete(taskId, taskVariables);return "任务完成";
}
示例

假设你需要查询分配给特定用户,并完成其中一个任务:

public class TaskQueryRequest {private String assignee;public TaskQueryRequest(String assignee) {this.assignee = assignee;}public String getAssignee() {return assignee;}public String getCandidateGroup() {return candidateGroup;}
}public class CompleteTaskRequest {private String taskId;private Map<String, Object> variables;public CompleteTaskRequest(String taskId, Map<String, Object> variables) {this.taskId = taskId;this.variables = variables;}public String getTaskId() {return taskId;}public Map<String, Object> getVariables() {return variables;}
}// 假设请求对象如下:
TaskQueryRequest queryRequest = new TaskQueryRequest("johnDoe");// 查询任务
List<Task> tasks = taskService.queryTasks(queryRequest);// 假设需要完成第一个任务
if (!tasks.isEmpty()) {Task task = tasks.get(0);CompleteTaskRequest completeRequest = new CompleteTaskRequest(task.getId(), Collections.singletonMap("result", "completed")); // 这是自己定义的方法// 完成任务String result = taskService.completeTask(completeRequest);System.out.println(result); // 输出 "任务完成"
}

文档md格式开源地址:springboot结合Camunda7简单快速入门教程文档
觉得写得不错的话,可以给个star(´・ω・`) 。

参考文章:
1.SpringBoot 优雅集成 Camunda 7以上 工作流引擎,保姆级教程!
2.Camunda修炼手册

相关文章:

简单易懂的springboot整合Camunda 7工作流入门教程

简单易懂的Spring Boot整合Camunda7入门教程 因为关于Spring Boot结合Camunda7的教程在网上比较少&#xff0c;而且很多都写得有点乱&#xff0c;很多概念写得太散乱&#xff0c;讲解不清晰&#xff0c;导致看不懂&#xff0c;本人通过研究学习之后就写出了这篇教学文档。 介…...

LabVIEW提高开发效率技巧----点阵图(XY Graph)

在LabVIEW开发中&#xff0c;点阵图&#xff08;XY Graph&#xff09; 是一种强大的工具&#xff0c;尤其适用于需要实时展示大量数据的场景。通过使用点阵图&#xff0c;开发人员能够将实时数据可视化&#xff0c;帮助用户更直观地分析数据变化。 1. 点阵图的优势 点阵图&…...

C++-匿名空间

匿名命名空间&#xff08;anonymous namespace&#xff09;是 C 中的一种特性&#xff0c;用于将符号&#xff08;如变量、函数或类&#xff09;限制在定义它们的源文件的作用域内。这意味着在该源文件外部&#xff0c;这些符号不可见&#xff0c;从而避免了命名冲突。 1. 定义…...

jdk的安装和环境变量配置

1.将从官网下载好的jdk放在自己想要放的位置&#xff0c;这里的位置是&#xff1a;E:\develop 2.新建一个文件夹用来放安装的jdk&#xff0c;将jdk安装的此目录&#xff0c;这里的位置是&#xff1a;E:\develop\jdk17 3.jdk安装好之后&#xff0c;点击jdk17目录&#xff0c;点…...

继承、Lambda、Objective-C和Swift

继承 东风系列导弹是镇国神器。东风41不是突然就造出来的&#xff0c;之前有很多种东风xx导弹&#xff0c;每种导弹都有自己的独特之处&#xff0c;相同之处都具备导弹基本特点。很多工厂有量产磨具的生产线&#xff0c;盖房子就图纸&#xff0c;建筑设计建设都有参考&#xff…...

设置服务器走本地代理

勾选&#xff1a; 然后&#xff1a; git clone https://github.com/rofl0r/proxychains-ng.git./configure --prefix/home/wangguisen/usr --sysconfdir/home/wangguisen/etcmakemake install# 在最后配置成本地代理地址 vim /home/wangguisen/etc/proxychains.confsocks4 17…...

刷题 -哈希

面试面试经典 150 题 - 哈希 383. 赎金信 - 一个哈希表搞定 class Solution { public:bool canConstruct(string ransomNote, string magazine) {int hash[26] {0};for (auto& ch : magazine) {hash[ch - a];}for (auto& ch : ransomNote) {if (--hash[ch - a] < …...

React响应式修改数组和对象

在React中&#xff0c;响应式地修改数组数据是一个常见的需求&#xff0c;它涉及到状态&#xff08;state&#xff09;的管理和更新。React的状态是不可变的&#xff0c;这意味着你不能直接修改状态对象中的数组元素&#xff0c;而是需要创建一个新的数组来更新状态。下面将详细…...

cerbot https证书免费自动续期

1. 简介 cerbot是一个开源的数字证书生成平台&#xff0c;简单好用。下面我们来看下安装配置和使用。 cerbot有很多种安装方式&#xff0c;有源码安装、第三方发布版本、pip安装和snap安装&#xff0c;官方推荐使用snap安装。 2. snap安装 snap官方安装文档&#xff0c;Sna…...

嵌入式硬件设计

嵌入式硬件设计是指针对嵌入式系统&#xff08;一种专用的计算机系统&#xff0c;通常嵌入到其他设备中&#xff09;进行的硬件设计工作。嵌入式系统广泛应用于消费电子、工业控制、医疗设备、汽车电子、航空航天等领域。以下是嵌入式硬件设计的主要内容和步骤&#xff1a; 1.…...

2024.09.24 校招 实习 内推 面经

&#x1f6f0;️ &#xff1a;neituijunsir 交* 流*裙 &#xff0c;内推/实习/校招汇总表格 1、校招 | 毫末智行2025届校园招聘正式启动 &#xff08;内推&#xff09; 校招 | 毫末智行2025届校园招聘正式启动 &#xff08;内推&#xff09; 2、校招 | 圭目机器人 2025 校…...

GIT安装及集成到IDEA中操作步骤

最近深感GIT使用技能太差&#xff0c;我只会些皮毛&#xff0c;还是得看官网&#xff0c;总结一下常用的操作方法吧。 GIT环境配置到IDEA中安装 一、GIt的基本的安装 这个不在这里赘述了&#xff0c;自己装一个git吧 二、给IDEA指定本地GIT的安装路径 1、下图这个是我本地的…...

Java使用线程池创建线程

一、线程前言 首先我们知道&#xff0c;线程的概念如果不知道可以去看这一篇Java中的线程&#xff0c;我们这篇主要讲述的是Java怎么使用线程池创建线程&#xff0c;首先我们要对线程池有点概念&#xff0c;其实顾名思义&#xff0c;线程池就是有喝多线程的一个池子类似于&…...

mysql UDF提权(实战案例)

作者&#xff1a;程序那点事儿 日期&#xff1a;2024/09/29 16:10 什么是UDF? 全称 User Define Function &#xff08;用户自定义函数&#xff09;UDF提权&#xff0c;就是通过自定义函数&#xff0c;实现执行系统的命令。 dll&#xff08;windows&#xff0c;dll文件是c语…...

【瑞昱RTL8763E】刷屏

1 显示界面填充 用户创建的各个界面在 rtk_gui group 中。各界面中 icon[]表对界面进行描述&#xff0c;表中的每个元素代表一 个显示元素&#xff0c;可以是背景、小图标、字符等&#xff0c;UI_WidgetTypeDef 结构体含义如下&#xff1a; typedef struct _UI_WidgetTypeDef …...

【黑马点评】使用RabbitMQ实现消息队列——3.使用Jmeter压力测试,导入批量token,测试异步秒杀下单

3 批量获取用户token&#xff0c;使用jmeter压力测试 3 批量获取用户token&#xff0c;使用jmeter压力测试3.1 需求3.2 实现3.2.1 环境配置3.2.2 修改登录接口UserController和实现类3.2.3 测试类 3.3 使用jmeter进行测试3.4 测试结果3.5 将用户登录逻辑修改回去 3 批量获取用户…...

第 21 章 一条记录的多幅面孔——事务的隔离级别与 MVCC

21.1 事前准备 CREATE TABLE hero ( number INT, NAME VARCHAR ( 100 ), country VARCHAR ( 100 ), PRIMARY KEY ( number ) ) ENGINE INNODB CHARSET utf8;INSERT INTO hero VALUES ( 1, 刘备, 蜀 );21.2 事务隔离级别 在保证事务隔离性的前提下&#xff0c;使用不同的隔…...

javaScript操作dom的事件(3个案例+代码+效果图)

目录 1.焦点事件 案例:登录表单的验证 1.代码 2.效果 3.解释 2.鼠标事件 案例:单击鼠标使小球跳跃 1.代码 2.效果 3.解释 3.键盘事件 案例:使用左右键控制小球左右移动 1.代码 2.效果 ​编辑 3.解释 1.焦点事件 focus 当获得焦点时出发(不会冒泡)blur 当失去焦点时出发(不会…...

国庆期间的问题,如何在老家访问杭州办公室的网络呢

背景&#xff1a;国庆期间的问题&#xff0c;如何在老家访问杭州办公室的网络呢 实现方案&#xff1a;异地组网 实现语言&#xff1a;Java 环境&#xff1a;三个网络&#xff0c;一台拥有公网IP的服务器、一台杭州本地机房内服务器、你老家所在网络中的一台电脑&#xff08;…...

动态规划算法——三步问题

1.题目解析 2.算法原理 本题可以近似看做泰波那契数列&#xff0c;即小孩到第一个台阶需要一步&#xff0c;到第二个台阶则是到第一个台阶的步数加上第一阶到第二阶的步数&#xff0c;同理第三阶就是第二阶的步数加上第二阶到第三阶的步数&#xff0c;由于小孩只能走三步&#…...

【鸿蒙学习】深入解析鸿蒙应用与元服务:含义、区别、应用场景及创建方法

文章目录 鸿蒙应用&#xff08;HarmonyOS App&#xff09;含义用于干什么优缺点 元服务&#xff08;Atomic Service&#xff09;含义用于干什么优缺点 鸿蒙应用与元服务的区别创建方法鸿蒙应用的创建元服务的创建 总结 随着科技的不断进步&#xff0c;操作系统也在不断迭代更新…...

React学习01 jsx、组件与组件的三大属性

文章目录 jsx的介绍与语法1.真实DOM和虚拟DOM2.jsx语法 模块与模块化&#xff0c;组件与组件化模块与模块化组件与组件化 React组件React事件绑定函数式组件类式组件组件属性state组件属性props组件属性ref 尚硅谷react教程官方文档学习记录笔记01 jsx的介绍与语法 1.真实DOM和…...

项目——超级马里奥——Day(3)

一、游戏开发思路&#xff1a; 1.Frame--->BackGround--->Obstacle---->BufferedImage&#xff0c;人物等 2.BackGround的构造函数&#xff1a; 只要记住窗口里边的每一个场景&#xff0c;只要游戏一开始就已经出现在屏幕里边的&#xff0c;都是在构造函数里边 3.绘…...

测试-BUG篇

文章目录 软件测试的生命周期BUGbug的概念描述bug的要素bug级别bug的生命周期 与开发产生争执怎么办&#xff08;高频考题&#xff09; 软件测试的生命周期 软件测试贯穿于软件的整个生命周期 BUG bug的概念 是指计算机程序中存在的一个错误(error)、缺陷(flaw)、疏忽(mista…...

vue2中 vue-count-to组件让数字从某个数字动态的显示到某个数字(后附vue3的用法)

1、首先安装 npm install vue-count-to2、使用 2.1、先导入组件 import countTo from ‘vue-count-to’2.2、注册组件 components: { countTo },2.3、使用组件 <countTo> <template><div class"home"><countTo class"count-to&qu…...

AI模型部署初认识

AI部署这个词儿大家肯定不陌生&#xff0c;可能有些小伙伴还不是很清楚这个是干嘛的&#xff0c;但总归是耳熟能详了。 近些年来&#xff0c;在深度学习算法已经足够卷卷卷之后&#xff0c;深度学习的另一个偏向于工程的方向–部署工业落地&#xff0c;才开始被谈论的多了起来…...

在线生成论文的网站有哪些?分享5款AI一键原创论文免费网站

一、千笔-AIPasspaper 千笔-AIPasspaper是一款备受推荐的AI写作助手&#xff0c;它集成了多种功能&#xff0c;包括论文大纲生成、内容填充、文献引用和查重修改等。这款工具基于最新的自然语言处理技术&#xff0c;能够帮助用户快速生成高质量的论文内容。 AI论文&#xff0…...

考研论坛平台|考研论坛小程序系统|基于java和微信小程序的考研论坛平台小程序设计与实现(源码+数据库+文档)

考研论坛平台小程序 目录 基于java和微信小程序的考研论坛平台小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂…...

Pandas 时间序列处理

Pandas 时间序列处理 说明&#xff1a; 请回答以下问题&#xff0c;以展示您对 pandas 中时间序列处理的全面理解。请在适用时提供代码示例。 问题 1 如何将日期字符串列表 [2023-01-01, 2023-01-02, 2023-01-03] 转换为 pandas 的 DatetimeIndex&#xff1f; 问题 2 给定一…...

PCL 1.8.1 + VTK 1.8.0 + QT5.14.2+ VS2017 环境搭建

先看看效果: PCL 1.8.1下载安装: Tags PointCloudLibrary/pcl GitHub 安装完成后: 如果VTK想重新编译的,可以看我的这篇博客:...