- 一、认识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使用了BPMN的技术(业务模型和符号),如下图:
总入口点是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 网关组件
网关相当于判断(与或非),最长用的三种网关分别是 互斥/排他网关、并行网关、包容网关
相当于判断,举例:如果输入值大于20走A节点,小20走B节点
与相容网关成对出现,表示网关中的人全部同意才能进入下一节点
它可以将执行分支(fork)为多条路径,也可以合并(join)多条入口路径的执行
1.2.3.3 包容网关:互斥网关与并行网关的结合体,如果满足A,B都互斥条件,则都需要流转,如果只有一个满足,那么久只流转满足条件的
包容网关与排他网关一样,可以在包容网关的出口顺序流上定义条件,包容网关会计算条件。然而主要的区别是,包容网关与并行网关一样,可以同时选择多于一条出口顺序流。
说明:
1.当审批申请人提交完成后进入审批阶段
2.两位项目经理进行审批,需要两人都同意进入下一节点
3.经理进行审批,此处业务为经理职位(mamage)的人都可以执行审批。(此处有认领业务此处不描述)
4.总经理/董事长审批,如果大于20天需要董事长审批,如果小于20天总经理审批。
标准的审批流系统都有一套标准化的业务流程下文,介绍如何 *** 作审批流系统。
一般在系统中的模块名如下, 请个字对应。
这里的任务管理可以查看到一个流程每个审批节点的具体信息。
在申请人进行审批时,需要填写申请的项目和申请数据。如请假审批需要填写请假时间和原因。所以这个表单我们希望可以定制
也就是使用BPMN绘制流程图,在图中会指定该审批流程的表单,下一审批节点人员与进入流程的流转条件。
当然也可以导入流程图。同时可以指定申请人在申请时需要填写的表单(审批人如果需要添加审批表单也可以在此处配置)
流程模型在编辑/导入后,并不会生效。之后发布生产流程定义后才能够使用并发起审批。当然流程定义模块还可以有导出激活等功能。
当设计完流程之后,就可以发起审批和进行审批了,用户拥有以下功能。
1.3.2.2 功能解释驳回:将审批重置发送给某节点,重新审批
转办:A转给其B审批,B审批后,进入下一节点
委派:A转给B审批,B审批后转给A,A审批后进入下一节点
根据上图可见,当发起审批后,就会生产流程实例了。流程实例和任务管理就可以查看到已发起的审批了
- 每一套审批信息生产一条流程实例信息
- 一条流程实例有多个审批节点(流程图中已画),每一个审批节点是一条任务管理信息。
- 请注意流程实例和流程定义的概念
流程定义(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数据库表的一行
表单数据的管理
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(…)时抛出。
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需要的表
https://cloud.tencent.com/developer/article/1979771
https://tkjohn.github.io/flowable-userguide/#flowableUIApps
链接: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应用一同部署。
表单数据的管理;
是可选服务,也就是说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),将报告发送给每一个投资人。
等等。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)