Flowable6.x导出/查看/跟踪流程图
Flowable6.x导出/查看/跟踪流程图
项目源码仓库
Flowable诞生于Activiti,是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎可用于部署BPMN 2.0流程定义,可以十分灵活地加入你的应用/服务/构架。
本文介绍4种绘制流程图的方式,前3种是在后台绘制静态图(image/png格式),以Stream形式返回前端显示。最后1种是后端生成JSON形式的结构化数据,由前端使用Snap.svg绘制的交互式SVG动画流程图。
导入Maven依赖
<dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter-basic</artifactId><version>6.4.1</version></dependency><dependency><groupId>org.flowable</groupId><artifactId>flowable-json-converter</artifactId><version>6.4.1</version></dependency>
导出流程定义图
适用于流程管理或启动流程时查看已经部署的流程图,流程图不包括任务办理实际流转信息。
使用流程定义(ProcessDefinition.id),通过调用flowable 的RepositoryService来导出其流程定义的图片资源。
源码:
@RestController
@Slf4j
public class ProcessController {@Autowiredprivate MyProcessService processService;/* 通过processDefinition.id和resType导出流程XML或图片资源* @param id processDefinition.id* @param resType 取值 “image/png”或“text/xml”* @param response* @throws Exception*/@GetMapping(value = "/res/exp")@ApiOperation("通过processDefinition.id和resType导出流程XML或图片资源")public void resourceRead(@RequestParam("id") String id,@RequestParam("resType") String resType, HttpServletResponse response) throws Exception {/ resType取值 “image/png”或“text/xml” /InputStream resourceAsStream = processService.resourceRead(id,resType);byte[] b = new byte[1024];int len = -1;while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {response.getOutputStream().write(b, 0, len);}}
}
@Service
public class MyProcessServiceImpl implements MyProcessService {@Autowiredprivate RepositoryService repositoryService;@Overridepublic InputStream resourceRead(String id, String resType) throws Exception {ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();String resourceName = "";if (resType.equals("image/png")) {resourceName = processDefinition.getDiagramResourceName();} else if (resType.equals("text/xml")) {resourceName = processDefinition.getResourceName();}InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);return resourceAsStream;}
}
运行效果如下:
绘制流程待办流图
适用于查看待办任务列表时,绘制该任务的流程图,流程图可强调显示当前待办任务所处的流程节点。使用流程实例(processInstanceId)ID,通过调用flowable引擎来绘制流程图。
源码:
@RequestMapping("/api/workflow/auth/activiti/task")
@RestController
@Slf4j
public class TaskController {@Autowiredprivate MyTaskService myTaskService;/* 绘制强调当前节点的流程图*/@GetMapping(value = "/process/diagram")@ApiOperation("绘制强调当前节点的流程图")public void genProcessDiagram(@RequestParam("processInstanceId") String processInstanceId, HttpServletResponse httpServletResponse) throws Exception {InputStream resourceAsStream = myTaskService.genProcessDiagram(processInstanceId);byte[] b = new byte[1024];int len = -1;while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {httpServletResponse.getOutputStream().write(b, 0, len);}}
}
@Slf4j
@Service
public class MyTaskServiceImpl implements MyTaskService {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate RepositoryService repositoryService;@Resourceprivate ProcessEngine processEngine;@Overridepublic InputStream genProcessDiagram(String processId) throws Exception {ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();//流程走完的不显示图if (pi == null) {return null;}Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();//使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象String InstanceId = task.getProcessInstanceId();List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(InstanceId).list();//得到正在执行的Activity的IdList<String> activityIds = new ArrayList<>();List<String> flows = new ArrayList<>();for (Execution exe : executions) {List<String> ids = runtimeService.getActiveActivityIds(exe.getId());activityIds.addAll(ids);}//获取流程图BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 2.0,true);return in;}
}
绘制流程已办流图
适用于查看已办任务列表时,绘制该任务的流程图,流程图可强调显示任务办理实际经过的路径。使用流程实例(processInstanceId)ID,通过调用flowable引擎来绘制流程图。
源码:
@RequestMapping("/api/workflow/auth/activiti/task")
@RestController
@Slf4j
public class TaskController {@Autowiredprivate MyTaskService myTaskService;/* 读取带跟踪的图片*/@GetMapping(value = "/trace/photo")public void tracePhoto(@RequestParam("processInstanceId") String processInstanceId, HttpServletResponse response) throws Exception {InputStream inputStream = myTaskService.genTracePhoto(processInstanceId);// 输出资源内容到相应对象byte[] b = new byte[1024];int len;while ((len = inputStream.read(b, 0, 1024)) != -1) {response.getOutputStream().write(b, 0, len);}}
}
@Slf4j
@Service
public class MyTaskServiceImpl implements MyTaskService {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Resourceprivate HistoryService historyService;@Autowiredprivate RepositoryService repositoryService;@Overridepublic InputStream genTracePhoto(String processInstanceId) throws Exception {String procDefId;ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();if (processInstance == null) {HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();procDefId = historicProcessInstance.getProcessDefinitionId();} else {procDefId = processInstance.getProcessDefinitionId();}BpmnModel bpmnModel = repositoryService.getBpmnModel(procDefId);DefaultProcessDiagramGenerator defaultProcessDiagramGenerator = new DefaultProcessDiagramGenerator(); // 创建默认的流程图生成器String imageType = "png"; // 生成图片的类型List<String> highLightedActivities = new ArrayList<>(); // 高亮节点集合List<String> highLightedFlows = new ArrayList<>(); // 高亮连线集合List<HistoricActivityInstance> hisActInsList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list(); // 查询所有历史节点信息hisActInsList.forEach(historicActivityInstance -> { // 遍历if("sequenceFlow".equals(historicActivityInstance.getActivityType())) {// 添加高亮连线highLightedFlows.add(historicActivityInstance.getActivityId());} else {// 添加高亮节点highLightedActivities.add(historicActivityInstance.getActivityId());}});String activityFontName = "宋体"; // 节点字体String labelFontName = "微软雅黑"; // 连线标签字体String annotationFontName = "宋体"; // 连线标签字体ClassLoader customClassLoader = null; // 类加载器double scaleFactor = 1.0d; // 比例因子,默认即可boolean drawSequenceFlowNameWithNoLabelDI = true; // 不设置连线标签不会画// 生成图片InputStream inputStream = defaultProcessDiagramGenerator.generateDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, activityFontName, labelFontName, annotationFontName, customClassLoader,scaleFactor, drawSequenceFlowNameWithNoLabelDI); // 获取输入流return inputStream;}
}
前端绘制流程跟踪图和显示日志
无论是待办、已办,亦或是流转中、已结束的流程实例,通过使用JS绘制SVG格式的交互式流程图,与以上三种方式相比,在效果上都具有明显优势。
运行效果如下图所示:
具体内容参见下一篇博文
项目源码仓库