flowable工作流的使用

flowable工作流的使用,第1张

文章目录
  • 一、认识Flowable
    • 1.1 flowable工作流所有业务概念
      • 1.1.1 类结构
    • 1.2 BPMN各个符号讲解
      • 1.2.1 开始节点 - 流程的开始处
      • 1.2.2 任务节点
      • 1.2.3 网关组件
        • 1.2.3.1 互斥/排他网关:
        • 1.2.3.2 并行网:
        • 1.2.3.3 包容网关:
        • 1.2.3.4 例子
    • 1.3 通用业务流程
      • 1.3.1 编辑流程
        • 1.3.1.1 自定义表单
        • 1.3.1.2 编辑流程模型
        • 1.3.1.3 部署成流程定义
      • 1.3.2 执行审批
        • 1.3.2.1 功能列表
        • 1.3.2.2 功能解释
      • 1.3.3 查询流程实例和任务
    • 1.4 表和api说明
      • 1.4.1 表说明
      • 1.4.2 api说明
        • 1.4.2.1 FormService
        • 1.4.2.2 RepositiryService
        • 1.4.2.3 RuntimeService
        • 1.4.2.4 HistoryService
        • 1.4.2.5 TaskService
        • 1.4.2.6 ManagementService
        • 1.4.2.7 IdentityService
    • 1.5 异常策略
    • 1.6 各种任务讲解
  • 二、springboot整合flowable
    • 2.1第一步:pom依赖
    • 2.2第二步:yml的配置
    • 2.3第三步:启动启动类
  • 三、flowable-ui可视化bpmn的生成工具
    • 3.1 参考网址:
    • 3.2 工具下载安装:
    • 3.3 使用
  • 四、代码
    • 4.1 api说明-同上
      • 4.1.1 FormService
      • 4.1.2 RepositiryService
      • 4.1.3 RuntimeService
      • 4.1.4 HistoryService
      • 4.1.5 TaskService
      • 4.1.6 ManagementService
      • 4.1.7 IdentityService
      • 4.1.8 DynamicBpmnService
    • 4.2 流程 *** 作讲解
      • 4.2.1 流程部署
      • 4.2.2 流程启动
      • 4.2.3 查看任务(流程实例需要的审核人, *** 作人)
      • 4.2.4 完成任务
      • 4.2.5 JavaDelegate - 实现申请通过后执行的自动逻辑
      • 4.2.6 使用历史数据
      • 4.2.7 结束流程
      • 4.2.8 删除流程
    • 4.3 案例
      • 4.3.1 简单案例
      • 4.3.2 进阶案例

一、认识Flowable

官网
中文文档
源码

1.1 flowable工作流所有业务概念
  • 工作流审批:审批流程管理;
  • Flowable使用了BPMN的技术(业务模型和符号),如下图:
1.1.1 类结构

总入口点是ProcessEngine;使用ProcessEngine,可以获得各种提供工作流/BPM方法的服务。ProcessEngine与服务对象都是线程安全的,因此可以在服务器中保存并共用同一个引用。

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); // spring的项目可以直接导入pom依赖,然后@Autowired导入使用

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();


1.2 BPMN各个符号讲解 1.2.1 开始节点 - 流程的开始处 1.2.2 任务节点
其中包含了多种任务,如图。其中最常用的就是用户任务。指定审批人都需要此选项;
![在这里插入图片描述](http://www.kaotop.com/file/tupian/20220514/4648e3ea9a46470393dc7ad8572e1bae.png)
1.2.3 网关组件

网关相当于判断(与或非),最长用的三种网关分别是 互斥/排他网关、并行网关、包容网关

1.2.3.1 互斥/排他网关:

相当于判断,举例:如果输入值大于20走A节点,小20走B节点


1.2.3.2 并行网:

与相容网关成对出现,表示网关中的人全部同意才能进入下一节点

它可以将执行分支(fork)为多条路径,也可以合并(join)多条入口路径的执行

1.2.3.3 包容网关:

互斥网关与并行网关的结合体,如果满足A,B都互斥条件,则都需要流转,如果只有一个满足,那么久只流转满足条件的

包容网关与排他网关一样,可以在包容网关的出口顺序流上定义条件,包容网关会计算条件。然而主要的区别是,包容网关与并行网关一样,可以同时选择多于一条出口顺序流。


1.2.3.4 例子


说明:
1.当审批申请人提交完成后进入审批阶段
2.两位项目经理进行审批,需要两人都同意进入下一节点
3.经理进行审批,此处业务为经理职位(mamage)的人都可以执行审批。(此处有认领业务此处不描述)
4.总经理/董事长审批,如果大于20天需要董事长审批,如果小于20天总经理审批。

1.3 通用业务流程

标准的审批流系统都有一套标准化的业务流程下文,介绍如何 *** 作审批流系统。

一般在系统中的模块名如下, 请个字对应。
这里的任务管理可以查看到一个流程每个审批节点的具体信息。

1.3.1 编辑流程 1.3.1.1 自定义表单

在申请人进行审批时,需要填写申请的项目和申请数据。如请假审批需要填写请假时间和原因。所以这个表单我们希望可以定制

1.3.1.2 编辑流程模型

也就是使用BPMN绘制流程图,在图中会指定该审批流程的表单,下一审批节点人员与进入流程的流转条件。
当然也可以导入流程图。同时可以指定申请人在申请时需要填写的表单(审批人如果需要添加审批表单也可以在此处配置)

1.3.1.3 部署成流程定义

流程模型在编辑/导入后,并不会生效。之后发布生产流程定义后才能够使用并发起审批。当然流程定义模块还可以有导出激活等功能。

1.3.2 执行审批 1.3.2.1 功能列表

当设计完流程之后,就可以发起审批和进行审批了,用户拥有以下功能。

1.3.2.2 功能解释

驳回:将审批重置发送给某节点,重新审批
转办:A转给其B审批,B审批后,进入下一节点
委派:A转给B审批,B审批后转给A,A审批后进入下一节点

1.3.3 查询流程实例和任务

根据上图可见,当发起审批后,就会生产流程实例了。流程实例和任务管理就可以查看到已发起的审批了

  • 每一套审批信息生产一条流程实例信息
  • 一条流程实例有多个审批节点(流程图中已画),每一个审批节点是一条任务管理信息。
  • 请注意流程实例和流程定义的概念
流程定义(process definition):创建BPMN,定义了流程的各个步骤(流程定义是BPMN 2.0流程对应的Java对象)
流程实例(process instance):就是申请某个流程
一个流程定义可以启动多个流程实例
1.4 表和api说明

flowable为我们提供了47张表和7个常用api

1.4.1 表说明
表分类表名表说明
一般数据(2)ACT_GE_BYTEARRAY通用的流程定义和流程资源
ACT_GE_PROPERTY系统相关属性
流程历史记录(8)ACT_HI_ACTINST历史的流程实例
ACT_HI_ATTACHMENT历史的流程附件
ACT_HI_COMMENT历史的说明性信息
ACT_HI_DETAIL历史的流程运行中的细节信息
ACT_HI_IDENTITYLINK历史的流程运行过程中用户关系
ACT_HI_PROCINST历史的流程实例
ACT_HI_TASKINST历史的任务实例
ACT_HI_VARINST历史的流程运行中的变量信息
用户用户组表(9)ACT_ID_BYTEARRAY二进制数据表
ACT_ID_GROUP用户组信息表
ACT_ID_INFO用户信息详情表
ACT_ID_MEMBERSHIP人与组关系表
ACT_ID_PRIV权限表
ACT_ID_PRIV_MAPPING用户或组权限关系表
ACT_ID_PROPERTY属性表
ACT_ID_TOKEN系统登录日志表
ACT_ID_USER用户表
流程定义表(3)ACT_RE_DEPLOYMENT部署单元信息
ACT_RE_MODEL模型信息
ACT_RE_PROCDEF已部署的流程定义
运行实例表(10)ACT_RU_DEADLETTER_JOB正在运行的任务表
ACT_RU_EVENT_SUBSCR运行时事件
ACT_RU_EXECUTION运行时流程执行实例
ACT_RU_HISTORY_JOB历史作业表
ACT_RU_IDENTITYLINK运行时用户关系信息
ACT_RU_JOB运行时作业表
ACT_RU_SUSPENDED_JOB暂停作业表
ACT_RU_TASK运行时任务表
ACT_RU_TIMER_JOB定时作业表
ACT_RU_VARIABLE运行时变量表
其他表(2)ACT_EVT_LOG事件日志表
ACT_PROCDEF_INFO流程定义信息

每个变量存储为ACT_RU_VARIABLE数据库表的一行



1.4.2 api说明 1.4.2.1 FormService

表单数据的管理

formService.getStartFormKey() // 获取表单key
formService.getRenderedStartForm()  // 查询表单json(无数据)
1.4.2.2 RepositiryService

提供了在编辑和发布审批流程的api。主要是模型管理和流程定义的业务api
这个服务提供了管理与控制部署(deployments)与流程定义(process definitions)的 *** 作

  • 查询引擎现有的部署与流程定义。
  • 暂停或激活部署中的某些流程,或整个部署。暂停意味着不能再对它进行 *** 作,激活刚好相反,重新使它可以 *** 作。
  • 获取各种资源,比如部署中保存的文件,或者引擎自动生成的流程图。
  • 获取POJO版本的流程定义。它可以用Java而不是XML的方式查看流程。
1.提供了带条件的查询模型流程定义的api
repositoryService.createXXXQuery()
例如:
repositoryService.createModelQuery().list() 模型查询 
repositoryService.createProcessDefinitionQuery().list() 流程定义查询

repositoryService.createXXXXQuery().XXXKey(XXX) (查询该key是否存在)

2.提供一大波模型与流程定义的通用方法
模型相关
repositoryService.getModel()  (获取模型)
repositoryService.saveModel()  (保存模型)
repositoryService.deleteModel() (删除模型)
repositoryService.createDeployment().deploy(); (部署模型)
repositoryService.getModelEditorSource()  (获得模型JSON数据的UTF8字符串)
repositoryService.getModelEditorSourceExtra()  (获取PNG格式图像)

3.流程定义相关
repositoryService.getProcessDefinition(ProcessDefinitionId);  获取流程定义具体信息
repositoryService.activateProcessDefinitionById() 激活流程定义
repositoryService.suspendProcessDefinitionById()  挂起流程定义
repositoryService.deleteDeployment()  删除流程定义
repositoryService.getProcessDiagram()获取流程定义图片流
repositoryService.getResourceAsStream()获取流程定义xml流
repositoryService.getBpmnModel(pde.getId()) 获取bpmn对象(当前进行到的那个节点的流程图使用)

4.流程定义授权相关
repositoryService.getIdentityLinksForProcessDefinition() 流程定义授权列表
repositoryService.addCandidateStarterGroup()新增组流程授权
repositoryService.addCandidateStarterUser()新增用户流程授权
repositoryService.deleteCandidateStarterGroup() 删除组流程授权
repositoryService.deleteCandidateStarterUser()  删除用户流程授权

1.4.2.3 RuntimeService

处理正在运行(已部署)的流程

runtimeService.createProcessInstanceBuilder().start() 发起流程
runtimeService.deleteProcessInstance() 删除正在运行的流程
runtimeService.suspendProcessInstanceById() 挂起流程定义
runtimeService.activateProcessInstanceById() 激活流程实例
runtimeService.getVariables(processInstanceId); 获取表单中填写的值
runtimeService.getActiveActivityIds(processInstanceId)获取以进行的流程图节点 (当前进行到的那个节点的流程图使用)

runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState(); 终止流程


1.4.2.4 HistoryService

在用户发起审批后,会生成流程实例。historyService为处理流程实例的api,但是其中包括了已完成的和未完成的流程实例;
如果是处理正在运行的流程实例,请使用runtimeService;

historyService.createHistoricProcessInstanceQuery().list() 查询流程实例列表(历史流程,包括未完成的)
historyService.createHistoricProcessInstanceQuery().list().foreach().getValue() 可以获取历史中表单的信息
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); 根绝id查询流程实例
historyService.deleteHistoricProcessInstance() 删除历史流程
historyService.deleteHistoricTaskInstance(taskid); 删除任务实例
historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list()  流程实例节点列表 (当前进行到的那个节点的流程图使用)

1.4.2.5 TaskService

对流程实例的各个节点的审批处理

流转的节点审批
taskService.createTaskQuery().list() 待办任务列表
taskService.createTaskQuery().taskId(taskId).singleResult();  待办任务详情
taskService.saveTask(task); 修改任务
taskService.setAssignee() 设置审批人
taskService.addComment() 设置审批备注
taskService.complete() 完成当前审批
taskService.getProcessInstanceComments(processInstanceId); 查看任务详情(也就是都经过哪些人的审批,意见是什么)
taskService.delegateTask(taskId, delegater); 委派任务
taskService.claim(taskId, userId);认领任务
taskService.unclaim(taskId); 取消认领
taskService.complete(taskId, completeVariables); 完成任务

任务授权
taskService.addGroupIdentityLink()新增组任务授权
taskService.addUserIdentityLink() 新增人员任务授权
taskService.deleteGroupIdentityLink() 删除组任务授权
taskService.deleteUserIdentityLink() 删除人员任务授权

1.4.2.6 ManagementService

主要是执行自定义命令

managementService.executeCommand(new classA())  执行classA的内部方法 

在自定义的方法中可以使用以下方法获取repositoryService

ProcessEngineConfiguration processEngineConfiguration =
            CommandContextUtil.getProcessEngineConfiguration(commandContext);
RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();

也可以获得流程定义方法集合

ProcessEngineConfigurationImpl processEngineConfiguration =
            CommandContextUtil.getProcessEngineConfiguration(commandContext);
        ProcessDefinitionEntityManager processDefinitionEntityManager =
            processEngineConfiguration.getProcessDefinitionEntityManager();
如findById/findLatestProcessDefinitionByKey/findLatestProcessDefinitionByKeyAndTenantId等。

1.4.2.7 IdentityService

用于身份信息获取和保存,这里主要是获取身份信息

identityService.createUserQuery().userId(userId).singleResult();  获取审批用户的具体信息
identityService.createGroupQuery().groupId(groupId).singleResult(); 获取审批组的具体信息

1.5 异常策略

Flowable的异常基类是org.flowable.engine.FlowableException,这是一个非受检异常(unchecked exception)。在任何API *** 作时都可能会抛出这个异常,javadoc提供了每个方法可能抛出的异常。例如,从TaskService中摘录:

  • FlowableWrongDbException: 当Flowable引擎检测到数据库表结构版本与引擎版本不匹配时抛出。
  • FlowableOptimisticLockingException: 当对同一数据实体的并发访问导致数据存储发生乐观锁异常时抛出。
  • FlowableClassLoadingException: 当需要载入的类(如JavaDelegate, TaskListener, …​)无法找到,或载入发生错误时抛出。
  • FlowableObjectNotFoundException: 当请求或要 *** 作的对象不存在时抛出。
  • FlowableIllegalArgumentException: 当调用Flowable API时使用了不合法的参数时抛出。可能是引擎配置中的不合法值,或者是API调用传递的不合法参数,也可能是流程定义中的不合法值。
  • FlowableTaskAlreadyClaimedException: 当对已被认领的任务调用taskService.claim(…​)时抛出。
1.6 各种任务讲解

二、springboot整合flowable 2.1第一步:pom依赖


        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.flowable
            flowable-spring-boot-starter
            6.3.0
        
        
        
            mysql
            mysql-connector-java
            5.1.45
        
    

2.2第二步:yml的配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/flowable-spring-boot?characterEncoding=UTF-8
    username: root
    password: root
flowable:
#关闭定时任务JOB
  async-executor-activate: false
2.3第三步:启动启动类

会生产一大堆flowable需要的表

三、flowable-ui可视化bpmn的生成工具 3.1 参考网址:

https://cloud.tencent.com/developer/article/1979771
https://tkjohn.github.io/flowable-userguide/#flowableUIApps

3.2 工具下载安装:
链接:https://pan.baidu.com/s/1olsZ4MuklF9RyJDhtFQ-lg 
提取码:5406

链接:https://pan.baidu.com/s/1LtUVOKRnckTL3YfR5x85_Q 
提取码:meot

第一步:下载Tomcat:https://tomcat.apache.org/download-80.cgi 官网下载后解压缩到非中文目录即可,然后是下载FlowableUI的文件,在Flowable6.6之后把FlowableUI中提供的四个功能合并到了一起。

第二步:然后把解压缩后的两个war包拷贝到Tomcat的解压缩的webapps目录下

第三步:启动Tomcat服务,执行startup.bat文件

如果启动中出现乱码修改Tomcat的conf目录下的 logging.properties 文件中的编码
tomcat启动失败:https://blog.csdn.net/LC_Liangchao/article/details/124499490

在浏览器中访问 http://localhost:8080/flowable-ui, 默认的账号密码是 admin/test

3.3 使用

Flowable提供了几个web应用,用于演示及介绍Flowable项目提供的功能:

  • Flowable IDM: 身份管理应用。为所有Flowable UI应用提供单点登录认证功能,并且为拥有IDM管理员权限的用户提供了管理用户、组与权限的功能。
  • Flowable Modeler: 让具有建模权限的用户可以创建流程模型、表单、选择表与应用定义。
  • Flowable Task: 运行时任务应用。提供了启动流程实例、编辑任务表单、完成任务,以及查询流程实例与任务的功能。
  • Flowable Admin: 管理应用。让具有管理员权限的用户可以查询BPMN、DMN、Form及Content引擎,并提供了许多选项用于修改流程实例、任务、作业等。管理应用通过REST API连接至引擎,并与Flowable Task应用及Flowable REST应用一同部署。

四、代码 4.1 api说明-同上 4.1.1 FormService

表单数据的管理;
是可选服务,也就是说Flowable没有它也能很好地运行,而不必牺牲任何功能。这个服务引入了开始表单(start form)与任务表单(task form)的概念。 开始表单是在流程实例启动前显示的表单,而任务表单是用户完成任务时显示的表单。Flowable可以在BPMN 2.0流程定义中定义这些表单。表单服务通过简单的方式暴露这些数据。再次重申,表单不一定要嵌入流程定义,因此这个服务是可选的

formService.getStartFormKey() // 获取表单key
formService.getRenderedStartForm()  // 查询表单json(无数据)
4.1.2 RepositiryService

提供了在编辑和发布审批流程的api。主要是模型管理和流程定义的业务api

这个服务提供了管理与控制部署(deployments)与流程定义(process definitions)的 *** 作

  • 查询引擎现有的部署与流程定义。
  • 暂停或激活部署中的某些流程,或整个部署。暂停意味着不能再对它进行 *** 作,激活刚好相反,重新使它可以 *** 作。
  • 获取各种资源,比如部署中保存的文件,或者引擎自动生成的流程图。
  • 获取POJO版本的流程定义。它可以用Java而不是XML的方式查看流程。
1.提供了带条件的查询模型流程定义的api
repositoryService.createXXXQuery()
例如:
repositoryService.createModelQuery().list() 模型查询 
repositoryService.createProcessDefinitionQuery().list() 流程定义查询

repositoryService.createXXXXQuery().XXXKey(XXX) (查询该key是否存在)

2.提供一大波模型与流程定义的通用方法
模型相关
repositoryService.getModel()  (获取模型)
repositoryService.saveModel()  (保存模型)
repositoryService.deleteModel() (删除模型)
repositoryService.createDeployment().deploy(); (部署模型)
repositoryService.getModelEditorSource()  (获得模型JSON数据的UTF8字符串)
repositoryService.getModelEditorSourceExtra()  (获取PNG格式图像)

3.流程定义相关
repositoryService.getProcessDefinition(ProcessDefinitionId);  获取流程定义具体信息
repositoryService.activateProcessDefinitionById() 激活流程定义
repositoryService.suspendProcessDefinitionById()  挂起流程定义
repositoryService.deleteDeployment()  删除流程定义
repositoryService.getProcessDiagram()获取流程定义图片流
repositoryService.getResourceAsStream()获取流程定义xml流
repositoryService.getBpmnModel(pde.getId()) 获取bpmn对象(当前进行到的那个节点的流程图使用)

4.流程定义授权相关
repositoryService.getIdentityLinksForProcessDefinition() 流程定义授权列表
repositoryService.addCandidateStarterGroup()新增组流程授权
repositoryService.addCandidateStarterUser()新增用户流程授权
repositoryService.deleteCandidateStarterGroup() 删除组流程授权
repositoryService.deleteCandidateStarterUser()  删除用户流程授权

4.1.3 RuntimeService

处理正在运行的流程

runtimeService.createProcessInstanceBuilder().start() 发起流程
runtimeService.deleteProcessInstance() 删除正在运行的流程
runtimeService.suspendProcessInstanceById() 挂起流程定义
runtimeService.activateProcessInstanceById() 激活流程实例
runtimeService.getVariables(processInstanceId); 获取表单中填写的值
runtimeService.getActiveActivityIds(processInstanceId)获取以进行的流程图节点 (当前进行到的那个节点的流程图使用)

runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState(); 终止流程


4.1.4 HistoryService

在用户发起审批后,会生成流程实例。historyService为处理流程实例的api,但是其中包括了已完成的和未完成的流程实例;
如果是处理正在运行的流程实例,请使用runtimeService;

暴露Flowable引擎收集的所有历史数据。当执行流程时,引擎会保存许多数据(可配置),例如流程实例启动时间、谁在执行哪个任务、完成任务花费的事件、每个流程实例的执行路径,等等。这个服务主要提供查询这些数据的能力

historyService.createHistoricProcessInstanceQuery().list() 查询流程实例列表(历史流程,包括未完成的)
historyService.createHistoricProcessInstanceQuery().list().foreach().getValue() 可以获取历史中表单的信息
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); 根绝id查询流程实例
historyService.deleteHistoricProcessInstance() 删除历史流程
historyService.deleteHistoricTaskInstance(taskid); 删除任务实例
historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list()  流程实例节点列表 (当前进行到的那个节点的流程图使用)

4.1.5 TaskService

对流程实例的各个节点的审批处理

流转的节点审批
taskService.createTaskQuery().list() 待办任务列表
taskService.createTaskQuery().taskId(taskId).singleResult();  待办任务详情
taskService.saveTask(task); 修改任务
taskService.setAssignee() 设置审批人
taskService.addComment() 设置审批备注
taskService.complete() 完成当前审批
taskService.getProcessInstanceComments(processInstanceId); 查看任务详情(也就是都经过哪些人的审批,意见是什么)
taskService.delegateTask(taskId, delegater); 委派任务
taskService.claim(taskId, userId);认领任务
taskService.unclaim(taskId); 取消认领
taskService.complete(taskId, completeVariables); 完成任务

任务授权
taskService.addGroupIdentityLink()新增组任务授权
taskService.addUserIdentityLink() 新增人员任务授权
taskService.deleteGroupIdentityLink() 删除组任务授权
taskService.deleteUserIdentityLink() 删除人员任务授权

4.1.6 ManagementService

主要是执行自定义命令

managementService.executeCommand(new classA())  执行classA的内部方法 

在自定义的方法中可以使用以下方法获取repositoryService

ProcessEngineConfiguration processEngineConfiguration =
            CommandContextUtil.getProcessEngineConfiguration(commandContext);
RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();

也可以获得流程定义方法集合

ProcessEngineConfigurationImpl processEngineConfiguration =
            CommandContextUtil.getProcessEngineConfiguration(commandContext);
        ProcessDefinitionEntityManager processDefinitionEntityManager =
            processEngineConfiguration.getProcessDefinitionEntityManager();
如findById/findLatestProcessDefinitionByKey/findLatestProcessDefinitionByKeyAndTenantId等。

4.1.7 IdentityService

用于身份信息获取和保存,这里主要是获取身份信息

用于管理(创建,更新,删除,查询……)组与用户。请注意,Flowable实际上在运行时并不做任何用户检查。例如任务可以分派给任何用户,而引擎并不会验证系统中是否存在该用户。这是因为Flowable有时要与LDAP、Active Directory等服务结合使用

identityService.createUserQuery().userId(userId).singleResult();  获取审批用户的具体信息
identityService.createGroupQuery().groupId(groupId).singleResult(); 获取审批组的具体信息

4.1.8 DynamicBpmnService

可用于修改流程定义中的部分内容,而不需要重新部署它。例如可以修改流程定义中一个用户任务的办理人设置,或者修改一个服务任务中的类名。

4.2 流程 *** 作讲解 4.2.1 流程部署

部署一个流程定义意味着:

  • 流程引擎会将XML文件存储在数据库中,这样可以在需要的时候获取它。
  • 流程定义转换为内部的、可执行的对象模型,这样使用它就可以启动流程实例。

将流程定义部署至Flowable引擎,需要使用RepositoryService,其可以从ProcessEngine对象获取。使用RepositoryService,可以通过XML文件的路径创建一个新的部署(Deployment),并调用deploy()方法实际执行:

RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
  .addClasspathResource("holiday-request.bpmn20.xml")
  .deploy();

查询验证流程定义已经部署在引擎中的流程bpmn文件名

ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
  .deploymentId(deployment.getId())
  .singleResult();
System.out.println("Found process definition : " + processDefinition.getName());


我们现在可以通过API查询验证流程定义已经部署在引擎中(并学习一些API)。通过RepositoryService创建的ProcessDefinitionQuery对象实现。

@Autowired
public ProcessEngine processEngine;


ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
  .deploymentId(deployment.getId())
  .singleResult();
System.out.println("Found process definition : " + processDefinition.getName());

4.2.2 流程启动

现在已经在流程引擎中部署了流程定义,因此可以使用这个流程定义作为“蓝图”启动流程实例。

要启动流程实例,需要提供一些初始化流程变量。一般来说,可以通过呈现给用户的表单,或者在流程由其他系统自动触发时通过REST API,来获取这些变量。在这个例子里,我们简化为使用java.util.Scanner类在命令行输入一些数据

	Scanner scanner= new Scanner(System.in);
	
	System.out.println("Who are you?");
	String employee = scanner.nextLine();
	
	System.out.println("How many holidays do you want to request?");
	Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());
	
	System.out.println("Why do you need them?");
	String description = scanner.nextLine();
	
		RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("employee", employee);
        variables.put("nrOfHolidays", nrOfHolidays);
        variables.put("description", description);

        // 这个key就是BPMN 2.0 XML文件中设置的id属性 
        ProcessInstance shenhe = runtimeService.startProcessInstanceByKey("shenhe", variables);


例子:

package com.activiti.demo.controller;

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * @author lc
 * @version 1.0
 * @date 2022/4/29 13:49
 */
@RestController
public class DemoController {


    @Autowired
    public ProcessEngine processEngine;

    @RequestMapping("/test")
    public void test() {
        //创建RepositoryService实例
        RepositoryService repositoryService=processEngine.getRepositoryService();
        //加载流程
        Deployment deployment=repositoryService.createDeployment()
                .addClasspathResource("shenhe.bpmn20.xml")
                .deploy();
        // 查看流程
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deployment.getId())
                .singleResult();
        System.out.println("Found process definition : " + processDefinition.getName());
        // 启动流程
        Scanner scanner= new Scanner(System.in);

        System.out.println("Who are you?");
        String employee = scanner.nextLine();

        System.out.println("How many holidays do you want to request?");
        Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());

        System.out.println("Why do you need them?");
        String description = scanner.nextLine();

        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map variables = new HashMap();
        variables.put("employee", employee);
        variables.put("nrOfHolidays", nrOfHolidays);
        variables.put("description", description);

        // 这个key就是BPMN 2.0 XML文件中设置的id属性 
        ProcessInstance shenhe = runtimeService.startProcessInstanceByKey("shenhe", variables);


    }
}

4.2.3 查看任务(流程实例需要的审核人, *** 作人)

usertask等等
我们还没有为用户任务配置办理人。我们想将第一个任务指派给"经理(managers)"组,而第二个用户任务指派给请假申请的提交人。因此需要为第一个任务添加candidateGroups属性:

<userTask id="approveTask" name="Approve or reject request" flowable:candidateGroups="managers"/>

并如下所示为第二个任务添加assignee属性。请注意我们没有像上面的’managers’一样使用静态值,而是使用一个流程变量动态指派。这个流程变量是在流程实例启动时传递的:

<userTask id="holidayApprovedTask" name="Holiday approved" flowable:assignee="${employee}"/>

要获得实际的任务列表,需要通过TaskService创建一个TaskQuery。我们配置这个查询只返回’managers’组的任务:

TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
System.out.println("You have " + tasks.size() + " tasks:");
for (int i=0; i<tasks.size(); i++) {
  System.out.println((i+1) + ") " + tasks.get(i).getName());
}

可以使用任务Id获取特定流程实例的变量,并在屏幕上显示实际的申请:

System.out.println("Which task would you like to complete?");
int taskIndex = Integer.valueOf(scanner.nextLine());
Task task = tasks.get(taskIndex - 1);
Map processVariables = taskService.getVariables(task.getId());
System.out.println(processVariables.get("employee") + " wants " +
    processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?");

4.2.4 完成任务

经理现在就可以完成任务了。在现实中,这通常意味着由用户提交一个表单。表单中的数据作为流程变量传递。在这里,我们在完成任务时传递带有’approved’变量(这个名字很重要,因为之后会在顺序流的条件中使用!)的map来模拟:

boolean approved = scanner.nextLine().toLowerCase().equals("y");
variables = new HashMap<String, Object>();
variables.put("approved", approved);
taskService.complete(task.getId(), variables);
4.2.5 JavaDelegate - 实现申请通过后执行的自动逻辑

拼图还缺了一块:我们还没有实现申请通过后执行的自动逻辑。在BPMN 2.0 XML中,这是一个服务任务(service task):

<serviceTask id="externalSystemCall" name="Enter holidays in external system"
    flowable:class="org.flowable.CallExternalSystemDelegate"/>

在现实中,这个逻辑可以做任何事情:向某个系统发起一个HTTP REST服务调用,或调用某个使用了好几十年的系统中的遗留代码。我们不会在这里实现实际的逻辑,而只是简单的日志记录流程。

具体 *** 作如下:
创建一个类实现JavaDelegate接口。并且实现execute方法


import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

public class CallExternalSystemDelegate implements JavaDelegate {

    public void execute(DelegateExecution execution) {
        System.out.println("Calling the external system for employee "
            + execution.getVariable("employee"));
    }

}

当执行到达服务任务时,会初始化并调用BPMN 2.0 XML中所引用的类。

上述例子是输入y,就会走这个了;

4.2.6 使用历史数据

选择使用Flowable这样的流程引擎的原因之一,是它可以自动存储所有流程实例的审计数据或历史数据。这些数据可以用于创建报告,深入展现组织运行的情况,瓶颈在哪里,等等。

例如,如果希望显示流程实例已经执行的时间,就可以从ProcessEngine获取HistoryService,并创建历史活动(historical activities)的查询。在下面的代码片段中,可以看到我们添加了一些额外的过滤条件:

  • 只选择一个特定流程实例的活动

  • 只选择已完成的活动

结果按照结束时间排序,代表其执行顺序。

HistoryService historyService = processEngine.getHistoryService();
List<HistoricActivityInstance> activities =
  historyService.createHistoricActivityInstanceQuery()
   .processInstanceId(processInstance.getId())
   .finished()
   .orderByHistoricActivityInstanceEndTime().asc()
   .list();

for (HistoricActivityInstance activity : activities) {
  System.out.println(activity.getActivityId() + " took "
    + activity.getDurationInMillis() + " milliseconds");
}

再次运行例子,可以看到控制台中显示:

startEvent took 1 milliseconds
approveTask took 2638 milliseconds
decision took 3 milliseconds
externalSystemCall took 1 milliseconds
4.2.7 结束流程

可以使用与之前完全相同的方式获取并申领审核任务。完成这个第二个任务会将流程执行移至结束事件,并结束流程实例。这个流程实例,及所有相关的运行时执行数据都会从数据库中移除。

也可以通过编程方式,使用historyService验证流程已经结束

HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance =
historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());
4.2.8 删除流程
/**
       * deleteDeployment  
       * Deployment deployment 
       * 第一参数是流程id(deployment.getId())  如果流程启动将不允许删除
       * 第二参数数级联删除  如果流程启动了也可以删除 相关的任务也会删除
       */
      repositoryService.deleteDeployment(deployment.getId());
      ProcessDefinitionQuery processDefinitionQuery = 
     repositoryService.createProcessDefinitionQuery();

4.3 案例 4.3.1 简单案例
public class TenMinuteTutorial {
	
  public static void main(String[] args) {

    // 创建Flowable流程引擎(spring项目可以直接注入使用)
    ProcessEngine processEngine = ProcessEngineConfiguration
      .createStandaloneProcessEngineConfiguration()
      .buildProcessEngine();

    // 获取Flowable服务
    RepositoryService repositoryService = processEngine.getRepositoryService();
    RuntimeService runtimeService = processEngine.getRuntimeService();

    // 部署流程定义
    repositoryService.createDeployment()
      .addClasspathResource("FinancialReportProcess.bpmn20.xml")
      .deploy();

    // 启动流程实例
    String procId = runtimeService.startProcessInstanceByKey("financialReport").getId();

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

      // 申领任务
      taskService.claim(task.getId(), "fozzie");
    }

    // 验证Fozzie获取了任务
    tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
    for (Task task : tasks) {
      System.out.println("Task for fozzie: " + task.getName());

      // 完成任务
      taskService.complete(task.getId());
    }

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

    // 获取并申领第二个任务
    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(), "kermit");
    }

    // 完成第二个任务并结束流程
    for (Task task : tasks) {
      taskService.complete(task.getId());
    }

    // 验证流程已经结束
    HistoryService historyService = processEngine.getHistoryService();
    HistoricProcessInstance historicProcessInstance =
      historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
    System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());
  }

}

可以看出这个业务流程太简单了,不能实际使用。但只要继续学习Flowable中可用的BPMN 2.0结构,就可以通过以下元素增强业务流程:

  • 定义网关(gateway)使经理可以选择:驳回财务报告,并重新为会计师创建任务;或者接受报告。
  • 定义并使用变量(variables)存储或引用报告,并可以在表单中显示它。
  • 在流程结束处定义服务任务(service task),将报告发送给每一个投资人。
    等等。
4.3.2 进阶案例

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/916644.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存