2021-10-19 Flowable笔记
一. Flowable API我们开发Flowable涉及到了一些Flowable的API,在开发的时候经常需要与这些API打交道。入口点为:ProcessEngine,我们有多种方式来创建它。通过ProcessEngine,我们可以获取工作流的不同服务类型,ProcessEngine和服务都是线程安全的,因此我们可以用作单例对象来使用这些服务。// 第一次会初始化和创建一个ProcessEngi
一. Flowable API
参考:Flowable学习笔记(一、入门) - 三分恶 - 博客园
我们开发Flowable涉及到了一些Flowable的API,在开发的时候经常需要与这些API打交道。
入口点为:ProcessEngine,我们有多种方式来创建它。
通过ProcessEngine,我们可以获取工作流的不同服务类型,ProcessEngine和服务都是线程安全的,因此我们可以用作单例对象来使用这些服务。
// 第一次会初始化和创建一个ProcessEngine,后续调用都会从缓存中直接返回,全局创建一次
// ProcessEngines.init()与ProcessEngines.destroy(). 初始化和消耗与ProcessEngines
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
- RepositoryService: 操作和管理流程的定义和部署,deployment(部署)是ProcessEngine的基本单元
- RuntimeService:每一个流程都可以创建许多的运行实例,RuntimeService启动流程的实例,检索和存储实例的变量信息
- IdentityService:管理组和用户的身份认证信息
- FormService:可选的服务
- HistoryService:检索ProcessEngine的历史数据
- ManagementService:检索数据库的元数据和表的信息,在编程的时候一般用不到
- DynamicBpmnService:动态的改变流程的定义,并且不需要重新部署,在生产环境很少使用
二。流程图及XML
参考:基于BPMN2.0的工作流(Workflow) - 简书
流程定义的说明:
-
我们假定启动流程需要提供一些信息,例如雇员名字、请假时长以及说明。当然,这些可以单独建模为流程中的第一步。 但是如果将它们作为流程的“输入信息”,就能保证只有在实际请求时才会建立一个流程实例。否则(将提交作为流程的第一步),用户可能在提交之前改变主意并取消,但流程实例已经创建了。 在某些场景中,就可能影响重要的指标(例如启动了多少申请,但还未完成),取决于业务目标。
-
左侧的圆圈叫做启动事件(start event)。这是一个流程实例的起点。
-
第一个矩形是一个用户任务(user task)。这是流程中人类用户操作的步骤。在这个例子中,经理需要批准或驳回申请。
-
取决于经理的决定,排他网关(exclusive gateway) (带叉的菱形)会将流程实例路由至批准或驳回路径。
-
如果批准,则需要将申请注册至某个外部系统,并跟着另一个用户任务,将经理的决定通知给申请人。当然也可以改为发送邮件。
-
如果驳回,则为雇员发送一封邮件通知他。
这里我们直接撰写XML,以熟悉BPMN 2.0及其概念。
以下是与上面展示的流程图对应的BPMN 2.0 XML。这里只包含了“流程部分”。如果使用图形化建模工具,实际的XML文件还将包含“可视化部分”,用于描述图形信息,如流程定义中各个元素的坐标(所有的图形化信息包含在XML的BPMNDiagram标签中,作为definitions标签的子元素)。
在src/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="holiday-request" 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">
<!--顺序流条件:以表达式(expression)的形式定义了条件(condition) -->
<conditionExpression xsi:type="tFormalExpression">
<!--条件表达式:是${approved == true}的简写-->
<![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="edu.hpu.process.CallExternalSystemDelegate"/>
<userTask id="holidayApprovedTask" name="Holiday Approve!"/>
<sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>
<serviceTask id="sendRejectionMail" name="Send out rejection email" flowable:class="edu.hpu.process.SendRejectionMail"/>
<sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>
<!--结束事件-->
<endEvent id="approveEnd"/>
<endEvent id="rejectEnd"/>
</process>
</definitions>
-
每一个步骤(在BPMN 2.0术语中称作活动(activity))都有一个id属性,为其提供一个在XML文件中唯一的标识符。所有的活动都可以设置一个名字,以提高流程图的可读性。
-
活动之间通过顺序流(sequence flow)连接,在流程图中是一个有向箭头。在执行流程实例时,执行(execution)会从启动事件沿着顺序流流向下一个活动。
-
离开排他网关(带有X的菱形)的顺序流很特别:都以表达式(expression)的形式定义了条件(condition) 。当流程实例的执行到达这个网关时,会计算条件,并使用第一个计算为true的顺序流。这就是排他的含义:只选择一个。当然如果需要不同的路由策略,可以使用其他类型的网关。
-
这里用作条件的表达式为𝑎𝑝𝑝𝑟𝑜𝑣𝑒𝑑,这是approved,这是{approved == true}的简写。变量’approved’被称作流程变量(process variable)。流程变量是持久化的数据,与流程实例存储在一起,并可以在流程实例的生命周期中使用。在这个例子里,我们需要在特定的地方(当经理用户任务提交时,或者以Flowable的术语来说,完成(complete)时)设置这个流程变量,因为这不是流程实例启动时就能获取的数据。
三 .数据库表
ACT_RE_:’RE’表示repository(存储 ),RepositoryService接口所操作的表。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则等)。
2、ACT_RU_:‘RU’表示runtime,运行时表-RuntimeService。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的数据。Activiti只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的表小且快。
3、ACT_ID_:’ID’表示identity (组织机构),IdentityService接口所操作的表。用户记录,流程中使用到的用户和组。这些表包含标识的信息,如用户,用户组,等等。
4、ACT_HI_:’HI’表示history,历史数据表,HistoryService。就是这些表包含着流程执行的历史相关数据,如结束的流程实例,变量,任务,等等
5、ACT_GE_*:全局通用数据及设置(general),各种情况都使用的数据。
四.流程操作
参考:Flowable 流程实例_tengyunyang的博客-CSDN博客
1. 部署流程
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
.setJdbcPassword("")
.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flowable?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8")
.setJdbcUsername("aihe")
.setJdbcPassword("123456")
.setJdbcDriver("com.mysql.jdbc.Driver")
// 如果数据表不存在的时候,自动创建数据表
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 执行完成后,就可以开始创建我们的流程了
ProcessEngine processEngine = cfg.buildProcessEngine();
// 使用BPMN 2.0定义process。存储为XML,同时也是可以可视化的。NPMN 2.0标准可以让技术人员与业务人员都
// 参与讨论业务流程中来
// 部署流程
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("holiday-request.bpmn20.xml")
.deploy();
2. 启动流程实例
使用RuntimeService启动流程实例
操作的是act_ru_execution表,如果是用户任务节点,同时也会在act_ru_task添加一条记录
String processDefinitionKey = "leave";
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
System.out.println(processInstance.getId()+","+processInstance.getActivityId());
3. 查询个人任务 TaskService(act_ru_task)
从processEngine中应该得到TaskService
使用TaskService获取到任务查询对象TaskQuery
为查询对象添加过滤条件,使用taskAssignee指定任务的办理者(即查询指定用户的待办任务),同时可以添加分页排序等过滤条件
调用list方法进行查询
String assignee = "张三";
String processDefinitionKey = "leave";
List<Task> list = taskService.createTaskQuery()
.taskAssignee(assignee)
.processDefinitionKey(processDefinitionKey).list();
list.forEach(v -> System.out.println(v.getId() + " "
+ v.getName() + " " + v.getTaskDefinitionKey()
+ " " + v.getExecutionId() + " " + v.getProcessInstanceId() + " " + v.getCreateTime()));
4.完成个人任务
对于执行完的任务,Flowable将从act_ru_task表中删除该任务,下一个任务会被插入进来(这两个操作是在一个事物中)
String taskId = "20006";
taskService.complete(taskId);
5. 查询流程状态
查询流程实例状态 判断流程正在执行还是结束
String processInstanceId = "30001";
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
if (processInstance != null) {
System.out.println("当前流程实例正在运行");
} else {
System.out.println("当前流程实例正在运行");
}
6. 流程发起人设置
String authenticatedUserId = "tyy";
identityService.setAuthenticatedUserId(authenticatedUserId);
String processDefinitionKey = "leave";
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
System.out.println(processInstance.getId() + "," + processInstance.getActivityId());
更多推荐
所有评论(0)