Springboot整合Flowable入门-学习笔记

目录

1、定义流程(画图)

2、Springboot部署流程

3、Springboot删除所有流程

4、Springboot根据 流程部署ID 查询 流程定义ID

5、Springboot启动(发起)流程

6、Springboot查询任务

6.1全部任务

6.2我的任务(代办任务)

7、springboot审批任务

1、审批通过

2、驳回

8、Springboot流程状态管理

1、流程定义

1、挂起《流程定义》

2、激活《流程定义》

2、流程实例

1、挂起《流程实例》

2、激活《流程实例》

9、资源

1.单元测试代码

2.xml代码


看了很多文档,总结一个完整的工作流包含以下步骤:

  • 定义流程: 创建一个BPMN 2.0格式的流程定义文件。
  • 部署流程: 将流程定义文件部署到Flowable引擎中。
  • 启动流程实例: 使用部署好的流程定义启动一个新的流程实例。
  • 执行任务: 查询和完成流程实例中的任务

ps:我使用的工具是 IDEA2019, 环境JDK8,Springboot版本2.5.15,Flowable版本6.8.0

大家先搞懂一个概念:是先有 流程定义 才会有 流程实例

1、定义流程(画图)

现在有很多优秀的画BPMN2.0开源系统。

我这里使用的是IDEA的插件:Flowable BPMN visualizer

安装好插件之后,在资源目录创建一个processes(flowable默认读取resources/processes下的流程文件)

创建BPMN文件

创建BPMN视图

开始画图:(整个流程必须是有一个起点,一个任务,一个终点)

我这里画一个请假流程:(开始-人事审核-主管审核-结束)

用户任务(UserTask)属性解释:

  • id:

    • 描述: User Task的唯一标识符。
    • 示例: id="sid-bb849ec0-1482-4057-a447-c8d68adc9ca2"
  • name:

    • 描述: User Task的显示名称。
    • 示例: name="人事审核"
  • assignee:

    • 描述: 指定执行此任务的单个用户。
    • 示例: flowable:assignee="cpw"    
  • candidateUsers:

    • 描述: 任务的候选用户列表。这些用户都有资格完成任务。
    • 示例: flowable:candidateUsers="cpw,zhangsan,lisi" (通过逗号隔开)
  • candidateGroups:

    • 描述: 任务的候选用户组列表。这些用户组中的用户都有资格完成任务。
    • 示例: flowable:candidateGroups="managers" 
  • formKey:

    • 描述: 指定与任务关联的表单的键,用于在任务执行时显示相应的表单。
    • 示例: flowable:formKey="approveForm"
  • dueDate:

    • 描述: 任务的到期日期,可以是一个具体日期或相对时间表达式。
    • 示例: flowable:dueDate="${now() + 5 days}"
  • priority:

    • 描述: 任务的优先级,数值越高表示优先级越高。
    • 示例: flowable:priority="50"
  • documentation:

    • 描述: 任务的文档说明,可以提供任务的详细描述。
    • 示例: <documentation>This task requires approval from the manager.</documentation>
  • extensions:

    • 描述: 自定义属性,可以添加额外的配置。例如,自定义表单字段或执行特定操作

连接节点

点击一个图案 按住拖动右上角的箭头进行连线

好了,完整的一个图出来了、完整的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: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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef"><process id="flowDemo" name="flowDemo" isExecutable="true"><startEvent id="sid-bb849ec0-1482-4057-a447-c8d68adc9ca2" name="开始"/><userTask id="sid-c30c0960-a986-4cd6-80e2-bae02d6af707" name="人事审核" flowable:assignee="cpw"></userTask><userTask id="sid-fc70937d-9773-4db8-acb3-a3af3e6ccb39" name="主管审核" flowable:assignee="zhuguan"/><endEvent id="sid-712aab8a-a060-4363-b3eb-cd3fa9215808"/><sequenceFlow id="sid-2c879163-8816-4dd7-89bb-bf1a4485fef4" sourceRef="sid-bb849ec0-1482-4057-a447-c8d68adc9ca2" targetRef="sid-c30c0960-a986-4cd6-80e2-bae02d6af707"/><sequenceFlow id="sid-2fca88ff-d597-430c-a5e9-edfefbdd2569" sourceRef="sid-c30c0960-a986-4cd6-80e2-bae02d6af707" targetRef="sid-fc70937d-9773-4db8-acb3-a3af3e6ccb39"/><sequenceFlow id="sid-e8b6c848-1c54-4fdb-a8b0-e085d715c906" sourceRef="sid-fc70937d-9773-4db8-acb3-a3af3e6ccb39" targetRef="sid-712aab8a-a060-4363-b3eb-cd3fa9215808"/></process><bpmndi:BPMNDiagram id="BPMNDiagram_flowDemo"><bpmndi:BPMNPlane bpmnElement="flowDemo" id="BPMNPlane_flowDemo"><bpmndi:BPMNShape id="shape-d460f24b-1aac-4028-b625-929601acd3c0" bpmnElement="sid-bb849ec0-1482-4057-a447-c8d68adc9ca2"><omgdc:Bounds x="-375.0" y="-37.25" width="30.0" height="30.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape id="shape-ad3ec780-dd25-42f1-8e53-6ed0608d5b91" bpmnElement="sid-c30c0960-a986-4cd6-80e2-bae02d6af707"><omgdc:Bounds x="-282.75" y="-62.25" width="100.0" height="80.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape id="shape-2a1947d2-0365-4dd8-8083-9bdaa7bea300" bpmnElement="sid-fc70937d-9773-4db8-acb3-a3af3e6ccb39"><omgdc:Bounds x="-134.25" y="-62.25" width="100.0" height="80.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape id="shape-c748377a-bdcd-4892-b001-3621cf05589a" bpmnElement="sid-712aab8a-a060-4363-b3eb-cd3fa9215808"><omgdc:Bounds x="15.625" y="-37.25" width="30.0" height="30.0"/></bpmndi:BPMNShape><bpmndi:BPMNEdge id="edge-a51efb51-2d88-4eae-9ffe-baa2e50cd0e5" bpmnElement="sid-2c879163-8816-4dd7-89bb-bf1a4485fef4"><omgdi:waypoint x="-345.0" y="-22.25"/><omgdi:waypoint x="-282.75" y="-22.25"/></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="edge-69253e56-2532-4829-b515-d27caeeb275a" bpmnElement="sid-2fca88ff-d597-430c-a5e9-edfefbdd2569"><omgdi:waypoint x="-182.75" y="-22.25"/><omgdi:waypoint x="-134.25" y="-22.25"/></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="edge-86a73120-1957-453e-b988-7f2ede9f75dc" bpmnElement="sid-e8b6c848-1c54-4fdb-a8b0-e085d715c906"><omgdi:waypoint x="-34.25" y="-22.25"/><omgdi:waypoint x="-10.011603" y="-22.25"/><omgdi:waypoint x="15.625" y="-22.25"/></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

2、Springboot部署流程

有两种使用Flowable类的方法:

第一种是使用ProcessEngine,它里面包含了所有flowable的核心类,我们可以查看源码:

第二种是直接使用***Service

有哪些Service可以查看flowable的jar包下engine里的Serivce类

现在开始部署流程:(使用Springboot单元测试)

@SpringBootTest
@DisplayName("流程测试")
public class UnitTest {//第一种方法使用ProcessEngine@Resourceprivate ProcessEngine processEngine;//第二种方法使用若干个 ***Service//@Autowired//private RuntimeService runtimeService;//@Autowired//private RepositoryService repositoryServiceService;@DisplayName("部署流程")@Testvoid deployFlow(){Deployment deploy = processEngine.getRepositoryService().createDeployment() //创建部署对象.addClasspathResource("processes/flowDemo.bpmn20.xml") // 默认是在resources/processes下寻找,当然你可以自定义目录.name("第一个Flowable案例") //设置流程的名字.deploy(); //deploy部署流程System.out.println("部署流程ID为:"+deploy.getId()); //获取到当前流程的ID}
}

运行结果:获取到部署成功的流程的ID

部署成功之后会涉及到以下数据表

ACT_GE_BYTEARRAY

  • 描述: 存储二进制数据,如流程定义的BPMN XML文件,PNG图片和其他附加数据。

ACT_RE_DEPLOYMENT

  • 描述: 存储流程部署的信息。每次部署一个新版本的流程定义时,会在此表中创建一条记录。

ACT_RE_PROCDEF

  • 描述: 存储流程定义的元数据,包括流程的ID、版本、名称和相关的部署ID。

部署成功之后查看 ACT_RE_DEPLOYMENT 表,你会发现创建的两条数据

因为项目启动时会自动部署flowable默认位置下的流程文件,所以会出现两个流程,这时候我们可以关闭自动部署。

可以根据你的需求加上以下配置:

flowable:# 关闭定时任务async-executor-activate: true# 将databaseSchemaUpdate设置为true。如果Flowable发现数据库的结构与应用所需的结构不一致的时候,会自动帮你更新或者新增表或者表结构。database-schema-update: true# 项目启动时会自动部署默认位置下的流程文件,false表示不检查,true表示检查,默认为truecheck-process-definitions: false

也可以根据需求更改存放路径和后缀名:
flowable.process-definition-location-prefix:classpath*:/processes/
flowable.process-definition-location-suffixes: **.bpmn20.xml,**.bpmn,

3、Springboot删除所有流程

    @DisplayName("删除全部流程")@Testvoid deleteAllFlowable(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();// 删除所有流程定义repositoryService.createProcessDefinitionQuery().list().forEach(pd ->repositoryService.deleteDeployment(pd.getDeploymentId(), true));System.out.println("删除成功");}

4、Springboot根据 流程部署ID 查询 流程定义ID

注意:一个 流程部署ID 可以对应多个 流程定义ID

    @DisplayName("根据 流程部署ID 查询 流程定义ID ")@Testvoid selectProcessByDeployId(){String deployId = "dd77ca7c-554e-11ef-93dc-581122450312";//从上一个流程获取到的部署IDList<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery().deploymentId(deployId).list();for (ProcessDefinition processDefinition : list) {System.out.println("deployId对应的流程定义ID为:"+processDefinition.getId());}}

运行结果:

流程定义ID由流程定义的name和一串uuid组成。

5、Springboot启动(发起)流程

启动流程有很多种方法,主要使用的是两种:一种是根据 流程定义的ID,一种是根据流程定义的KEY(标识)

最好是使用 流程定义ID(随机生成),因为KEY就是流程定义的名字可能会重复(实际业务中注意新增流程的时候,如果选择KEY来查询流程,记得做唯一判断)

PS:前面关于部署和定义使用的是RepositoryService,接下来操作流程则使用RuntimeService

    @DisplayName("启动流程")@Testvoid startProcess(){// 前面关于部署和定义使用的是RepositoryService,接下来操作流程则使用RuntimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();// act_re_procdef(流程定义)表中的idString processId = "flowDemo:1:dd9eb36f-554e-11ef-93dc-581122450312";runtimeService.startProcessInstanceById(processId);//String processKey = "flowDemo";//runtimeService.startProcessInstanceByKey(processKey);System.out.println("启动流程成功");}

运行结果

启动流程后下面的表发生变化:

  • 流程实例表 (ACT_RU_EXECUTION)

    • 记录流程实例的当前状态和运行时信息。
    • 启动流程后,新增一条记录,记录新流程实例的信息。
  • 任务表 (ACT_RU_TASK)

    • 记录运行时任务的信息。
    • 如果启动流程后有用户任务,会在这个表中新增一条或多条任务记录。
  • 历史流程实例表 (ACT_HI_PROCINST)

    • 记录历史流程实例的信息。
    • 启动流程后,新增一条记录,用于记录历史流程实例的信息。
  • 历史任务表 (ACT_HI_TASKINST)

    • 记录历史任务的信息。
    • 如果启动流程后有用户任务,会在这个表中新增历史任务记录。
  • 历史活动实例表 (ACT_HI_ACTINST)

    • 记录历史活动实例的信息。
    • 启动流程后,每个活动节点(如任务、网关等)都会在这个表中新增一条记录。
  • 任务参与者表 (ACT_RU_IDENTITYLINK)

    • 记录任务的参与者信息。
    • 如果启动的流程涉及到任务分配,会在这个表中新增记录

6、Springboot查询任务

PS:涉及到任务则使用TaskService方法

6.1全部任务

    @DisplayName("全部任务查询")@Testvoid findAllTask(){List<Task> list = processEngine.getTaskService().createTaskQuery().list();for (Task task : list) {System.out.println("任务ID:"+task.getId()+"---任务名称:"+task.getName()+"---任务当前办理人:"+task.getAssignee());}}

运行结果:

6.2我的任务(代办任务)

    @DisplayName("我的(代办)任务查询")@Testvoid findMyTask(){//任务查询 通过TaskService来实现TaskService taskService = processEngine.getTaskService();List<Task> list = taskService.createTaskQuery().taskAssignee("cpw").list(); //流程设置的  用户任务的办理人--人事//List<Task> list = taskService.createTaskQuery().taskAssignee("zhuguan").list(); //流程设置的  用户任务的办理人--主管for (Task task : list) {System.out.println("任务ID:"+task.getId()+"---任务名称:"+task.getName()+"---任务当前办理人:"+task.getAssignee());}}

7、springboot审批任务

发起流程之后,会从开始节点流到人事审核节点

根据上面查询到的任务ID进行操作:

1、审批通过

    @DisplayName("任务审批通过")@Testvoid completeTask(){//任务相关操作通过TaskService来实现TaskService taskService = processEngine.getTaskService();String taskId = "df2f8b51-5559-11ef-8d43-581122450312";taskService.complete(taskId);System.out.println("审批通过");}

运行结果:

此时流程就会跑到:人事审核节点跑到了主管审核节点

验证:这时候我们查询一下主管的代办任务,就会发现任务跑到主管这里来了

    @DisplayName("我的(代办)任务查询")@Testvoid findMyTask(){//任务查询 通过TaskService来实现TaskService taskService = processEngine.getTaskService();//List<Task> list = taskService.createTaskQuery().taskAssignee("cpw").list(); //流程设置的  用户任务的办理人--人事List<Task> list = taskService.createTaskQuery().taskAssignee("zhuguan").list(); //流程设置的  用户任务的办理人--主管for (Task task : list) {System.out.println("任务ID:"+task.getId()+"---任务名称:"+task.getName()+"---任务当前办理人:"+task.getAssignee());}}

审批任务影响以下表:

ACT_RU_TASK

  • 操作: 删除任务记录。

  • 描述: 当任务完成后,任务记录会从该表中删除。这个表存储的是正在运行的任务。

ACT_RU_IDENTITYLINK

  • 操作: 删除相关任务的身份链接记录。

  • 描述: 当任务完成后,相关的用户和组的身份链接记录会从该表中删除。这个表存储的是任务与用户/组之间的关系,如任务的分配者、候选人和参与者。

ACT_HI_TASKINST

  • 操作: 插入或更新任务历史记录。

  • 描述: 当任务完成后,会在该表中插入一条新的历史任务实例记录,或者更新现有的任务实例记录,以反映任务的完成时间和状态。

ACT_HI_ACTINST

  • 操作: 插入或更新活动历史记录。

  • 描述: 当任务完成后,会在该表中插入一条新的历史活动实例记录,或者更新现有的活动实例记录,以反映任务的完成。

ACT_HI_IDENTITYLINK

  • 操作: 插入或更新身份链接历史记录。

  • 描述: 当任务完成后,与任务相关的身份链接信息会在该表中插入新的历史记录或者更新现有的记录。

-----------------------------------------------------------------------------------------------------------------------

主管再次审批,则就到了结束节点即任务完成,act_ru表(流程运行实例表)相关的记录就会被完善

PS:注意在人事审核节点的时候任务审批通过之后,将会生成新的任务ID流向主管审核

2、驳回

我们再部署第二个流程来进行驳回操作,接下来重复简单讲解(因为上面的已经说完了)

部署流程:

查询流程:

发起流程:

查询我的任务:

审核任务:

好了,终于又回到主管审核节点~  重头戏来了~

驳回:

根据业务驳回可以是驳回到上一个节点,或者是驳回到起点重新开始。

这里讲一下驳回到起点重新开始。

1、在查询任务的时候,我们加上查询当前任务的流程实例ID

    @DisplayName("我的(代办)任务查询")@Testvoid findMyTask(){//任务查询 通过TaskService来实现TaskService taskService = processEngine.getTaskService();//List<Task> list = taskService.createTaskQuery().taskAssignee("cpw").list(); //流程设置的  用户任务的办理人--人事List<Task> list = taskService.createTaskQuery().taskAssignee("zhuguan").list(); //流程设置的  用户任务的办理人--主管for (Task task : list) {System.out.println("任务ID:"+task.getId()+"---任务名称:"+task.getName()+"---任务当前办理人:"+task.getAssignee()+"---任务的流程实例ID:"+task.getProcessInstanceId());}}

2、根据实例ID获取到流程实例,然后根据流程实例获取到流程定义,然后取消当前流程实例,重新启动新的流程实例 (驳回流程)

以下是运行的过程的参数变化:

运行结果:

验证:看看流程是否从 主管审核 退回到起点 人事审核 

ok兄弟们,驳回成功

    @DisplayName("任务驳回")@Testvoid rejectTask(){String processInstanceId = "9cd07051-555d-11ef-ba69-581122450312";RuntimeService runtimeService = processEngine.getRuntimeService();RepositoryService repositoryService = processEngine.getRepositoryService();// 获取当前流程实例ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();System.out.println("获取当前流程实例:"+processInstance);// 获取流程定义ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();System.out.println("获取当前流程定义:"+processDefinition);// 取消当前流程实例runtimeService.deleteProcessInstance(processInstanceId, "驳回流程");System.out.println("取消流程实例ID:"+processInstanceId);// 启动新的流程实例runtimeService.startProcessInstanceById(processDefinition.getId());System.out.println("流程ID:"+processDefinition.getId()+"启动成功!!!");}

8、Springboot流程状态管理

重要的事情说三遍:是先有 流程定义 才会有 流程实例 才会有  流程任务

PS:操作流程使用RepositoryService方法

1、流程定义

查询所有的流程定义

    @DisplayName("查询流程定义状态")@Testvoid selectProcessDefinition(){List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery().list();for (ProcessDefinition processDefinition : list) {//流程定义是否挂起 false为否(fasle表示该流程定义的状态为:激活)  true为是(true表示该流程定义的状态为:挂起)System.out.println("流程定义的ID:"+processDefinition.getId()+"---流程定义的Name:"+processDefinition.getName()+"---该流程定义是否挂起:"+processDefinition.isSuspended());}}

运行结果:

processDefinition.isSuspended()查询流程定义是否挂起 
false为否(fasle表示该流程定义的状态为:激活)  
true为是(true表示该流程定义的状态为:挂起)

由此可以判断这两个《流程定义》都是激活状态

1、挂起《流程定义》

当一个流程定义被挂起时,新的流程实例将不能基于该流程定义启动,但已经运行的流程实例不受影响。

挂起流程定义主要有两种方法,一种是通过id 另一种是通过key,这里使用id来演示

    @DisplayName("挂起流程定义")@Testvoid stopProcessDefinition(){String processDefinitionId = "flowDemo2:1:82ce3927-555c-11ef-859f-581122450312";processEngine.getRepositoryService().suspendProcessDefinitionById(processDefinitionId);System.out.println("流程定义ID为:"+processDefinitionId+"挂起成功!");}

运行结果:

检验:

第一种检验方法:

第二种方法:

当流程定义被挂起时,我们来测试一下新的流程实例能不能启动?

2、激活《流程定义》

当一个挂起的流程定义被激活时,新的流程实例可以基于该流程定义启动。

跟挂起流程定义同理,激活流程定义也是主要通过两种方法来激活(ID,KEY)

我们继续使用ID来激活:

    @DisplayName("激活流程定义")@Testvoid startProcessDefinition(){String processDefinitionId = "flowDemo2:1:82ce3927-555c-11ef-859f-581122450312";processEngine.getRepositoryService().activateProcessDefinitionById(processDefinitionId);System.out.println("流程定义ID为:"+processDefinitionId+"激活成功!");}

运行结果:

检验:

好了,我好兄弟又激活回来了,我们来看看能否发起新的流程实例?

成功!

2、流程实例

操作流程实例使用RuntimeService方法

查询所有在运行的流程实例:

    @DisplayName("查询流程实例状态")@Testvoid selectProcessInstance(){List<ProcessInstance> list = processEngine.getRuntimeService().createProcessInstanceQuery().list();for (ProcessInstance processInstance : list) {//processDefinition.isSuspended()查询流程定义是否挂起 false为否(fasle表示该流程定义的状态为:激活)  true为是(true表示该流程定义的状态为:挂起)System.out.println("流程实例的ID:"+processInstance.getId()+"---流程实例的Name:"+processInstance.getName()+"---该流程实例是否挂起:"+processInstance.isSuspended());}}

运行结果:

1、挂起《流程实例》

当一个流程实例被挂起时,该实例中的任务将不能被执行,不能继续进行下一步的操作。

    @DisplayName("挂起流程实例")@Testvoid stopProcessInstance(){String processInstanceId = "93012f42-5569-11ef-bb69-581122450312";processEngine.getRuntimeService().suspendProcessInstanceById(processInstanceId);System.out.println("流程实例ID为:"+processInstanceId+"挂起成功!");}

检验:

找到该挂起的流程实例下的用户任务,看看能否作业?

2、激活《流程实例》

当一个挂起的流程实例被激活时,该实例可以继续执行,进行下一步的操作。

    @DisplayName("激活流程实例")@Testvoid startProcessInstance(){String processInstanceId = "93012f42-5569-11ef-bb69-581122450312";processEngine.getRuntimeService().activateProcessInstanceById(processInstanceId);System.out.println("流程实例ID为:"+processInstanceId+"激活成功!");}

运行结果:

检验:

那兄弟们再执行一下该流程实例的任务看看

OKOK 审批通过!!

完结撒花~~~~

----------------------------------------------------------------------------------------------------------------------------

9、资源

1.单元测试代码

附上全部测试代码:


@SpringBootTest
@DisplayName("流程测试")
public class UnitTest {//第一种方法使用ProcessEngine@Resourceprivate ProcessEngine processEngine;//第二种方法使用若干个 ***Service//@Autowired//private RuntimeService runtimeService;//@Autowired//private RepositoryService repositoryServiceService;@DisplayName("部署流程")@Testvoid deployFlow(){Deployment deploy = processEngine.getRepositoryService().createDeployment() //创建部署对象.addClasspathResource("processes/flowDemo2.bpmn20.xml") // 默认是在resources/processes下寻找,当然你可以自定义目录.name("第二个Flowable案例") //设置流程的名字.deploy(); //deploy部署流程System.out.println("流程部署ID为:"+deploy.getId()); //获取到当前流程的ID}@DisplayName("根据 流程部署ID 查询 流程定义ID ")@Testvoid selectProcessByDeployId(){String deployId = "82aa5d74-555c-11ef-859f-581122450312";//从上一个流程获取到的部署IDList<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery().deploymentId(deployId).list();for (ProcessDefinition processDefinition : list) {System.out.println("deployId对应的流程定义ID为:"+processDefinition.getId());}}@DisplayName("启动流程")@Testvoid startProcess(){// 前面关于部署和定义使用的是RepositoryService,接下来操作流程则使用RuntimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();// act_re_procdef(流程定义)表中的idString processId = "flowDemo2:1:82ce3927-555c-11ef-859f-581122450312";runtimeService.startProcessInstanceById(processId);//String processKey = "flowDemo";//runtimeService.startProcessInstanceByKey(processKey);System.out.println("启动流程成功");}@DisplayName("全部任务查询")@Testvoid findAllTask(){List<Task> list = processEngine.getTaskService().createTaskQuery().list();for (Task task : list) {System.out.println("任务ID:"+task.getId()+"---任务名称:"+task.getName()+"---任务办理人:"+task.getAssignee());}}@DisplayName("我的(代办)任务查询")@Testvoid findMyTask(){//任务查询 通过TaskService来实现TaskService taskService = processEngine.getTaskService();List<Task> list = taskService.createTaskQuery().taskAssignee("cpw").list(); //流程设置的  用户任务的办理人--人事//List<Task> list = taskService.createTaskQuery().taskAssignee("zhuguan").list(); //流程设置的  用户任务的办理人--主管for (Task task : list) {System.out.println("任务ID:"+task.getId()+"---任务名称:"+task.getName()+"---任务当前办理人:"+task.getAssignee()+"---任务的流程实例ID:"+task.getProcessInstanceId());}}@DisplayName("任务审批通过")@Testvoid completeTask(){//任务相关操作通过TaskService来实现TaskService taskService = processEngine.getTaskService();String taskId = "93043c87-5569-11ef-bb69-581122450312";taskService.complete(taskId);System.out.println("审批通过");}@DisplayName("任务驳回")@Testvoid rejectTask(){String processInstanceId = "9cd07051-555d-11ef-ba69-581122450312";RuntimeService runtimeService = processEngine.getRuntimeService();RepositoryService repositoryService = processEngine.getRepositoryService();// 获取当前流程实例ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();System.out.println("获取当前流程实例:"+processInstance);// 获取流程定义ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();System.out.println("获取当前流程定义:"+processDefinition);// 取消当前流程实例runtimeService.deleteProcessInstance(processInstanceId, "驳回流程");System.out.println("取消流程实例ID:"+processInstanceId);// 启动新的流程实例runtimeService.startProcessInstanceById(processDefinition.getId());System.out.println("流程ID:"+processDefinition.getId()+"启动成功!!!");}@DisplayName("查询流程定义状态")@Testvoid selectProcessDefinition(){List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery().list();for (ProcessDefinition processDefinition : list) {//processDefinition.isSuspended()查询流程定义是否挂起 false为否(fasle表示该流程定义的状态为:激活)  true为是(true表示该流程定义的状态为:挂起)System.out.println("流程定义的ID:"+processDefinition.getId()+"---流程定义的Name:"+processDefinition.getName()+"---该流程定义是否挂起:"+processDefinition.isSuspended());}}@DisplayName("挂起流程定义")@Testvoid stopProcessDefinition(){String processDefinitionId = "flowDemo2:1:82ce3927-555c-11ef-859f-581122450312";processEngine.getRepositoryService().suspendProcessDefinitionById(processDefinitionId);System.out.println("流程定义ID为:"+processDefinitionId+"挂起成功!");}@DisplayName("激活流程定义")@Testvoid startProcessDefinition(){String processDefinitionId = "flowDemo2:1:82ce3927-555c-11ef-859f-581122450312";processEngine.getRepositoryService().activateProcessDefinitionById(processDefinitionId);System.out.println("流程定义ID为:"+processDefinitionId+"激活成功!");}@DisplayName("查询流程实例状态")@Testvoid selectProcessInstance(){List<ProcessInstance> list = processEngine.getRuntimeService().createProcessInstanceQuery().list();for (ProcessInstance processInstance : list) {//processDefinition.isSuspended()查询流程定义是否挂起 false为否(fasle表示该流程定义的状态为:激活)  true为是(true表示该流程定义的状态为:挂起)System.out.println("流程实例的ID:"+processInstance.getId()+"---流程实例的Name:"+processInstance.getName()+"---该流程实例是否挂起:"+processInstance.isSuspended());}}@DisplayName("挂起流程实例")@Testvoid stopProcessInstance(){String processInstanceId = "93012f42-5569-11ef-bb69-581122450312";processEngine.getRuntimeService().suspendProcessInstanceById(processInstanceId);System.out.println("流程实例ID为:"+processInstanceId+"挂起成功!");}@DisplayName("激活流程实例")@Testvoid startProcessInstance(){String processInstanceId = "93012f42-5569-11ef-bb69-581122450312";processEngine.getRuntimeService().activateProcessInstanceById(processInstanceId);System.out.println("流程实例ID为:"+processInstanceId+"激活成功!");}@DisplayName("删除全部流程")@Testvoid deleteAllFlowable(){ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = processEngine.getRepositoryService();// 删除所有流程定义repositoryService.createProcessDefinitionQuery().list().forEach(pd ->repositoryService.deleteDeployment(pd.getDeploymentId(), true));System.out.println("删除成功");}}

2.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: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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef"><process id="flowDemo" name="flowDemo" isExecutable="true"><startEvent id="sid-bb849ec0-1482-4057-a447-c8d68adc9ca2" name="开始"/><userTask id="sid-c30c0960-a986-4cd6-80e2-bae02d6af707" name="人事审核" flowable:assignee="cpw"></userTask><userTask id="sid-fc70937d-9773-4db8-acb3-a3af3e6ccb39" name="主管审核" flowable:assignee="zhuguan"/><endEvent id="sid-712aab8a-a060-4363-b3eb-cd3fa9215808"/><sequenceFlow id="sid-2c879163-8816-4dd7-89bb-bf1a4485fef4" sourceRef="sid-bb849ec0-1482-4057-a447-c8d68adc9ca2" targetRef="sid-c30c0960-a986-4cd6-80e2-bae02d6af707"/><sequenceFlow id="sid-2fca88ff-d597-430c-a5e9-edfefbdd2569" sourceRef="sid-c30c0960-a986-4cd6-80e2-bae02d6af707" targetRef="sid-fc70937d-9773-4db8-acb3-a3af3e6ccb39"/><sequenceFlow id="sid-e8b6c848-1c54-4fdb-a8b0-e085d715c906" sourceRef="sid-fc70937d-9773-4db8-acb3-a3af3e6ccb39" targetRef="sid-712aab8a-a060-4363-b3eb-cd3fa9215808"/></process><bpmndi:BPMNDiagram id="BPMNDiagram_flowDemo"><bpmndi:BPMNPlane bpmnElement="flowDemo2" id="BPMNPlane_flowDemo"><bpmndi:BPMNShape id="shape-d460f24b-1aac-4028-b625-929601acd3c0" bpmnElement="sid-bb849ec0-1482-4057-a447-c8d68adc9ca2"><omgdc:Bounds x="-375.0" y="-37.25" width="30.0" height="30.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape id="shape-ad3ec780-dd25-42f1-8e53-6ed0608d5b91" bpmnElement="sid-c30c0960-a986-4cd6-80e2-bae02d6af707"><omgdc:Bounds x="-282.75" y="-62.25" width="100.0" height="80.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape id="shape-2a1947d2-0365-4dd8-8083-9bdaa7bea300" bpmnElement="sid-fc70937d-9773-4db8-acb3-a3af3e6ccb39"><omgdc:Bounds x="-133.5509" y="-62.9491" width="100.0" height="80.0"/></bpmndi:BPMNShape><bpmndi:BPMNShape id="shape-c748377a-bdcd-4892-b001-3621cf05589a" bpmnElement="sid-712aab8a-a060-4363-b3eb-cd3fa9215808"><omgdc:Bounds x="15.625" y="-37.25" width="30.0" height="30.0"/></bpmndi:BPMNShape><bpmndi:BPMNEdge id="edge-a51efb51-2d88-4eae-9ffe-baa2e50cd0e5" bpmnElement="sid-2c879163-8816-4dd7-89bb-bf1a4485fef4"><omgdi:waypoint x="-345.0" y="-22.25"/><omgdi:waypoint x="-282.75" y="-22.25"/></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="edge-69253e56-2532-4829-b515-d27caeeb275a" bpmnElement="sid-2fca88ff-d597-430c-a5e9-edfefbdd2569"><omgdi:waypoint x="-182.75" y="-22.25"/><omgdi:waypoint x="-133.5509" y="-22.9491"/></bpmndi:BPMNEdge><bpmndi:BPMNEdge id="edge-86a73120-1957-453e-b988-7f2ede9f75dc" bpmnElement="sid-e8b6c848-1c54-4fdb-a8b0-e085d715c906"><omgdi:waypoint x="-33.550903" y="-22.9491"/><omgdi:waypoint x="-10.011603" y="-22.25"/><omgdi:waypoint x="15.625" y="-22.25"/></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/400589.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM知识总结(性能调优)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 性能调优 何时进行JVM调优&#xff1f; 遇到以下情况&#xff0c…

傻瓜式一步到位Mysql 8.0 密码修改

5.7之前修改密码语句 update user set authentication_string password(“root”) where user “root”; mysql 5.7.9以后废弃了password字段和password()函数&#xff1b;并在user表加了authentication_string:字段表示用户密码 #进入到mysql 安装目录下 #停止 mysql 服务 …

怎么调试python脚本

打开pycharm community 2019.1软件&#xff0c;创建一个项目。 创建一个py后缀的文件作为示范&#xff0c;文件名自己定义。 编写代码&#xff0c;然后右键点击进行运行&#xff0c;查看一下是否有问题。 点击右上角的虫子图标&#xff0c;然后下面会有控制面板出来&#xff0c…

基于C11的简单log,支持C++的‘<<’风格和C的‘可变参数’风格

基于C11的简单log&#xff0c;支持C的‘<<’风格和C的‘可变参数’风格 日志仅由richlog.h单个文件实现功能&#xff0c;软件集成简单。 支持C的std::cout的<<风格的日志打印&#xff0c;也支持C的printf风格的日志打印 日志多线程安全&#xff0c;采用C11 mute…

SpringBoot整合日志功能(slf4j+logback)详解

目录 一、日志门面与日志实现 1.1 什么是日志门面和日志实现&#xff1f; 1.2 为什么需要日志门面&#xff1f; 二、简介 三、日志格式 四、记录日志 4.1 使用日志工厂 4.2 使用Lombok的Slf4j注解 五、日志级别 5.1 日志级别介绍 5.2 配置日志级别 5.3 指定某个包下…

分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost

分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost 文章目录 前言分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost 一、PSO-KELM-Adaboost模型1. 核化极限学习机 (KELM)2. 粒子…

数据库原理面试-核心概念-问题理解

目录 1.数据库、数据库系统与数据库管理系统 2.理解数据独立性 3.数据模型 4.模式、外模式和内模式 5.关系和关系数据库 6.主键与外键 7.SQL语言 8.索引与视图 9.数据库安全 10.数据库完整性 11.数据依赖和函数依赖 12.范式&#xff1f;三范式&#xff1f;为什么要遵…

用栈访问最后若干元素——682、71、388

682. 棒球比赛&#xff08;简单&#xff09; 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的。你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[…

【redis的大key问题】

在使用 Redis 的过程中&#xff0c;如果未能及时发现并处理 Big keys&#xff08;下文称为“大Key”&#xff09;&#xff0c;可能会导致服务性能下降、用户体验变差&#xff0c;甚至引发大面积故障。 本文将介绍大Key产生的原因、其可能引发的问题及如何快速找出大Key并将其优…

基于llama.cpp实现Llama3模型的guff格式转换、4bit量化以及GPU推理加速(海光DCU)

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 序言 本文使用llama.cpp框架&#xff0c;对 Llama3-8B-Instruct 模型进行gguf格式转换&#xff0c;8bit量化&#xff0c;并在CPU和GPU上对8bit模型进行推理。 测试…

基于SpringBoot的企业资产管理系统

TOC springboot117基于SpringBoot的企业资产管理系统 系统概述 1.1 研究背景 智慧养老是面向居家老人、社区及养老机构的传感网系统与信息平台&#xff0c;并在此基础上提供实时、快捷、高效、低成本的&#xff0c;物联化、互联化、智能化的养老服务。 随着科技进步&#…

mysql中log

目录 MySQL 日志系统概述 日志类型 日志的作用和重要性 Mermaid图示 1. Undo Log 和 Redo Log 的协同工作图 2. Redo Log 确保持久性的流程图 Undo Log&#xff08;回滚日志&#xff09; 事务的原子性&#xff08;Atomicity&#xff09;保障 事务回滚机制 MVCC&#…

【二叉树进阶】--- 二叉搜索树转双向链表 最近公共祖先

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 数据结构 本篇博客我们继续了解一些二叉树的进阶算法。 &#x1f3e0; 二叉搜索 树转化为双向循环链表 &#x1f4cc; 题目内容 将二叉搜索树转化为排序…

失败:Windows--WSL2--Ubuntuon--Docker

编写目的&#xff1a; 在Windows上安装Docker&#xff0c;用Docker安装Gitlab、Jenkins等软件。 文章记录一下Windows上安装Docker的过程。 参考文档&#xff1a; 旧版 WSL 的手动安装步骤 | Microsoft Learn 下面用"参考文档"代替 目录 第一步&#xff1a;启…

SAP与网易大数据系统集成案例

一、项目环境 江西某药业有限公司是一家以医药产业为主营、资本经营为平台的大型民营企业集团。公司成立迄今&#xff0c;企业经营一直呈现稳健、快速发展的态势集团总销售额超40亿元。 为了帮助企业更有效的进行分配和管理&#xff0c;包括人力、物资、时间和预算等资源&a…

UVa1660/LA3031 Cable TV Network

UVa1660/LA3031 Cable TV Network 题目链接题意分析AC 代码 题目链接 本题是2004年icpc欧洲区域赛东南欧赛区的题目 题意 给定一个n&#xff08;n≤50&#xff09;个点的无向图&#xff0c;求它的点连通度&#xff0c;即最少删除多少个点&#xff0c;使得图不连通。如下图所示…

C语言----约瑟夫环

约瑟夫环 实例说明&#xff1a; 本实例使用循环链表实现约瑟夫环。给定一组编号分别是4、7、5、9、3、2、6、1、8。报数初始值由用户输入&#xff0c;这里输入4&#xff0c;如图12.18所示&#xff0c;按照约瑟夫环原理打印输出队列。 实现过程&#xff1a; (1)在 VC6.0中创建…

GlobalMapper软件安装流程

目录 一、环境准备 二、安装步骤 三、软件激活 一、环境准备 系统&#xff1a;win7操作系统 安装包下载&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1Vb4VVRFBRYawt3MT-5gYOw 提取码&#xff1a;sxdj 二、安装步骤 1、解压&#xff0c;右键global-mapper-23_1-x…

Redis的简单介绍

一、Redis简介 1.NOSQL NoSQL( Not Only SQL)&#xff0c;意即“不仅仅是SQL”&#xff0c;泛指非关系型的数据库。随着互联网web2.0网站的兴起&#xff0c;传统的关系数据库在应付web2.0网站&#xff0c;纯动态网站已经显得力不从心&#xff0c;暴露了很多难以克服的问题&am…

java学习19VUE

VUE NPM npm的全称是Node Package Manager 中文名为Node.js包管理器&#xff0c;是一个NodeJS包管理和分发工具&#xff0c;已经成为了非官方的发布Node模块(包)的标准。NPM可以方便地从一个全球的代码库中获取并安装Node.js模块&#xff0c;这些模块可以用于构建应用程序、…