前言
阶段时间需要使用工作流,最终选择了Camunda,其中遇到的问题需要不停的查找不同文档,今天整理一下,方便从未使用过的小伙伴尽量一篇文档了解全部基础。
一、环境部署
java环境是java8,Camunda版本选择的7.19.0。
1.添加依赖
pom.xml文件中添加下面依赖
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter</artifactId>
<version>7.19.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
<version>7.19.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
<version>7.19.0</version>
</dependency>
2.登录配置和数据库配置
在bootstrap.yml文件中添加以下配置
# camunda登录信息配置
camunda.bpm:
admin-user:
id: admin #用户名
password: 123456 #密码
firstName: pkk
filter:
create: All tasks
#数据库配置
spring:
datasource:
type: ***.alibaba.druid.pool.DruidDataSource
driver-class-name: ***.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/camunda
username: root
password:
数据库需要自己创建,服务启动后,会自动创建Camunda表。
3.表结构
Camunda相关表大概分这几类,主要讲下常用的:
ACT_ID_:用户模块,配置文件里面的用户,信息就在此模块
ACT_HI_:表示流程历史记录。
act_hi_actinst: 执行的活动历史
act_hi_taskinst:执行任务历史
act_hi_procinst:执行流程实例历史
act_hi_varinst:流程变量历史表
ACT_RE_:表示流程资源存储
act_re_procdef:流程定义存储
act_re_deployment: 自动部署,springboot每次启动都会重新部署,生成记录
ACT_RU_:表示流程运行时表数据,流程结束后会删除
act_ru_execution:运行时流程实例
act_ru_task:运行时的任务
act_ru_variable:运行时的流程变量
二、绘制BPMN流程图文件
BPMN流程图文件是Camunda用来加载流程定义,为后续Camunda如何执行提供流程逻辑。
1.绘图工具
首先需要一个工具 Camunda Modeler 来画,下载地址:
https://camunda.***/download/modeler/
下载后解压双击执行 Camunda Modeler.exe 文件即可。
新建BPMN文件,选择最常用的Camunda platform 7
绘制一个简单流程
2.分类介绍
一个完整流程要从开始事件开始,然后经过业务流程逻辑,最终到结束事件。中间最常用的是任务(Task)和网关(Gateway),下面大概介绍一下这两个分类:
2.1 任务(Task)
任务大概分两种,用户任务 和 系统任务。
用户任务(User Task):具体来说就是需要用户手动执行的任务,即需要我们编写完业务代码后,调用代码,来提交当前任务,当前任务才会被完成,从而走到下一个流程。
执行流程时,需要编写变量,才能把信息在任务时获取和传递变量。
单击工具最右侧隐藏框,把信息框拉出来。
选中用户任务后,即可对这个任务变量进行编辑,主要关注这几个参数:
Name:自定义,可为空。
ID:默认生成,可自定义,表达一个流程中的唯一任务。
Assignee:受理人,这个很重要,表示这个任务的处理人。
流程间的变量传递有这么几种方式:
- 写死,就比如 zhangsan
- 表达式,比如上面写的 ${user},这种需要传入参数,其实就是启动参数的时候传入,传入参数,可选值为一个Map<String,Object>,之后的流程可查看次参数,上面写的是 user, 所以map里面的key需要带着user,不然会报错。
系统任务(Service Task):配置调用的代码实例后,系统会自动帮我们完成的任务。
系统任务的配置除了name和id,关注这几个参数:
Type:表示系统代码的类型,java中通常推荐Delegate expression,代码中需要实现JavaDelegate接口。
Delegate expression:配置具体的类实例名;上图${testService}要和定义的Bean名称一致。
配置表达式可以实现JavaDelegate接口使用类名配置,快捷写法如下,比较推荐下面这种,此种可灵活配置bean和spring结合使用,注入service等业务方法
@Bean("testService")
JavaDelegate testService() {
return execution -> {
Map<String, Object> variables = execution.getVariables();
log.info("variables:{}",variables);
//业务逻辑
};
}
也可以自定义类实现JavaDelegate接口。
2.2会签/或签
会签或签是对用户任务的一种设置,这里单独介绍一下。
用户任务可以选择不同的执行方式,包括并行任务、串行任务和循环任务。
并行:同时发生的任务。
串行:也叫顺序任务,按顺序执行的任务。
循环:顾名思义
会签/或签一般是并行任务,主要区别是完成条件的不同。选择并行任务后,主要关注这几个配置参数
Assignee:上面讲到过,当前任务的受理人。
Collection:参数集合;比如这个任务需要多人处理,则需要传入一个处理人集合。
Element variable:集合元素;可以理解为上面集合中每个元素的变量名,要和Assignee定义的变量一致
***pletion condition:完成条件;会签和或签主要是在这里区分,当然也可以根据实际业务需求自定义逻辑。
变量中,nrOfInstances:代表当前任务实例的总数。nrOf***pletedInstances:代表当前任务实例中已完成的数量。
因为会签表示所有人都要完成,此任务才完成;或签表示至少一人完成,这个任务即完成。因此:
会签的完成条件配置:${nrOfInstances == nrOf***pletedInstances}
或签的完成条件配置:${nrOf***pletedInstances == 1}
2.3网关(Gateway)
排他网关(Exclusive Gateway):
意义:用于选择一条单一路径继续流程。
用法:根据条件选择下一个活动。例如,根据订单金额决定是否需要额外审批。
并行网关(Parallel Gateway):
意义:允许多条路径同时进行。
用法:同时执行多个并行任务。例如,同时发送邮件通知客户和更新库存系统。
复杂网关(***plex Gateway):
意义:用于更复杂的路由逻辑。
用法:处理更复杂的流程分支逻辑。
2.4网关条件
配置完网关后,对于网关后面的任务,具体要走哪条流程,可通过点击网关向后面流程的线来进行配置,主要关注以下参数:
Type:条件,通常选择表达式Expression
Condition Expression:自定义满足条件的表达式。
三、代码介绍
1.Camunda 服务概述
在使用Camunda BPM引擎时,有几个核心服务可以帮助我们管理和执行流程。以下是这些服务的基本介绍以及它们的主要用途:
RepositoryService:是你与Camunda引擎交互的第一个切入点。它主要用于管理流程定义的部署,包括上传流程定义文件(如BPMN文件)到引擎中。
主要功能:
- 部署和管理流程定义。
- 查询已部署的流程定义和部署信息。
- 挂起和激活流程定义,控制其是否可以被启动。
- 检索流程定义中的文件和流程图。
RuntimeService:是用于在流程执行期间与引擎交互的服务。它允许启动流程实例,并且可以查询正在执行的流程实例状态。
主要功能:
- 启动流程实例。
- 存储和检索流程实例的变量。
- 查询正在执行的流程实例和执行实例(指向流程实例当前位置的“令牌”)。
- 处理流程实例的外部触发。
TaskService:专注于管理流程中的任务,特别是那些需要人为干预的任务。
主要功能:
- 查询分配给用户的任务。
- 创建新的任务,这些任务可以独立于任何流程实例。
- 分配任务给用户或组。
- 认领和完成任务。
HistoryService:提供了访问流程执行历史记录的功能。
主要功能:
- 查询流程实例的历史数据,如开始时间、执行用户、任务耗时等。
- 数据持久化级别可配置。
IdentityService:IdentityService提供了管理用户和组的功能,但请注意,核心引擎并不会在运行时验证用户身份。
主要功能:
- 创建、更新、删除和查询用户和组。
- 尽管可以将任务分配给任何用户,但实际的身份验证和授权需在应用层实现。
2.Query API
Camunda引擎提供了多种方式来查询数据。
主要功能:
- Java Queries:使用面向对象的API进行查询,适用于大多数场景。
- Native Queries:直接构建SQL查询语句,适用于复杂或特定的需求。
3.示例
启动流程:
@PostMapping("/start")
public String start(@RequestBody RuntimeVO vo) {
String processId = vo.getProcessId();
ProcessInstance instance = runtimeService.startProcessInstanceByKey(processId, vo.getVariables());
return instance.getId();
}
暂停流程:
runtimeService.suspendProcessInstanceById(instance.getId());
重新激活流程:
runtimeService.activateProcessInstanceById(instance.getId());
删除流程:同时会删除任务
runtimeService.deleteProcessInstance(instance.getId(), "删除");
查询流程:
@PostMapping("/get")
public List<ProcessInstance> get(@RequestBody RuntimeVO vo) {
return runtimeService.createProcessInstanceQuery().processInstanceId(vo.getInstanceId()).list();
}
完成任务:
@PostMapping("/***plete")
public void ***plete(@RequestBody TaskVO taskVO) {
taskService.***plete(taskVO.getTaskId(), taskVO.getVariables());
}
任务回退:
大体思路是拿到当前的任务,及当前任务的上一个历史任务,然后重启
Task activeTask = taskService.createTaskQuery()
.taskId(taskId)
.active()
.singleResult();
List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(instanceId)
.orderByHistoricActivityInstanceStartTime()
.desc()
.list();
List<HistoricTaskInstance> historicTaskInstances = historicTaskInstance.stream().filter(v -> !v.getTaskDefinitionKey().equals(activeTask.getTaskDefinitionKey())).toList();
Assert.notEmpty(historicTaskInstances, "当前已是初始任务!");
HistoricTaskInstance curr = historicTaskInstances.get(0);
runtimeService.createProcessInstanceModification(instanceId)
.cancelAllForActivity(activeTask.getTaskDefinitionKey())
.setAnnotation("重新执行")
.startBeforeActivity(curr.getTaskDefinitionKey())
.execute();
4.任务相关API
基于service的查询类,都可先构建一个 query,然后在附上查询条件
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
List<Task> list = taskService.createTaskQuery().taskAssignee("zhangsan").list();
List<ProcessInstance> instances = runtimeService.createProcessInstanceQuery().listPage(1, 10);
查询历史任务
List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().list();
查询当前任务/分页
List<Task> list = taskService.createTaskQuery().orderByTaskCreateTime().desc().list();
四、内部管理页面
在服务的resources文件夹下新建bpmn文件夹,把编辑好的bpmn文件放到bpmn文件夹下,启动服务时,服务会自动加载流程定义文件到应用中。
启动成功后,访问ip:port,进入工作流管理页面,用上面配置的登录信息登录,进入首页。
Cockpit:这是Camunda的管理控制台,用于监视和调试流程实例。你可以在这里查看流程定义、流程实例、历史数据等。它是开发人员和管理员的主要工具,用于理解流程行为和诊断问题。
Tasklist:这是一个任务列表,用于查看和管理当前待办事项。对于那些需要完成任务的用户来说,这是一个重要的入口点。
Admin:这是Camunda的管理工具,用于管理用户、组、权限和数据库连接等。它提供了对系统设置的全面控制。
对下面这个流程简单演示一下:
1.点击Tasklist,进入任务列表,点击右上角start process,开启一个流程。
2.选择一个流程定义,输入业务key(实例唯一),添加下一任务所需的参数,点击开始。如下,代表下一个任务的处理人的id为p1。这样,一个流程实例便启动了。
3.登录用户p1,进行审批完成。因为后面网关里面的判断条件有${day>3}和${day<=3},因此这里要添加day=4(满足day>3,要走用户任务2)。
4.点击完成后,走到系统任务中,如果有具体的业务逻辑,可放在这里处理。
5.登录用户p2,进行审批,也可以通过接口调用审批。
参考:
SpringBoot 优雅集成 Camunda 7以上 工作流引擎,保姆级教程!_springboot + camunda 教程-CSDN博客
简单易懂的springboot整合Camunda 7工作流入门教程_camunda7-CSDN博客