一、Flowable介绍
官方地址:https://www.flowable.com/open-source/docs/oss-introduction
中文V6.3.0文档地址 Flowable BPMN 用户手册 (v 6.3.0) (tkjohn.github.io)
flowable是BPMN2.0 的一个基于java的工作流引擎实现,flowable不仅包括了BPMN,还有DMN决策表和CMMN Case管理引擎,并且有自己的用户管理,微服务API等一系列功能,是一个服务平台。
flowable和Activiti有一些渊源,flowable的主程是Activiti的作者,从Activiti6开始,主程自己带人做了flowable。所以flowable是由Activiti6演变过来的
二、Flowable基础知识
1.创建ProcessEngine
创建一个基本的maven工程,添加flowable依赖和mysql依赖以及junit
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>6.5.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
配置日志打印
log4j.properties
log4j.rootLogger = DEBUG, CA
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern = %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n
@Test
public void testProcessEngine(){
// 创建 ProcessEngineConfiguration
ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();
// 配置数据库连接指令
configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("x");
configuration.setJdbcUrl("jdbc:mysql://192.168.1.xx:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
// 配置表生成策略
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 通过 ProcessEngineConfiguration 构建 processEngine
ProcessEngine processEngine = configuration.buildProcessEngine();
}
运行成功后,数据库会生成表,其中比较重要的有
act_ge_bytearry 定义了流程信息
act_re_deployment 流程部署信息
act_ru_job 工作
act_ru_task 任务
可以注意到,flowable中的表和Activiti相似度高
2.部署流程定义
Flowable引擎需要流程定义为BPMN2.0格式,这是一个业界接受的XML标准。
一个BPMN可以称之为一个流程定义Process definition。一个流程定义又可以启动多个流程实例Process instance。
下面是员工请假流程,流程定义 定义了请假的各个步骤,而流程实例对应员工提出的请假申请。
对下面流程图有疑问的可以参考我的博客 Activiti基础知识
保存xml到工作空间/main/resources下面,命名holiday-request.bpmn20.xml
<?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:xsd="http://www.w3.org/2001/XMLSchema"
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:flowable="http://flowable.org/bpmn"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="http://www.flowable.org/processdef">
<process id="holidayRequest" name="Holiday Request" isExecutable="true">
<startEvent id="startEvent"/>
<sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>
<userTask id="approveTask" name="Approve or reject request"/>
<sequenceFlow sourceRef="approveTask" targetRef="decision"/>
<exclusiveGateway id="decision"/>
<sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[
${approved}
]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="decision" targetRef="sendRejectionMail">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[
${!approved}
]]>
</conditionExpression>
</sequenceFlow>
<serviceTask id="externalSystemCall" name="Enter holidays in external system"
flowable:class="org.flowable.CallExternalSystemDelegate"/>
<sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>
<userTask id="holidayApprovedTask" name="Holiday approved"/>
<sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>
<serviceTask id="sendRejectionMail" name="Send out rejection email"
flowable:class="org.flowable.SendRejectionMail"/>
<sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>
<endEvent id="approveEnd"/>
<endEvent id="rejectEnd"/>
</process>
</definitions>
流程引擎下面比较重要的服
ProcessEngine
-RepositoryService
-RuntimeService
-TaskService
-HistoryService
添加部署测试
/**
* 获取流程引擎对象
*/
@Before
public void testProcessEngine(){
// 配置数据库连接指令
configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("x
");
configuration.setJdbcUrl("jdbc:mysql://192.168.1.x:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
// 配置表生成策略
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 通过 ProcessEngineConfiguration 构建 processEngine
ProcessEngine processEngine = configuration.buildProcessEngine();
}
/***
* 部署流程
*/
@Test
public void testDeploy(){
// 获取 ProcessEngine
ProcessEngine processEngine = configuration.buildProcessEngine();
// 获取资源对象
RepositoryService repositoryService = processEngine.getRepositoryService();
// 完成流程的部署操作
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("holiday-request.bpmn20.xml")
.name("请假流程")
.deploy();
System.out.println("deploy.getId() = " + deploy.getId());
System.out.println("deploy.getName() = " + deploy.getName());
}
查看数据库
在表ACT_GE_BYTEARRY中新增了一条bpmn信息
在ACT_RE_PROCDEF中新增了一条流程定义信息
在表ACT_RE_DEPLOYMENT中新增了一条部署记录
产看流程定义、删除流程定义
* 查询流程定义信息
*/
@Test
public void testDeployQuery(){
ProcessEngine processEngine = configuration.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId("1")
.singleResult();
System.out.println("processDefinition.getDeploymentId() = " + processDefinition.getDeploymentId());
System.out.println("processDefinition.getDeploymentId() = " + processDefinition.getDeploymentId());
System.out.println("processDefinition.getName() = " + processDefinition.getName());
System.out.println("processDefinition.getDescription() = " + processDefinition.getDescription());
}
/***
* 删除流程定义信息
*/
@Test
public void testDeleteQuery(){
ProcessEngine processEngine = configuration.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
// 删除部署流程,第一个参数是id,如果部署流程启动了,不允许删除
repositoryService.deleteDeployment("1");
// 第二个参数是级联参数,如果流程启动了,相关的任务会一并删除
// repositoryService.deleteDeployment("1", true);
}
3.启动流程实例
现在已经在流程引擎中部署了流程定义,因此可以使用流程定义作为模板,来启动易流程实例
/***
* 启动流程实例
*/
@Test
public void testRunProcess(){
ProcessEngine processEngine = configuration.buildProcessEngine();
// 通过runtimeService启动流程实例
RuntimeService runtimeService = processEngine.getRuntimeService();
// 构建流程变量,其实在业务中是从表单传递过来的
Map<String,Object> varivales = new HashMap<>();
varivales.put("employee", "张三");
varivales.put("nrOfHolidays",3);
varivales.put("description","感冒了,想要休息");
// 启动流程实例
runtimeService.startProcessInstanceByKey("holidayRequest", varivales);
}
ACT_RU_VARIABLE表中记录了流程变量信息
ACT_RU_TASK中记录了任务信息
ACT_RU_EXECUTION中记录了流程信息
4.查看任务
上面员工发起了一个请假流程,接下来就会流转到总经理处理,案例中的BPMN没有指定经理这的处理人,我们可以加一个
<userTask id="approveTask" name="Approve or reject request" flowable:assignee="lisi"/>
级联删除以前的流程,
重新部署流程
发起请假申请
任务查询
/***
* 测试任务查询
*/
@Test
public void testQueryTask(){
ProcessEngine processEngine = configuration.buildProcessEngine();
TaskService taskService = processEngine.getTaskService();
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey("holidayRequest")// 指定查询的流程编号
.taskAssignee("lisi")// 查询这个任务的处理人
.list();
for (Task task : list) {
System.out.println("task.getProcessDefinitionId() = " + task.getProcessDefinitionId());
System.out.println("task.getAssignee() = " + task.getAssignee());
}
}
5.完成任务
/***
* 完成任务
*/
@Test
public void testCompleteTask(){
ProcessEngine processEngine = configuration.buildProcessEngine();
TaskService taskService = processEngine.getTaskService();
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey("holidayRequest")// 指定查询的流程编号
.taskAssignee("lisi")// 查询这个任务的处理人
.list();
// 构建流程变量
Map<String,Object> varivales = new HashMap<>();
varivales.put("approved", "false");
for (Task task : list) {
taskService.complete(task.getId(), varivales);
}
}
重写org.flowable.SendRejectionMail 实现javaDeleagte委托类接口,实现自定义逻辑
6.流程的删除
/***
* 删除流程定义信息
*/
@Test
public void testDeleteProcessDefine (){
ProcessEngine processEngine = configuration.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
// 删除部署流程,第一个参数是id,如果部署流程启动了,不允许删除
// repositoryService.deleteDeployment("1");
// 第二个参数是级联参数,如果流程启动了,相关的任务会一并删除
repositoryService.deleteDeployment("5001", true);
}
7.查看历史信息
选择使用FLowable这样的流程引擎原因之一,是它可以自动存储所有流程实例的审计数据或历史数据。这些数据可以用于创建报告,深入展现组织运行的情况,瓶颈在哪里,等等。
例如,如果蜥蜴王显示流程实例已经执行的时间,就可以从ProcessEngine获取HistoryService,并创建历史活动(historical activies)的查询。在下面的代码片段中,我们可以看到我们添加了一些额外的过滤条件:
- 只选择一个特定流程实例的活动
- 只选择已完成的活动
结果按照结束时间排序,代表执行顺序
/***
* 获取流程任务历史数据
*/
@Test
public void testHistory(){
ProcessEngine processEngine = configuration.buildProcessEngine();
HistoryService historyService = processEngine.getHistoryService();
historyService.createHistoricActivityInstanceQuery()
.processDefinitionId("holidayRequest:1:7503")
.finished() // 查询历史记录的状态是完成的
.orderByHistoricActivityInstanceEndTime().asc()// 指定排序的字段
.list();
for (;;){
// 打印history消耗的时间、处理人、名称、任务编号等等
}
}
三、流程设计器
1.Eclipse 插件
https://eclipse.org/downloads/packages/release
注意 2020-06及以后版本支持JDK8
注意:
安装插件的方式有坑
本人比较懒,因为现在使用的是idea,电脑上的eclipse版本又比较老,所以想使用第二种方式。
2.Flowable UI应用
安装部署
第一步
安装说明地址
https://tkjohn.github.io/flowable-userguide/#flowableUIApps
tomcat下载地址
https://tomcat.apache.org/
flowable下载地址
https://www.flowable.com/open-source
第二步
解压后的war包放到tomcat的webapps下面。tomcat下的/bin/start.bat启动(如果启动乱码,检查conf/properties编码UTF-8/GBK)
第三步
登录 localhost:8080/flowable-ui,
账号密码 admin/test
控制台窗口能看到四个模块,就是下面官网中提到的内容
Flowable提供了几个web应用,用于演示及介绍Flowable项目提供的功能:
- Flowable IDM: 身份管理应用。为所有Flowable UI应用提供单点登录认证功能,并且为拥有IDM管理员权限的用户提供了管理用户、组与权限的功能。
- Flowable Modeler: 让具有建模权限的用户可以创建流程模型、表单、选择表与应用定义。
- Flowable Task: 运行时任务应用。提供了启动流程实例、编辑任务表单、完成任务,以及查询流程实例与任务的功能。
- Flowable Admin: 管理应用。让具有管理员权限的用户可以查询BPMN、DMN、Form及Content引擎,并提供了许多选项用于修改流程实例、任务、作业等。管理应用通过REST API连接至引擎,并与Flowable Task应用及Flowable REST应用一同部署。
绘制流程
点击创建新模型,创建一个新的流程
流程图界面
创建流程,分配处理人
绘制好的流程
部署流程
1.点击按钮导出 BPMN2
2.将导出的xml文件复制到 main/resources/下面
3.按照test测试类中的顺序部署流程定义,创建流程实例、
本篇文章工程github地址
https://github.com/cuim/flowable-demo17
其他实践参考地址
https://blog.csdn.net/qq_44787816/article/details/125303284