zoukankan      html  css  js  c++  java
  • Activiti开发案例之代码生成工作流图片

    图例

    环境

    软件 版本
    SpringBoot 1.5.10
    activiti-spring-boot-starter-basic 6.0

    生成代码

    以下是简化代码:

        /**
    	 * 查看实例流程图,根据流程实例ID获取流程图
    	 */
    	@RequestMapping(value="traceprocess/{instanceId}",method=RequestMethod.GET)
    	public void traceprocess(HttpServletResponse response,@PathVariable("instanceId")String instanceId) throws Exception{
    		InputStream in = flowUtils.getResourceDiagramInputStream(instanceId);
    		ServletOutputStream output = response.getOutputStream();
    		IOUtils.copy(in, output);
    	}
    

    Flow 工具类:

    /**
     * Flow 工具类
     * @author zhipeng.zhang
     */
    @Component
    public class FlowUtils {
    	
    	@Autowired
    	RuntimeService runservice;
    	@Autowired
        private HistoryService historyService;
    	@Autowired
    	private RepositoryService repositoryService;
    	@Autowired
    	private ProcessEngineFactoryBean processEngine;
    	/**
    	 * 获取历史节点流程图
    	 * @param id
    	 * @return
    	 */
    	public  InputStream getResourceDiagramInputStream(String id) {
            try {
                // 获取历史流程实例
                HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
                // 获取流程中已经执行的节点,按照执行先后顺序排序
                List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(id).orderByHistoricActivityInstanceId().asc().list();
                // 构造已执行的节点ID集合
                List<String> executedActivityIdList = new ArrayList<String>();
                for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                    executedActivityIdList.add(activityInstance.getActivityId());
                }
                // 获取bpmnModel
                BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
                // 获取流程已发生流转的线ID集合
                List<String> flowIds = this.getExecutedFlows(bpmnModel, historicActivityInstanceList);
                // 使用默认配置获得流程图表生成器,并生成追踪图片字符流
                ProcessDiagramGenerator processDiagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
                //你也可以 new 一个
                //DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
                InputStream imageStream = processDiagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", null, 2.0);
                return imageStream;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    	
    	private List<String> getExecutedFlows(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstances) {
            // 流转线ID集合
            List<String> flowIdList = new ArrayList<String>();
            // 全部活动实例
            List<FlowNode> historicFlowNodeList = new LinkedList<FlowNode>();
            // 已完成的历史活动节点
            List<HistoricActivityInstance> finishedActivityInstanceList = new LinkedList<HistoricActivityInstance>();
            for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
                historicFlowNodeList.add((FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true));
                if (historicActivityInstance.getEndTime() != null) {
                    finishedActivityInstanceList.add(historicActivityInstance);
                }
            }
            // 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
            FlowNode currentFlowNode = null;
            for (HistoricActivityInstance currentActivityInstance : finishedActivityInstanceList) {
                // 获得当前活动对应的节点信息及outgoingFlows信息
                currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
                List<SequenceFlow> sequenceFlowList = currentFlowNode.getOutgoingFlows();
                /**
                 * 遍历outgoingFlows并找到已已流转的
                 * 满足如下条件认为已已流转:
                 * 1.当前节点是并行网关或包含网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
                 * 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最近的流转节点视为有效流转
                 */
                FlowNode targetFlowNode = null;
                if (BpmsActivityTypeEnum.PARALLEL_GATEWAY.getType().equals(currentActivityInstance.getActivityType())
                        || BpmsActivityTypeEnum.INCLUSIVE_GATEWAY.getType().equals(currentActivityInstance.getActivityType())) {
                    // 遍历历史活动节点,找到匹配Flow目标节点的
                    for (SequenceFlow sequenceFlow : sequenceFlowList) {
                        targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true);
                        if (historicFlowNodeList.contains(targetFlowNode)) {
                            flowIdList.add(sequenceFlow.getId());
                        }
                    }
                } else {
                    List<Map<String, String>> tempMapList = new LinkedList<Map<String,String>>();
                    // 遍历历史活动节点,找到匹配Flow目标节点的
                    for (SequenceFlow sequenceFlow : sequenceFlowList) {
                        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
                            if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
                                tempMapList.add(UtilMisc.toMap("flowId", sequenceFlow.getId(), "activityStartTime", String.valueOf(historicActivityInstance.getStartTime().getTime())));
                            }
                        }
                    }
                    // 遍历匹配的集合,取得开始时间最早的一个
                    long earliestStamp = 0L;
                    String flowId = null;
                    for (Map<String, String> map : tempMapList) {
                        long activityStartTime = Long.valueOf(map.get("activityStartTime"));
                        if (earliestStamp == 0 || earliestStamp >= activityStartTime) {
                            earliestStamp = activityStartTime;
                            flowId = map.get("flowId");
                        }
                    }
                    flowIdList.add(flowId);
                }
            }
            return flowIdList;
        }
    	
    }
    

    UtilMisc 工具类:

    public class UtilMisc {
        public static <V, V1 extends V, V2 extends V> Map<String, V> toMap(String name1, V1 value1, String name2, V2 value2) {
            return populateMap(new HashMap<String, V>(), name1, value1, name2, value2);
        }
        @SuppressWarnings("unchecked")
        private static <K, V> Map<String, V> populateMap(Map<String, V> map, Object... data) {
            for (int i = 0; i < data.length;) {
                map.put((String) data[i++], (V) data[i++]);
            }
            return map;
        }
    }
    

    工作流枚举类:

    /**
     * 工作流枚举类
     * @author zhipeng.zhang
     */
    public enum BpmsActivityTypeEnum {
        
        START_EVENT("startEvent", "开始事件"),
        END_EVENT("endEvent", "结束事件"),
        USER_TASK("userTask", "用户任务"),
        EXCLUSIVE_GATEWAY("exclusiveGateway", "排他网关"),
        PARALLEL_GATEWAY("parallelGateway", "并行网关"),
        INCLUSIVE_GATEWAY("inclusiveGateway", "包含网关");
        
        private String type;
        private String name;
        
        private BpmsActivityTypeEnum(String type, String name) {
            this.type = type;
            this.name = name;
        }
        
        public String getType() {
            return type;
        }
        public void setType(String type) {
            this.type = type;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    

    浏览器直接发送以下格式请求,就可以查看实时流程图:

    # traceprocess 后面追加流程ID
    http://localhost:8080/traceprocess/20190214
    
  • 相关阅读:
    学习笔记之pandas
    学习笔记之Nearest-Neighbour Searching with PostGIS
    学习笔记之Gurobi
    python基础之装饰器
    python作业
    python的位置参数、默认参数、关键字参数、可变参数区别
    python文件处理
    python基础之文件处理
    python基础之条件和循环
    python基础之函数
  • 原文地址:https://www.cnblogs.com/smallSevens/p/10403312.html
Copyright © 2011-2022 走看看