官网: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