Activiti工作流查看流程视图
思路
首先我们要知道Activiti工作流查看流程针对的是运行的实例, 可以看到流程流转到那个节点。
但是大多数情况实例对业务来说是没有意义的,那么我就需要业务key,每个业务key对应工作流唯一的task任务。
有了这些想法我们就能构思查看流程视图的接口了,入参肯定是业务能够提供的,出参没有疑问那就是图片了,为了方便我们直接返回图片流InputStream
业务key转换流程实例
通过businessKey 查询业务key对应的task任务
List<Task> tasks = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).list();
理论上来说业务businessKey也是唯一的,但是对Activiti来说只是某一列返回List,没事我们直接加判断,不唯一就异常出去。
if(tasks != null && tasks.size() == 1){
String taskId = tasks.get(0).getId();
Task nowTask = taskService.createTaskQuery().taskId(taskId).singleResult();
processInstanceId = nowTask.getProcessInstanceId();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinitionId = processInstance.getProcessDefinitionId();
}else if (tasks != null && tasks.size() == 0){
List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().finished().processInstanceBusinessKey(businessKey).list();
if(list != null && list.size() == 1){
processDefinitionId = list.get(0).getProcessDefinitionId();
processInstanceId = list.get(0).getId();
}
}
有了思路不多说直接上代码
public InputStream _$look_png(String businessKey) {
logger.info("_$look_png---参数businessKey="+businessKey);
InputStream inputStream= null;
String processInstanceId = null;
String processDefinitionId = null;
try {
List<Task> tasks = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).list();
logger.info("_$look_png---任务tasks="+ tasks);
if(tasks != null && tasks.size() == 1){
String taskId = tasks.get(0).getId();
Task nowTask = taskService.createTaskQuery().taskId(taskId).singleResult();
processInstanceId = nowTask.getProcessInstanceId();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinitionId = processInstance.getProcessDefinitionId();
}else if (tasks != null && tasks.size() == 0){
List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().finished().processInstanceBusinessKey(businessKey).list();
if(list != null && list.size() == 1){
processDefinitionId = list.get(0).getProcessDefinitionId();
processInstanceId = list.get(0).getId();
}
}
if(StringUtils.isBlank(processInstanceId) || StringUtils.isBlank(processDefinitionId)){
logger.info("_$look_png---异常,未找到或发现多个流程!businessKey="+businessKey);
String result = "未找到或发现多个流程!businessKey="+businessKey;
inputStream = new ByteArrayInputStream(result.getBytes());
return inputStream;
}
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
List<HistoricActivityInstance> activityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
List<String> activityIds = new ArrayList<String>();
List<String> flowIds = new ArrayList<String>();
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processDefinitionId);
//获取流程走过的线
flowIds = getHighLightedFlows(processDefinition, activityInstances);
for (HistoricActivityInstance hai : activityInstances) {
//获取流程走过的节点
activityIds.add(hai.getActivityId());
}
ImageIO.setCacheDirectory(new File(_PNG_PATH));
inputStream = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator().generateDiagram(bpmnModel, "png", activityIds, flowIds,"宋体", "宋体", "宋体", null, 1.0);
}catch (Exception e){
e.printStackTrace();
logger.error("_$look_png---异常:", e);
}
return inputStream;
}
这里有个注意的地方, linux注意安装字体
linux 安装字体
yum install -y fontconfig mkfontscale
将 宋体 丢入/usr/share/fonts/
建立字体索引信息,更新字体缓存,使用如下命令:
mkfontscale
mkfontdir
fc-cache
查看安装字体fc-list,重启服务
//获取流程走过的线
public static List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity,List<HistoricActivityInstance> haiList) throws Exception{
//用来保存高亮的线 flowId
List<String> highFlows = new ArrayList<String>();
for (int i = 0; i < haiList.size() - 1; i++) {
//对历史流程节点进行遍历
//得到节点定义的详细信息
ActivityImpl activityImpl = processDefinitionEntity.findActivity(haiList.get(i).getActivityId());
//用以保存后需要开始时间相同的节点
List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();
ActivityImpl sameActivityImpl1 = processDefinitionEntity.findActivity(haiList.get(i + 1).getActivityId());
//讲后面第一个节点放在时间相同节点的集合里
sameStartTimeNodes.add(sameActivityImpl1);
for (int j = i + 1; j < haiList.size() - 1; j++) {
HistoricActivityInstance activityImpl1 = haiList.get(j);//后续第一个节点
HistoricActivityInstance activityImpl2 = haiList.get(j + 1);//后续第而个节点
if(activityImpl1.getStartTime().equals(activityImpl2.getStartTime())){
//如果第一个节点和第二个节点开始时间相同保存
ActivityImpl sameActivityImpl2 = processDefinitionEntity.findActivity(activityImpl2.getActivityId());
sameStartTimeNodes.add(sameActivityImpl2);
}else{
//不同就调查循环
break;
}
}
//取出节点的所有出去的线
List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();
for(PvmTransition pvmTransition : pvmTransitions){
//对所有的线进行遍历
ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();
//如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示
if(sameStartTimeNodes.contains(pvmActivityImpl)){
highFlows.add(pvmTransition.getId());
}
}
}
return highFlows;
}