目录
2. Flowable与springBoot项目整合... 3
5.4 设置审批人(Assignee or Group)... 10
1.1 参考文档:
官方文档:链接
官方文档汉化: 链接
简书上API介绍 : 链接 (重要,在写功能前先看一遍,很有用)
官方API : 链接
好的flowable博客地址:链接 (功能实现)
gitee上好的Demo:链接
我写的Demo地址:链接 (后续还会修改完善)
别人项目的使用文档 链接 (可以参考下功能和思路)
1.2 Flowable介绍
Flowable is a light-weight business process engine written in Java.这是官网文档对此框架的完美解释:Flowable是一个用java语言写的轻量级工作流引擎。
在简单了解flowable后与activiti框架相比的第一感觉就是开发方便快速,易与springBoot等各种框架快速整合。如果项目中需要快速实现一些工作流的相关功能那么用此框架是一个不错的选择。
- Flowable与springBoot项目整合
使用版本
springBoot版本:2.0.1.RELEASE
flowable版本:6.3.0
建议 mysql 5.7 以上,有人试过低版本数据库会启动失败的
添加依赖
<!--flowable工作流依赖-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.3.0</version>
</dependency>
添加flowable依赖后一定要有数据库依赖,不然会报错
加了flowable依赖就整合好了,是不是很意外
- flowable配置
配置方面只需配置好数据源就可以了 。初次运行时flowable会将自动执行flowable中的初始化脚本完成工作流所需要的数据表的建立,如果指定的数据库中还未创建过flowable的相关数据表的话。
-
Flowable数据库表(60张)
初次运行项目会生成上述60张表,其中
act_cmmn_: 表示的是CMMN流程引擎(cmmn)数据
act_dmn_: 表示的是DMN流程引擎(dmn)数据
act_evt_log表示事件日志
act_fo_: 表示的是表单引擎(form)数据
act_ge_: 表示的是通用数据(general),用于各种用例
act_hi_: 表示这些表包含历史数据(history),例如过去的流程实例、变量、任务等等
act_id_: 表示存储的是与用户身份(identity)相关的数据
act_prodef_info表示的是流程定义的信息。
act_re_: 表示的是流程定义(repository)相关数据的存储库。具有此前缀的表包含静态信息,例如流程定义和流程资源(图像、规则等)
act_ru_: 表示的是流程实例运行时(runtime)时的数据,这些是包含流程实例、用户任务、变量、作业等运行时数据的运行时表。Flowable仅在流程实例执行期间存储运行时数据,并在流程实例结束时删除记录。这使运行时表保持小而快。
5.1 流程部署
流程部署有7种方式,下面6种是通过代码的方式部署流程,另一种方式为 processes目录下的任何BPMN 2.0流程定义都会被自动部署。创建processes目录,并在其中创建示例流程定义,使用这种方式注意命名为 流程名.bpmn20.xml(我就是用的这一种,简单方便)
addInputStream()方式
@Test
public void addInputStreamTest() throws IOException {
// 定义的文件信息的流读取
InputStream inputStream = DeploymentBuilderTest.class.getClassLoader()
.getResource("com/shareniu/shareniu_flowable6/ch2/leave.bpmn")
.openStream();
// 流程定义的分类
String category = "shareniu_addInputStream";
// 构造DeploymentBuilder对象
DeploymentBuilder deploymentBuilder = repositoryService
.createDeployment().category(category)
.addInputStream(resourceName, inputStream);
// 部署
Deployment deploy = deploymentBuilder.deploy();
System.out.println(deploy);
}
addClasspathResource 方式
@Test
public void addClasspathResource() throws InterruptedException {
ProcessEngineConfigurationImpl processEngineConfiguration = Context
.getProcessEngineConfiguration();
System.out.println(processEngineConfiguration);
String resource = "com/shareniu/chapter3/common.bpmn";
// 流程定义的分类
String category = "shareniu_addClasspathResource";
// 构造DeploymentBuilder对象
Date date = new Date();
DeploymentBuilder deploymentBuilder = repositoryService
.createDeployment()
// .activateProcessDefinitionsOn(date)
.addClasspathResource(resource).category(category);
// 部署
processEngineConfiguration = Context.getProcessEngineConfiguration();
System.out.println(processEngineConfiguration);
Deployment deploy = deploymentBuilder.deploy();
System.out.println(deploy);
}
addString 方式
@Test
public void addString() {
String resource = "shareniu_addString.bpmn";
// 读取文件获取文件中定义的xml信息
String text = readTxtFile("E:/activitilearing/activiti/src/main/java/com/shareniu/chapter3/common.bpmn");
// 构造DeploymentBuilder对象
DeploymentBuilder deploymentBuilder = repositoryService
.createDeployment().addString(resource, text);
// 部署
Deployment deploy = deploymentBuilder.deploy();
}
addZip 方式
@Test
public void zip() {
InputStream inputStream = DeploymentBuilderTest.class.getClassLoader()
.getResourceAsStream("1.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
Deployment deploy = repositoryService.createDeployment()
.addZipInputStream(zipInputStream).deploy();
identityService.setAuthenticatedUserId("shareniu");
}
addByte 方式(略)
BpmnModel 方式(略)
上述方式仅做参考,我还是喜欢直接放到process文件夹下,省去部署
5.2 发起流程
流程发起的方法就比较多了,但是所有发起的方法都在RuntimeService里。
runtimeService: 主要用于管理流程在运行时产生的数据(流程参数,事件,流程实例,以及执行流)以及对正在运行的流程进行操作的API
在demo内,使用根据流程key值发起流程:
ProcessInstance startProcessInstanceByKey(String var1, String var2, Map<String, Object> var3);
黄色部分: 该方法为流程Key值。
绿色部分: 此处为流程变量,变量名需要与画流程图设置的变量名一致,可用于设置审批人,分支判断,流程走向。 变量可后续追加,也可一次写完
红色部分: 上述写法是把请假单据信息保存到自己创建的表内,主键放到flowable表中,做关联
蓝色部分: 在发起流程前设置发起人,(在demo中把第一个审批节点的审批人也设置成了发起人,用蓝色部分设置是因为有个方法能比较简单的查出来发起人的所有流程,这里写算是偷个懒)
第二行设置null 是因为这个方法最终使用一个ThreadLocal类型的变量进行存储,也就是与当前的线程绑定,所以流程实例启动完毕之后,需要设置为null,防止多线程的时候出问题。 然后到数据库表中就可以看到该流程发起人
5.3 查看个人任务
5.3.1发起人查看待审批任务,审批完成任务
因为在蓝色部分偷懒,所以这里直接调用startBy() 方法即可
因为流程结束后流程信息在数据库里有所改变所以查的方法也不一样
注意两个不同的地方审批未完成,是使用的 RuntimeService()
已完成,是使用的HistoryService()详见 简书上API介绍
5.3.2 审批人 (个人) 查看个人待审批任务,已审批任务
这里我之前踩过一个坑,把开始startTask后的第一个 userTask 当成了发起人,以为发起了上级就可以看到。然后原因是虽然流程发起了,但是本人不审批,导致领导查询待审批为 null,而我还一直百度,一直看文档找方法。
查询个人待审批任务使用TaskService调用 taskAssignee() 方法即可
查询审批人已审批任务 使用HistoryService的 taskAssignee
通过3.1 和 3.2 不难看出,查询执行中的为 RuntimeService 查询执行完成的为HistoryService
5.3.3 各种查询 组查询,组成员查询。。。。各种
先根据对应的***Service 调用对应***Query 然后调用方法即可
使用很简单,基本上什么条件都可以查,不知道方法含义也可以查 api à 链接
5.4 设置审批人(Assignee or Group)
通过流程图设置
这个比较简单就属于写死审批人 画流程图时 在 Assignee写, 可以一个 也可以多个用逗号隔开就好
通过变量设置(通过这种方式可以设置组成员,组)
有图就属于在画流程图时通过 {变量名} 这种方式设置审批人。
在代码中只需在该步骤运行 前 设置变量就可以了。
通过类设置(通过这种方式也可以设置组成员,组)
B步骤有写Listern类,那么程序会在A步骤完成后就调用B步骤的Listern类。上图写的就是赋审批人的方法。
另外类中delegateTask包含 taskID 有了taskId 那能做的事情就不仅仅局限于上述setAssignee了
5.5 任务申领,任务指派
指派任务
然后看源码
他的实现也就是给属性assignee 赋值的一个方法.
任务申领
组成员(BOSS组成员)申领任务,任务申领成功后该用户会成为该任务执行人(assignee)。当前任务就会在BOSS组其他成员的任务列表消失。申领任务代码:
taskService.claim(任务ID, "成员ID");
那么该用户查询任务的代码就从 .taskCandidateUser(userId)
改为 .taskAssignee(userId)
简单点说这个组任务已经改变为某人的 个人任务
5.6 审批
审批通过
Outcome = 通过 这是在流程图上 线的判断条件而已
对于Flowable引擎来说,complete() 这就是个外部信号,指示流程实例可以继续执行。任务本身会从运行时数据中移除,并沿着这个任务唯一的出口转移线(箭头指示),将执行移至下一步任务。
审批驳回 指定节点驳回(包含驳回到发起人)
第一个参数为 流程实例ID 流程发起后就可以得到 数据库对应字段 PROC_INST_ID_
根据实例ID 的到当前流程处于那一步骤
第二个参数为 选中的驳回节点名称 (id值)
然后调用方法即可,还是很简单的
6.1 排他网关
- 一个排他网关对应一个以上的顺序流
- 排他网关只会返回一条结果。当流程执行到排他网关时,流程引擎会自动检索网关出口,从上到下检索如果发现第一条决策结果为true或者没有设置条件的(默认为成立),则流出。
- 如果没有任何一个出口符合条件,则抛出异常
- 使用流程变量,设置连线的条件,并按照连线的条件执行工作流,如果没有条件符合的条件,则以默认的连线离开。例如:
6.2 并行网关
- 一个流程中流程实例只有1个,执行对象有多个
- 并行网关的功能是基于进入和外出的顺序流的:
分支(fork): 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。
汇聚(join): 所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通过汇聚网关。
- 并行网关的进入和外出都是使用相同节点标识
- 如果同一个并行网关有多个进入和多个外出顺序流, 它就同时具有分支和汇聚功能。 这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。
- 并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略。
并行网关不需要是“平衡的”(比如, 对应并行网关的进入和外出节点数目不一定相等)。如图中标示是合法的: