2026/4/18 9:01:17
网站建设
项目流程
怀化公司网站建设,服务周到的做网站,做徽章标牌的企业网站,什么是优化师1. Flowable历史数据基础概念解析
第一次接触Flowable的历史数据模块时#xff0c;我完全被那些以ACT_HI_开头的数据库表搞晕了。直到在某个深夜加班调试流程时#xff0c;突然意识到这些历史数据就像是流程世界的黑匣子#xff0c;完整记录了每个流程实例从生到…1. Flowable历史数据基础概念解析第一次接触Flowable的历史数据模块时我完全被那些以ACT_HI_开头的数据库表搞晕了。直到在某个深夜加班调试流程时突然意识到这些历史数据就像是流程世界的黑匣子完整记录了每个流程实例从生到死的全部轨迹。Flowable的历史数据模块主要包含六大核心实体它们各自承担着不同的记录职责HistoricProcessInstance流程实例的人生档案记录流程从启动到结束的关键时间节点。我常把它比作快递物流信息能看到流程什么时候发货startTime、什么时候签收endTimeHistoricActivityInstance每个流程节点的监控录像精确到秒级记录节点执行情况。最近排查一个审批卡顿问题时就是通过它发现某个审批节点平均耗时高达47秒HistoricVariableInstance流程变量的时光胶囊保存着流程运行过程中所有变量的最终状态。上周财务部门需要三年前的某个报销流程的审批金额就是从这里挖出来的HistoricTaskInstance人工任务的工作日志包含任务分配人、处理时间等关键信息。人力资源部做绩效考核时这些数据就是重要依据HistoricDetail流程细节的显微镜可以追踪变量变更记录。曾用它找出某个订单价格被多次修改的完整记录HistoricIdentityLink参与者的通讯录记录所有参与过流程的人员信息与运行时数据相比历史数据有三大特点持久性流程结束后依然存在不像运行时数据会被清理只读性只能查询不能修改确保数据真实性分析友好包含完整的生命周期信息适合做统计分析// 典型的历史数据表结构示例 ACT_HI_PROCINST (流程实例表) |-- ID_ // 主键 |-- PROC_DEF_ID_ // 流程定义ID |-- START_TIME_ // 开始时间 |-- END_TIME_ // 结束时间 |-- DURATION_ // 总耗时(毫秒) |-- START_USER_ID_// 发起人2. 历史流程实例查询实战去年我们系统出现一个诡异现象某些流程实例会无故消失。最后就是通过历史流程查询锁定了问题——某个定时任务误删了运行中的数据但历史表里还完整保留着这些流程的遗照。2.1 基础查询方法最常用的查询场景莫过于查找特定状态的流程实例。比如要查询所有已完成的采购审批流程ListHistoricProcessInstance processes historyService .createHistoricProcessInstanceQuery() .processDefinitionKey(purchaseApproval) .finished() // 只查已结束的 .list();几个实用的查询技巧.unfinished()查找进行中的流程.processDefinitionKey()按流程类型过滤.startedBy(user1)按发起人过滤2.2 高级查询技巧当需要做流程效能分析时这些查询特别有用// 查询耗时最长的10个流程 ListHistoricProcessInstance slowProcesses historyService .createHistoricProcessInstanceQuery() .orderByProcessInstanceDuration().desc() .listPage(0, 10); // 查询某时间段内发起的流程 Date startDate Date.from(LocalDate.now().minusDays(7).atStartOfDay(ZoneId.systemDefault()).toInstant()); Date endDate new Date(); ListHistoricProcessInstance recentProcesses historyService .createHistoricProcessInstanceQuery() .startedAfter(startDate) .startedBefore(endDate) .list();2.3 元数据查询有时我们需要获取流程的关联信息HistoricProcessInstance instance historyService .createHistoricProcessInstanceQuery() .processInstanceId(123) .includeProcessVariables() // 包含变量 .singleResult(); MapString, Object variables instance.getProcessVariables(); String businessKey instance.getBusinessKey();提示当查询大量历史数据时建议使用.listPage(start, size)分页查询避免内存溢出3. 历史变量查询的妙用曾经处理过一个棘手的需求需要找出所有修改过合同金额的审批流程。历史变量查询就像时光机带我找出了所有动过金额字段的流程记录。3.1 基础变量查询// 查询某个流程的所有历史变量 ListHistoricVariableInstance variables historyService .createHistoricVariableInstanceQuery() .processInstanceId(123) .list(); // 查询特定变量的变更记录 HistoricVariableInstance amountVar historyService .createHistoricVariableInstanceQuery() .processInstanceId(123) .variableName(contractAmount) .singleResult();3.2 变量类型处理Flowable支持多种变量类型查询时需要特别注意// 处理不同类型变量 variables.forEach(var - { if(var.getVariableTypeName().equals(string)) { String value (String)var.getValue(); // 处理字符串值 } else if(var.getVariableTypeName().equals(long)) { Long value (Long)var.getValue(); // 处理数值 } });3.3 变量变更追踪要查看变量的完整修改记录需要使用HistoricDetailListHistoricDetail changes historyService .createHistoricDetailQuery() .variableUpdates() .processInstanceId(123) .variableName(contractAmount) .orderByTime().asc() .list(); changes.forEach(change - { HistoricVariableUpdate update (HistoricVariableUpdate)change; System.out.println(update.getTime() : update.getValue()); });4. 历史活动与任务查询实战上个月做流程优化时我发现审批流程的平均耗时比预期长很多。通过历史活动查询最终定位到问题出在财务复核环节该环节平均耗时高达2.3天。4.1 活动实例查询// 查询某个流程的所有活动节点 ListHistoricActivityInstance activities historyService .createHistoricActivityInstanceQuery() .processInstanceId(123) .orderByHistoricActivityInstanceStartTime().asc() .list(); // 查询特定类型的活动 ListHistoricActivityInstance userTasks historyService .createHistoricActivityInstanceQuery() .activityType(userTask) .processInstanceId(123) .list();4.2 任务实例查询// 查询某用户处理过的所有任务 ListHistoricTaskInstance tasks historyService .createHistoricTaskInstanceQuery() .taskAssignee(zhangsan) .finished() .orderByHistoricTaskInstanceEndTime().desc() .list(); // 查询超时任务 long threshold 1000 * 60 * 60 * 24; // 24小时 ListHistoricTaskInstance overdueTasks historyService .createHistoricTaskInstanceQuery() .finished() .taskDurationGreaterThan(threshold) .list();4.3 活动耗时分析这个代码帮我找出了流程中的性能瓶颈ListHistoricActivityInstance activities historyService .createHistoricActivityInstanceQuery() .processDefinitionId(leaveApproval:1:123) .finished() .list(); MapString, ListLong durationByActivity activities.stream() .collect(Collectors.groupingBy( HistoricActivityInstance::getActivityId, Collectors.mapping( ai - ai.getDurationInMillis(), Collectors.toList() ) )); durationByActivity.forEach((activityId, durations) - { double avg durations.stream().mapToLong(l - l).average().orElse(0); System.out.println(activityId 平均耗时 (avg / 1000 / 60) 分钟); });5. 高级历史数据应用场景5.1 流程版本对比当流程定义升级后我们常需要对比不同版本的表现// 查询v1.0版本的流程实例 ListHistoricProcessInstance v1Instances historyService .createHistoricProcessInstanceQuery() .processDefinitionKey(loanApproval) .processDefinitionVersion(1) .finished() .list(); // 查询v2.0版本的流程实例 ListHistoricProcessInstance v2Instances historyService .createHistoricProcessInstanceQuery() .processDefinitionKey(loanApproval) .processDefinitionVersion(2) .finished() .list(); // 比较平均处理时间 double v1Avg calculateAverageDuration(v1Instances); double v2Avg calculateAverageDuration(v2Instances);5.2 流程轨迹重现通过组合多种历史数据可以完整重现流程执行过程public void replayProcess(String processInstanceId) { // 获取流程实例 HistoricProcessInstance instance historyService .createHistoricProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); System.out.println(流程[ instance.getId() ]轨迹); System.out.println(发起时间 instance.getStartTime()); // 获取所有活动节点 ListHistoricActivityInstance activities historyService .createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime().asc() .list(); // 打印节点轨迹 activities.forEach(act - { System.out.printf(%s - %s (%s~%s)\n, act.getActivityName(), act.getActivityType(), act.getStartTime(), act.getEndTime()); }); System.out.println(结束时间 instance.getEndTime()); }5.3 历史数据清理随着系统运行历史数据会不断膨胀需要定期清理// 删除3个月前的完成的历史流程 Calendar calendar Calendar.getInstance(); calendar.add(Calendar.MONTH, -3); Date beforeDate calendar.getTime(); historyService.createHistoricProcessInstanceDeleteBuilder() .finishedBefore(beforeDate) .deleteWithRelatedData(); // 同时删除关联数据注意删除操作不可逆建议先做备份。我们曾经误删过一次数据现在都会先执行.count()确认影响范围