activiti版本为5.22
公司业务需求要求显示流程图的执行的线路高亮
然后就开始了漫长的复制粘贴之旅
因为activiti不会对走过Flow进行记录,只对活动做记录,基本思路就是通过historyService可以获取到所有的HistoricActivityInstance,然后通过活动顺序再获取到执行过的flowId
// 获得历史活动记录实体
List<HistoricActivityInstance> historicActivityInstances = historyService
.createHistoricActivityInstanceQuery().processInstanceId(processId).list();
但是这里有一个巨坑,这个HistoricActivityInstance是无序的,里面并没有字段可以对其进行排序,网上有很多文章说是用开始时间进行排序
List<HistoricActivityInstance> historicActivityInstances = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(processId)
.orderByHistoricActivityInstanceStartTime()
.asc()
.list();
但这是根本就是扯淡,开始时间根本不能排序,因为很多活动都是一瞬间完成的,开始时间是完全相同的,比如开始事件和第一个活动,比如排他网关和执行的下一个活动,所以根本无法排序,同理结束时间也无法进行排序。
还有很多文章写了很复杂的算法来获取到执行过的线路,但是都是没有用,不是少了就是多了。
最后仔细的研究了HistoricActivityInstance这个类,发现其实是有规律的,那就是一个活动结束的时间是和下一个执行的活动的开始时间,如果当前Activity的结束时间和下一个Activity的开始时间相等两个活动中间的Flow就走过,知道原理就好办了。
下面贴上核心代码。
public List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) {
// 用以保存高亮的线flowId
List<String> highFlows = new ArrayList<>();
historicActivityInstances.forEach(historicActivityInstance -> {
ActivityImpl activityImpl = processDefinitionEntity.findActivity(historicActivityInstance.getActivityId());
List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();
Date endTime = historicActivityInstance.getEndTime();
//如果结束时间不为空
if (endTime != null) {
pvmTransitions.forEach(pvmTransition -> {
String id = pvmTransition.getDestination().getId();
List<HistoricActivityInstance> collect = historicActivityInstances.stream().filter(h -> h.getActivityId().equals(id)).collect(Collectors.toList());
collect.forEach(c -> {
//如果当前Activity的结束时间和下一个Activity的开始时间相等此路线就走过
if (c.getStartTime().getTime() == endTime.getTime()) {
highFlows.add(pvmTransition.getId());
}
});
});
}
});
return highFlows;
}