Flowable最新版670入门篇之基于JavaAPI的

「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

作者:汤圆

个人博客:javalover.cc

前言

前面我们接触了很多Flowable以及Flowable UI相关方面的例子;

这篇我们再通过一个例子,来系统地了解一下BPMN以及Flowable的相关概念;

为了熟悉Flowable的相关API,这里我们用的例子是基于JavaAPI的。

同时也有用到flowable-ui相关知识

目录

  1. 背景介绍
  2. 流程定义
  3. 部署流程
  4. 配置用户、组、权限
  5. UI界面启动流程
  6. 代码层面启动流程

正文

1. 背景介绍

这里的案例是基于一个公司来讲的,比如一个公司有股东,有经理,有财务;

每个月财务都需要把报表提交给上级经理,经理审批通过后,会发送给股东。

2. 流程定义

这里我们先看一个图,如下所示:这里我们直接引用官方的图

image-20211109143551966

其中包括的元素有:

  • 空的启动事件
  • 用户任务-写每个月的财务报表
  • 用户任务-审核每个月的财务报表
  • 空的结束事件

下面我们就来编写这个bpmn.xml文件:FinancialReportProcess.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
32
33
34
35
36
37
38
39
40
41
42
43
xml复制代码<definitions id="definitions"
targetNamespace="http://flowable.org/bpmn20"
xmlns:flowable="http://flowable.org/bpmn"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">

<process id="financialReport" name="Monthly financial report reminder process">

<startEvent id="theStart" />

<sequenceFlow id="flow1" sourceRef="theStart" targetRef="writeReportTask" />

<userTask id="writeReportTask" name="Write monthly financial report" >
<documentation>
Write monthly financial report for publication to shareholders.
</documentation>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>accountancy</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>

<sequenceFlow id="flow2" sourceRef="writeReportTask" targetRef="verifyReportTask" />

<userTask id="verifyReportTask" name="Verify monthly financial report" >
<documentation>
Verify monthly financial report composed by the accountancy department.
This financial report is going to be sent to all the company shareholders.
</documentation>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>

<sequenceFlow id="flow3" sourceRef="verifyReportTask" targetRef="theEnd" />

<endEvent id="theEnd" />

</process>

</definitions>

3. 部署流程

这里我们创建一个maven程序,将刚才创建的流程定义部署到资源目录下,完整路径为:src/main/resources/FinancialReportProcess.bpmn20.xml

主程序如下所示:这里我们直接运行主程序,就可以把流程定义部署到flowable中,这里的实际存储地址就是程序中的那个h2数据库

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
java复制代码package org.flowable;

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FinancialReport {
public static void main(String[] args) {
// 1. 流程引擎
// 1.1 流程引擎 配置
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
.setJdbcUrl("jdbc:h2:~/flowable-db/engine-db;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9093;DB_CLOSE_DELAY=-1")
.setJdbcUsername("flowable")
.setJdbcPassword("flowable")
.setJdbcDriver("org.h2.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 1.2 构建流程引擎
ProcessEngine processEngine = cfg.buildProcessEngine();

// 2. 流程定义
// 2.1 将 流程定义文件 部署到 流程引擎 中
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("FinancialReportProcess.bpmn20.xml")
.deploy();

}
}

PS:程序中的h2数据库配置 跟 官方的 flowable-ui.war 例子中的 h2 数据库是保持一致的(通过解压flowable-ui.war即可看到相关参数配置),方便后续的界面化操作

这里我们需要明白一点:流程启动后,每执行一步,都会将这一步的状态和数据保存到数据库中,此时就算流程重启,数据也不会丢失;

比如流程启动后,执行了空的启动事件,此时来到第一个用户任务:任务内容是填写财务报表,任务的分配人/组是财务组,任务的状态为等待,那么这几个数据就会保存到数据库中;

当这个任务完成时,流程才会继续往下走,走到下一个任务,继续等待(同时存储任务的相关数据)。

这里的部署其实有很多种方式,详细参考:wwv.flowable.com/open-source…

4. 配置用户、组、权限

下面我们需要涉及到之前flowable-ui介绍的东西

先运行flowable-ui.war程序:下载地址

1
bash复制代码java -jar flowable-ui.war

启动成功之后,访问: http://localhost:8080/flowable-ui/

用admin/test登录之后,分别执行如下操作:

  • 进入IDM管理界面,创建两个用户:jalon 和 tangyuan(这个名字随便起)
  • 给上面这两个用户分配工作流权限
  • 创建两个组:accountancy 和 management(一个是财务组,一个是经理组,在xml中有定义)
  • 将jalon添加到accountancy 组,将 tangyuan 添加到 management 这个组

5. UI界面启动流程

  • 然后用jalon账号登录,进入任务应用程序之后,点击启动流程,就能看到刚才部署的流程定义

image-20211109153652930

  • 启动之后,点击活动任务进去,然后认领任务,因为这里没有表单需要填写,所以直接点击完成即可

image-20211109153847038

image-20211109153924333

image-20211109154012249

  • 然后用tangyuan账号登录,就可以看到jalon启动的流程,操作步骤类似,先认领,再完成

6. 代码层面启动流程

上面我们用UI实现了一个流程的完整过程,下面我们用代码来实现下:

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
java复制代码package org.flowable;

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FinancialReport {
public static void main(String[] args) {
// 1. 流程引擎
// 1.1 流程引擎 配置
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
.setJdbcUrl("jdbc:h2:~/flowable-db/engine-db;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9093;DB_CLOSE_DELAY=-1")
.setJdbcUsername("flowable")
.setJdbcPassword("flowable")
.setJdbcDriver("org.h2.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 1.2 构建流程引擎
ProcessEngine processEngine = cfg.buildProcessEngine();

// 2. 流程定义
// 2.1 将 流程定义文件 部署到 流程引擎 中
// RepositoryService repositoryService = processEngine.getRepositoryService();
// Deployment deployment = repositoryService.createDeployment()
// .addClasspathResource("FinancialReportProcess.bpmn20.xml")
// .deploy();
// 3. 启动流程
RuntimeService runtimeService = processEngine.getRuntimeService();
String procId = runtimeService.startProcessInstanceByKey("financialReport").getId();

// 4. 领取任务
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
for (Task task : tasks) {
System.out.println("Following task is available for accountancy group: " + task.getName());

// claim it
taskService.claim(task.getId(), "jalon");
}

// 查看领取的任务
tasks = taskService.createTaskQuery().taskAssignee("jalon").list();
for (Task task : tasks) {
System.out.println("Task for jalon: " + task.getName());

// Complete the task
taskService.complete(task.getId());
}

System.out.println("Number of tasks for jalon: "
+ taskService.createTaskQuery().taskAssignee("jalon").count());

// 5. 经理领取任务
tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
System.out.println("Following task is available for management group: " + task.getName());
taskService.claim(task.getId(), "tangyuan");
}

// 6. 完成任务
for (Task task : tasks) {
taskService.complete(task.getId());
}

// 7. 查看任务是否完成
HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance =
historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());
}
}

源码

上传在github

总结

这一篇主要是将代码和UI结合起来做了演示,虽然例子简单,但是概念都大同小异;

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%