Flowable-HelloWorld

简介

轻量级工作流引擎,使用Java编写,Flowable是Activiti的fork

github地址:https://github.com/flowable/flowable-engine

开源文档:https://wwv.flowable.com/open-source/docs/bpmn/ch02-GettingStarted/

6.5.0版本中文文档:https://jeesite.gitee.io/front/flowable/6.5.0/bpmn/index.html

Hello World

Gitee地址:https://gitee.com/aacopy/flowable-learn.git

创建一个spring boot项目

需要加入 spring web,

本示例,spring boot 2.6.1,flowable 6.7.1, mysql 5.7

创建数据库

新建一个mysql数据库,名称为flowable_learn

编写示例

  1. 加入maven依赖
1
2
3
4
5
6
7
8
9
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.7.1</version>
</dependency>
  1. 在application.properties新增配置项
1
2
3
4
5
server.servlet.context-path=/flowable-learn

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/flowable_learn?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456

此处有坑:

如果启动服务,报错找不到flowable的表

​ 原因:使用root用户登录,程序检测到该用户下的其他数据库中有flowable相关的表,就不再创建表了,但是在使用的时候又找不到表。

​ 解决:在url后面追加&nullCatalogMeansCurrent=true

1
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/flowable_learn?characterEncoding=UTF-8&nullCatalogMeansCurrent=true
  1. 在resources文件夹下新建文件夹processes
  2. 创建一个流程文件hello-world.bpmn20.xml,复制以下内容到文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://flowable.org/test" exporter="Flowable Open Source Modeler" exporterVersion="1.1.0-SNAPSHOT">
<process id="helloWorldProcess" name="Hello World Process">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />
<userTask id="theTask" name="my task" flowable:assignee="aacopy" />
<sequenceFlow id="flow2" sourceRef="theTask" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_helloWorldProcess">
<bpmndi:BPMNPlane id="BPMNPlane_helloWorldProcess" bpmnElement="helloWorldProcess">
<bpmndi:BPMNEdge id="flow1_di" bpmnElement="flow1">
<omgdi:waypoint x="130" y="178" />
<omgdi:waypoint x="180" y="178" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="flow2_di" bpmnElement="flow2">
<omgdi:waypoint x="280" y="178" />
<omgdi:waypoint x="332" y="178" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="BPMNShape_theStart" bpmnElement="theStart">
<omgdc:Bounds x="100" y="163" width="30" height="30" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="theTask_di" bpmnElement="theTask">
<omgdc:Bounds x="180" y="138" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="theEnd_di" bpmnElement="theEnd">
<omgdc:Bounds x="332" y="160" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
  1. 编写HelloWorldController类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package cn.aacopy.learn.flowable;

import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author iseven.yang
* @date 2021/12/2 15:40
*/
@RestController
@RequestMapping("/helloWorld")
public class HelloWorldController {

@Autowired
private RuntimeService runtimeService;

@Autowired
private TaskService taskService;

@Autowired
private RepositoryService repositoryService;

/**
* 查看流程图
* @param response
* @throws IOException
*/
@RequestMapping("/image")
public void image(HttpServletResponse response) throws IOException {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("helloWorldProcess").latestVersion().singleResult();
InputStream imageStream = repositoryService.getProcessDiagram(processDefinition.getId());
byte[] data = IoUtil.readInputStream(imageStream, "image inputStream name");
response.setContentType(MediaType.IMAGE_PNG_VALUE);
response.getOutputStream().write(data);
}

/**
* 启动流程
* @return
*/
@RequestMapping("/start")
public String start() {
runtimeService.startProcessInstanceByKey("helloWorldProcess");
return "success";
}

/**
* 获取待办列表
* @param assignee
* @return
*/
@RequestMapping("/todo")
public List<Map<String, Object>> todo(String assignee) {
List<Task> list = taskService.createTaskQuery()
.taskAssignee(assignee).orderByTaskCreateTime().desc().list();
return list.stream().map(task -> {
Map<String, Object> taskMap = new HashMap<>();
taskMap.put("id", task.getId());
taskMap.put("name", task.getName());
taskMap.put("createTime", task.getCreateTime());
return taskMap;
}).collect(Collectors.toList());
}

/**
* 提交任务
* @param taskId
* @return
*/
@RequestMapping("/complete")
public String complete(String taskId) {
taskService.complete(taskId);
return "success";
}

}

运行示例

第一次启动,程序会自动创建flowable相关表,启动需要的时间较长

打开浏览器测试

  1. 查看流程图

http://127.0.0.1:8080/flowable-learn/helloWorld/image

image-20211202211702240

  1. 启动流程

http://127.0.0.1:8080/flowable-learn/helloWorld/start

  1. 查看待办任务

http://127.0.0.1:8080/flowable-learn/helloWorld/todo?assignee=aacopy

1
[{"createTime":"2021-12-02T08:57:27.886+00:00","name":"my task","id":"e0193bb3-534d-11ec-ac8c-d08e7902fe33"}]
  1. 提交任务

taskId入参填写“查看待办任务”接口返回列表中的id值

http://127.0.0.1:8080/flowable-learn/helloWorld/complete?taskId=e0193bb3-534d-11ec-ac8c-d08e7902fe33