Camunda工作流引擎简单入门
官网:https://camunda.com/
官方文档:https://docs.camunda.org/get-started/spring-boot/project-setup/
阅读新体验:http://www.zhouhong.icu/post/155
一、简介
Camunda是一个工作流引擎,执行Bpmn2.0标准,因此依赖于基于bpmn的流程图(本质上是一个xml文件)
二、一个完整的报销 demo 入门
1、创建一个SpringBoot项目,导入数据库依赖、Camunda 等依赖
1 <dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-web</artifactId>
4 </dependency>
5 <dependency>
6 <groupId>org.mybatis.spring.boot</groupId>
7 <artifactId>mybatis-spring-boot-starter</artifactId>
8 <version>2.2.0</version>
9 </dependency>
10
11 <!-- https://mvnrepository.com/artifact/org.camunda.bpm.springboot/camunda-bpm-spring-boot-starter-webapp -->
12 <dependency>
13 <groupId>org.camunda.bpm.springboot</groupId>
14 <artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
15 <version>3.4.4</version>
16 </dependency>
17 <!-- https://mvnrepository.com/artifact/org.camunda.bpm.springboot/camunda-bpm-spring-boot-starter-rest -->
18 <dependency>
19 <groupId>org.camunda.bpm.springboot</groupId>
20 <artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
21 <version>3.4.4</version>
22 </dependency>
23
24 <dependency>
25 <groupId>mysql</groupId>
26 <artifactId>mysql-connector-java</artifactId>
27 <scope>runtime</scope>
28 </dependency>
29 <dependency>
30 <groupId>org.projectlombok</groupId>
31 <artifactId>lombok</artifactId>
32 <optional>true</optional>
33 </dependency>
34 <dependency>
35 <groupId>org.springframework.boot</groupId>
36 <artifactId>spring-boot-starter-test</artifactId>
37 <scope>test</scope>
38 </dependency>
39 <dependency>
40 <groupId>junit</groupId>
41 <artifactId>junit</artifactId>
42 <version>4.13.2</version>
43 </dependency>
44 <dependency>
45 <groupId>com.aliyun</groupId>
46 <artifactId>aliyun-java-sdk-ecs</artifactId>
47 <version>4.17.6</version>
48 </dependency>
application.yml 部分配置:
1 spring:
2 application:
3 name: camunda-demo
4 #数据源配置
5 datasource:
6 url: jdbc:mysql://127.0.0.1:3306/camunda-demo?serverTimezone=Asia/Shanghai
7 driver-class-name: com.mysql.cj.jdbc.Driver
8 username: root
9 password: 123456
10 camunda:
11 bpm:
12 #配置账户密码来访问Camunda自带的管理界面
13 admin-user:
14 id: admin
15 password: admin
16 first-name: admin
17 filter:
18 create: All tasks
19 #禁止自动部署resources下面的bpmn文件
20 auto-deployment-enabled: false
2、启动后会生成47张表:

3、访问 http://localhost:8080/

4、下载bpmn建模工具:https://camunda.com/download/modeler/
5、画一个报销流程图,申请人为shangsan、人事为lisi、经理为wangwu,保存后放到项目resources目录下面,同时进入控制台Admin目录下建立相关的人员信息。

注意:报销金额判断条件使用 Expression 表达式
6、流程定义部署
@PostMapping("/deploy")
public void deploy() {
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("BPMN/apply.bpmn")
.deploy();
System.out.println(deploy.getId());
}
用PostMan发起流程后会在ACT_RE_DEPLOYMENT表中看到一个流程的实例
7、启动流程实例
@PostMapping("/start")
public void runProcinst(){
Map<String,Object> params = new HashMap<>();
params.put("money",2001);
ProcessInstance holiday = runtimeService.startProcessInstanceByKey("apply",params);
}
然后切换到zhangsan用户,在控制台TaskList下查看

8、审批通过,在审批的过程中可以随意添加审批信息
@PostMapping("/taskComplete")
public void taskComplete(){
Task task = taskService.createTaskQuery()
.taskAssignee("zhangsan")
.singleResult();
params.put("approve2","lisi");
Map<String,Object> params = new HashMap<>();
taskService.complete(task.getId(),params);
}
切换 lisi 用户在控制台查看任务

9、进入控制台在Cockplt中查看流程走到哪(因为我们的money设置的是2001,大于2000,所以流程走到下面的那个分支)

10、其他关于流程的一些简单操作
1 /**
2 * @ClassName: camunda-demo
3 * @Description:
4 * @Author: zhouhong
5 * @Create: 2021-07-08 10:06
6 **/
7
8 @RestController
9 public class Test {
10
11 @Autowired
12 RepositoryService repositoryService;
13 @Autowired
14 RuntimeService runtimeService;
15 @Autowired
16 TaskService taskService;
17 @Autowired
18 HistoryService historyService;
19 @Autowired
20 ProcessEngine processEngine;
21
22 @Autowired
23 ProcessEngine engine;
24
25 /**
26 * @Description: 流程定义部署
27 * @Author: zhouhong
28 * @Date: 2021/7/8
29 */
30 @PostMapping("/deploy")
31 public void deploy() {
32 Deployment deploy = repositoryService.createDeployment()
33 .addClasspathResource("BPMN/apply.bpmn")
34 .deploy();
35 System.out.println(deploy.getId());
36 }
37
38 /**
39 * @Description: 开启一个流程实例
40 * @Author: zhouhong
41 * @Date: 2021/7/8
42 */
43 @PostMapping("/start")
44 public void runProcinst(){
45 Map<String,Object> params = new HashMap<>();
46 params.put("money",2001);
47 ProcessInstance apply = runtimeService.startProcessInstanceByKey("apply",params);
48 System.out.println(apply.getProcessDefinitionId());
49 System.out.println(apply.getId());
50 System.out.println(apply.getProcessInstanceId());
51 }
52
53 /**
54 * @Description: 流程任务查询
55 * @Author: zhouhong
56 * @Date: 2021/7/8
57 */
58 @PostMapping("/taskquery")
59 public void taskQuery() {
60 List<Task> tasks = taskService.createTaskQuery()
61 .processDefinitionKey("apply")
62 .list();
63 for (Task task : tasks) {
64 System.out.println(task.getAssignee());
65 System.out.println(task.getId());
66 System.out.println(task.getName());
67 System.out.println(task.getTenantId());
68 }
69 }
70
71 /**
72 * @Description: 当前需要处理的任务
73 * @Author: zhouhong
74 * @Date: 2021/7/8
75 */
76 @PostMapping("/mytaskquery")
77 public List<HistoricTaskInstance> myTaskQuery() {
78 List<HistoricTaskInstance> instances = engine.getHistoryService().createHistoricTaskInstanceQuery()
79 .taskAssignee("lisi").unfinished().orderByHistoricActivityInstanceStartTime().asc().list();
80 return instances;
81 }
82
83 /**
84 * @Description: 流程任务执行
85 * @Author: zhouhong
86 * @Date: 2021/7/8
87 */
88 @PostMapping("/taskComplete")
89 public void taskComplete(){
90 //目前lisi只有一个任务,业务中根据场景选择其他合适的方式
91 Task task = taskService.createTaskQuery()
92 .taskAssignee("zhangsan")
93 .singleResult();
94 Map<String,Object> params = new HashMap<>();
95 params.put("approve2","lisi");
96 taskService.complete(task.getId(),params);
97 }
98
99 /**
100 * @Description: 流程定义查询
101 * @Author: zhouhong
102 * @Date: 2021/7/8
103 */
104 @PostMapping("/queryDefine")
105 public void queryDefine(){
106 ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
107 List<ProcessDefinition> definitions = query.processDefinitionKey("apply")
108 .orderByProcessDefinitionVersion()
109 .desc()
110 .list();
111 for (ProcessDefinition definition : definitions) {
112 System.out.println(definition.getDeploymentId());
113 System.out.println(definition.getName());
114 System.out.println(definition.getVersion());
115 System.out.println(definition.getId());
116 System.out.println(definition.getKey());
117 }
118 }
119
120 /**
121 * 删除流程定义
122 */
123 @PostMapping("/deleteDefine")
124 public void deleteDefine(){
125 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
126 List<ProcessDefinition> definitions = processDefinitionQuery.processDefinitionKey("apply")
127 .orderByProcessDefinitionVersion()
128 .asc()
129 .list();
130 ProcessDefinition processDefinition = definitions.get(0);
131 if (processDefinition != null){
132 repositoryService.deleteDeployment(processDefinition.getDeploymentId(),true);
133 }
134 }
135
136 /**
137 * 查询历史信息
138 */
139 @PostMapping("/queryHistory")
140 public void queryHistory(){
141 List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
142 .finished()
143 .orderByHistoricActivityInstanceEndTime()
144 .asc()
145 .list();
146 for (HistoricActivityInstance instance : list) {
147 System.out.println(instance.getActivityId());
148 System.out.println(instance.getProcessDefinitionKey());
149 System.out.println(instance.getAssignee());
150 System.out.println(instance.getStartTime());
151 System.out.println(instance.getEndTime());
152 System.out.println("=============================");
153 }
154 }
155
156 /**
157 * 启动一个流程实例,并且添加一个业务key
158 * 业务key 可以在 act_ru_execution 中看到
159 */
160
161 public void startProcInstAddBusinessKey(){
162 ProcessInstance apply = runtimeService.startProcessInstanceByKey("apply", "aaaa-scsc-89uc");
163 System.out.println(apply.getBusinessKey());
164 }
165
166 }
167
Camunda工作流引擎简单入门的更多相关文章
- Slickflow.NET 开源工作流引擎快速入门之三: 简单或分支流程代码编写示例
前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从请假流程,或分支模式来快速了解引擎代码的编写. 1. 创建或分支流程图形 或分支流程是常见的 ...
- Slickflow.NET 开源工作流引擎快速入门之二: 简单并行分支流程代码编写示例
前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从一个最简单的并行分支流程来示例说明,如何快速了解引擎代码的编写. 版本:.NET Core2 ...
- Slickflow.NET 开源工作流引擎快速入门之一: 简单序列流程代码编写示例
前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从一个最简单的流程来示例说明,如何快速了解引擎代码的编写. 版本: .NETCore 2.1 ...
- RoadFlowCore工作流引擎快速入门
RoadFlow新建一个流程分为以下几步: 1.建表 在数据库建一张自己的业务表(根据你自己的业务需要确定表字段,如请假流程就有,请假人.请假时间.请假天数等字段),数据表必须要有一个主键,主键类型是 ...
- Slickflow.Graph 开源工作流引擎快速入门之四: 图形编码建模工具使用手册
前言: 业务人员绘制流程时,通常使用图形GUI界面交互操作来完成,然而对于需要频繁操作或者管理较多流程的系统管理用户,就需要一款辅助工具,来帮助他们快速完成流程的创建和编辑更新.Slickflow.G ...
- 工作流引擎activiti入门
眼下最新的版本号是5.17 1.下载:activiti-5.17.0.zip http://activiti.org/download.html 2.解压activiti-5.17.0.zip 3.打 ...
- 工作流引擎之Elsa入门系列教程之一 初始化项目并创建第一个工作流
引子 工作流(Workflow)是对工作流程及其各操作步骤之间业务规则的抽象.概括描述. 为了实现某个业务目标,需要多方参与.按预定规则提交数据时,就可以用到工作流. 通过流程引擎,我们按照流程图,编 ...
- Camunda开源流程引擎快速入门——Hello World
市场上比较有名的开源流程引擎有osworkflow.jbpm.activiti.flowable.camunda.由于jbpm.activiti.flowable这几个流程引擎出现的比较早,国内人用的 ...
- 工作流Activiti新手入门学习路线整理
写在前面: 最近项目中使用到了工作流,虽然此部分不是自己需要完成的,但是也涉及到了要调用写的接口.正好有时间,就了解下,以便之后能在其他项目中用到时,不至于什么都不知道什么都不了解. 这里就主要整理下 ...
随机推荐
- 使用Prometheus Operator 监控Kubernetes(15)
一.Prometheus概述: Prometheus是一个开源系统监测和警报工具箱. Prometheus Operator 是 CoreOS 开发的基于 Prometheus 的 Kubernete ...
- 云计算OpenStack核心组件---neutron网络服务(8)*****
一.neutron介绍 1.Neutron概述 传统的网络管理方式很大程度上依赖于管理员手工配置和维护各种网络硬件设备:而云环境下的网络已经变得非常复杂,特别是在多租户场景里,用户随时都可能需要创建. ...
- mysql基础之数据库备份和恢复的基础知识
备份数据的最终目的是为了在出现一些意外情况时,能够通过备份将数据还原,所以单单的备份数据往往是无法满足还原时的需求的,所以在备份数据库时,除了要备份数据本身,还要备份相关的数据库环境,如配置文件,定时 ...
- shell进阶之tree、pstree、lsof命令详解
一.tree命令详解: 主要功能是创建文件列表,将所有文件以树的形式列出来 -a 显示所有文件和目录. -A 使用ASNI绘图字符显示树状图而非以ASCII字符组合. -C 在文件和目录清单加上色彩, ...
- 僵尸进程和孤儿进程-(转自Anker's Blog)
2.基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当 ...
- jsoup select 选择器(Day_02)
"自己"这个东西是看不见的,撞上一些别的什么,反弹回来,才会了解"自己". 所以,跟很强的东西.可怕的东西.水准很高的东西相碰撞,然后才知道"自己&q ...
- JAVA并发(3)-ReentrantReadWriteLock的探索
1. 介绍 本文我们继续探究使用AQS的子类ReentrantReadWriteLock(读写锁).老规矩,先贴一下类图 ReentrantReadWriteLock这个类包含读锁和写锁,这两种锁都存 ...
- ThreadLocal与ThreadLocalMap源码分析
ThreadLocal类 该类主要用于不同线程存储自己的线程本地变量.本文先通过一个示例简单介绍该类的使用方法,然后从ThreadLocal类的初始化.存储结构.增删数据和hash值计算等几个方面,分 ...
- typeof的作用及用法
typeof的作用及用法 1.检查一个变量是否存在,是否有值. typeof在两种情况下会返回"undefined":一个变量没有被声明的时候,和一个变量的值是undefined的 ...
- 熬夜讲解vue3组合API中setup、 ref、reactive的用法
1.初识setUp的使用 简单介绍下面的代码功能: 使用ref函数,去使用监听某一个变量的变化,并且把它渲染到视图上. setUp函数是组合API的入口函数.这个是非常重要的. setUp可以去监听变 ...