本文將介紹怎麼在本身的系統內顯示activiti的流程圖,示例代碼是從官方demo裏提取的一部分流程圖展現的代碼,這裏是結合springmvc來實現的,你們能夠從官方代碼裏提取,也能夠參照本博文來直接使用。javascript
一、代碼目錄結構html
二、代碼詳情前端
JacksonConfiguration.javajava
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.fasterxml.jackson.databind.ObjectMapper; /** * @author Joram Barrez */ @Configuration public class JacksonConfiguration { @Bean() public ObjectMapper objectMapper() { // To avoid instantiating and configuring the mapper everywhere ObjectMapper mapper = new ObjectMapper(); return mapper; } }
BaseProcessDefinitionDiagramLayoutResource.javanode
import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiObjectNotFoundException; import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.impl.bpmn.behavior.BoundaryEventActivityBehavior; import org.activiti.engine.impl.bpmn.behavior.CallActivityBehavior; import org.activiti.engine.impl.bpmn.parser.BpmnParse; import org.activiti.engine.impl.bpmn.parser.ErrorEventDefinition; import org.activiti.engine.impl.bpmn.parser.EventSubscriptionDeclaration; import org.activiti.engine.impl.jobexecutor.TimerDeclarationImpl; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.PvmTransition; import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.pvm.process.Lane; import org.activiti.engine.impl.pvm.process.LaneSet; import org.activiti.engine.impl.pvm.process.ParticipantProcess; import org.activiti.engine.impl.pvm.process.TransitionImpl; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.Execution; import org.activiti.engine.runtime.ProcessInstance; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; public class BaseProcessDefinitionDiagramLayoutResource { @Autowired private RuntimeService runtimeService; @Autowired private RepositoryService repositoryService; @Autowired private HistoryService historyService; public ObjectNode getDiagramNode(String processInstanceId, String processDefinitionId) { List<String> highLightedFlows = Collections.<String> emptyList(); List<String> highLightedActivities = Collections.<String> emptyList(); Map<String, ObjectNode> subProcessInstanceMap = new HashMap<String, ObjectNode>(); ProcessInstance processInstance = null; if (processInstanceId != null) { processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId) .singleResult(); if (processInstance == null) { throw new ActivitiObjectNotFoundException("Process instance could not be found"); } processDefinitionId = processInstance.getProcessDefinitionId(); List<ProcessInstance> subProcessInstances = runtimeService.createProcessInstanceQuery() .superProcessInstanceId(processInstanceId).list(); for (ProcessInstance subProcessInstance : subProcessInstances) { String subDefId = subProcessInstance.getProcessDefinitionId(); String superExecutionId = ((ExecutionEntity) subProcessInstance).getSuperExecutionId(); ProcessDefinitionEntity subDef = (ProcessDefinitionEntity) repositoryService .getProcessDefinition(subDefId); ObjectNode processInstanceJSON = new ObjectMapper().createObjectNode(); processInstanceJSON.put("processInstanceId", subProcessInstance.getId()); processInstanceJSON.put("superExecutionId", superExecutionId); processInstanceJSON.put("processDefinitionId", subDef.getId()); processInstanceJSON.put("processDefinitionKey", subDef.getKey()); processInstanceJSON.put("processDefinitionName", subDef.getName()); subProcessInstanceMap.put(superExecutionId, processInstanceJSON); } } if (processDefinitionId == null) { throw new ActivitiObjectNotFoundException("No process definition id provided"); } ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService .getProcessDefinition(processDefinitionId); if (processDefinition == null) { throw new ActivitiException("Process definition " + processDefinitionId + " could not be found"); } ObjectNode responseJSON = new ObjectMapper().createObjectNode(); // Process definition JsonNode pdrJSON = getProcessDefinitionResponse(processDefinition); if (pdrJSON != null) { responseJSON.put("processDefinition", pdrJSON); } // Highlighted activities if (processInstance != null) { ArrayNode activityArray = new ObjectMapper().createArrayNode(); ArrayNode flowsArray = new ObjectMapper().createArrayNode(); highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId); highLightedFlows = getHighLightedFlows(processInstanceId, processDefinition); for (String activityName : highLightedActivities) { activityArray.add(activityName); } for (String flow : highLightedFlows) flowsArray.add(flow); responseJSON.put("highLightedActivities", activityArray); responseJSON.put("highLightedFlows", flowsArray); } // Pool shape, if process is participant in collaboration if (processDefinition.getParticipantProcess() != null) { ParticipantProcess pProc = processDefinition.getParticipantProcess(); ObjectNode participantProcessJSON = new ObjectMapper().createObjectNode(); participantProcessJSON.put("id", pProc.getId()); if (StringUtils.isNotEmpty(pProc.getName())) { participantProcessJSON.put("name", pProc.getName()); } else { participantProcessJSON.put("name", ""); } participantProcessJSON.put("x", pProc.getX()); participantProcessJSON.put("y", pProc.getY()); participantProcessJSON.put("width", pProc.getWidth()); participantProcessJSON.put("height", pProc.getHeight()); responseJSON.put("participantProcess", participantProcessJSON); } // Draw lanes if (processDefinition.getLaneSets() != null && !processDefinition.getLaneSets().isEmpty()) { ArrayNode laneSetArray = new ObjectMapper().createArrayNode(); for (LaneSet laneSet : processDefinition.getLaneSets()) { ArrayNode laneArray = new ObjectMapper().createArrayNode(); if (laneSet.getLanes() != null && !laneSet.getLanes().isEmpty()) { for (Lane lane : laneSet.getLanes()) { ObjectNode laneJSON = new ObjectMapper().createObjectNode(); laneJSON.put("id", lane.getId()); if (StringUtils.isNotEmpty(lane.getName())) { laneJSON.put("name", lane.getName()); } else { laneJSON.put("name", ""); } laneJSON.put("x", lane.getX()); laneJSON.put("y", lane.getY()); laneJSON.put("width", lane.getWidth()); laneJSON.put("height", lane.getHeight()); List<String> flowNodeIds = lane.getFlowNodeIds(); ArrayNode flowNodeIdsArray = new ObjectMapper().createArrayNode(); for (String flowNodeId : flowNodeIds) { flowNodeIdsArray.add(flowNodeId); } laneJSON.put("flowNodeIds", flowNodeIdsArray); laneArray.add(laneJSON); } } ObjectNode laneSetJSON = new ObjectMapper().createObjectNode(); laneSetJSON.put("id", laneSet.getId()); if (StringUtils.isNotEmpty(laneSet.getName())) { laneSetJSON.put("name", laneSet.getName()); } else { laneSetJSON.put("name", ""); } laneSetJSON.put("lanes", laneArray); laneSetArray.add(laneSetJSON); } if (laneSetArray.size() > 0) responseJSON.put("laneSets", laneSetArray); } ArrayNode sequenceFlowArray = new ObjectMapper().createArrayNode(); ArrayNode activityArray = new ObjectMapper().createArrayNode(); // Activities and their sequence-flows for (ActivityImpl activity : processDefinition.getActivities()) { getActivity(processInstanceId, activity, activityArray, sequenceFlowArray, processInstance, highLightedFlows, subProcessInstanceMap); } responseJSON.put("activities", activityArray); responseJSON.put("sequenceFlows", sequenceFlowArray); return responseJSON; } private List<String> getHighLightedFlows(String processInstanceId, ProcessDefinitionEntity processDefinition) { List<String> highLightedFlows = new ArrayList<String>(); List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list(); List<String> historicActivityInstanceList = new ArrayList<String>(); for (HistoricActivityInstance hai : historicActivityInstances) { historicActivityInstanceList.add(hai.getActivityId()); } // add current activities to list List<String> highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId); historicActivityInstanceList.addAll(highLightedActivities); // activities and their sequence-flows for (ActivityImpl activity : processDefinition.getActivities()) { int index = historicActivityInstanceList.indexOf(activity.getId()); if (index >= 0 && index + 1 < historicActivityInstanceList.size()) { List<PvmTransition> pvmTransitionList = activity.getOutgoingTransitions(); for (PvmTransition pvmTransition : pvmTransitionList) { String destinationFlowId = pvmTransition.getDestination().getId(); if (destinationFlowId.equals(historicActivityInstanceList.get(index + 1))) { highLightedFlows.add(pvmTransition.getId()); } } } } return highLightedFlows; } @SuppressWarnings("unchecked") private void getActivity(String processInstanceId, ActivityImpl activity, ArrayNode activityArray, ArrayNode sequenceFlowArray, ProcessInstance processInstance, List<String> highLightedFlows, Map<String, ObjectNode> subProcessInstanceMap) { ObjectNode activityJSON = new ObjectMapper().createObjectNode(); // Gather info on the multi instance marker String multiInstance = (String) activity.getProperty("multiInstance"); if (multiInstance != null) { if (!"sequential".equals(multiInstance)) { multiInstance = "parallel"; } } ActivityBehavior activityBehavior = activity.getActivityBehavior(); // Gather info on the collapsed marker Boolean collapsed = (activityBehavior instanceof CallActivityBehavior); Boolean expanded = (Boolean) activity.getProperty(BpmnParse.PROPERTYNAME_ISEXPANDED); if (expanded != null) { collapsed = !expanded; } Boolean isInterrupting = null; if (activityBehavior instanceof BoundaryEventActivityBehavior) { isInterrupting = ((BoundaryEventActivityBehavior) activityBehavior).isInterrupting(); } // Outgoing transitions of activity for (PvmTransition sequenceFlow : activity.getOutgoingTransitions()) { String flowName = (String) sequenceFlow.getProperty("name"); boolean isHighLighted = (highLightedFlows.contains(sequenceFlow.getId())); boolean isConditional = sequenceFlow.getProperty(BpmnParse.PROPERTYNAME_CONDITION) != null && !((String) activity.getProperty("type")).toLowerCase().contains("gateway"); boolean isDefault = sequenceFlow.getId().equals(activity.getProperty("default")) && ((String) activity.getProperty("type")).toLowerCase().contains("gateway"); List<Integer> waypoints = ((TransitionImpl) sequenceFlow).getWaypoints(); ArrayNode xPointArray = new ObjectMapper().createArrayNode(); ArrayNode yPointArray = new ObjectMapper().createArrayNode(); for (int i = 0; i < waypoints.size(); i += 2) { // waypoints.size() // minimally 4: x1, y1, // x2, y2 xPointArray.add(waypoints.get(i)); yPointArray.add(waypoints.get(i + 1)); } ObjectNode flowJSON = new ObjectMapper().createObjectNode(); flowJSON.put("id", sequenceFlow.getId()); flowJSON.put("name", flowName); flowJSON.put("flow", "(" + sequenceFlow.getSource().getId() + ")--" + sequenceFlow.getId() + "-->(" + sequenceFlow.getDestination().getId() + ")"); if (isConditional) flowJSON.put("isConditional", isConditional); if (isDefault) flowJSON.put("isDefault", isDefault); if (isHighLighted) flowJSON.put("isHighLighted", isHighLighted); flowJSON.put("xPointArray", xPointArray); flowJSON.put("yPointArray", yPointArray); sequenceFlowArray.add(flowJSON); } // Nested activities (boundary events) ArrayNode nestedActivityArray = new ObjectMapper().createArrayNode(); for (ActivityImpl nestedActivity : activity.getActivities()) { nestedActivityArray.add(nestedActivity.getId()); } Map<String, Object> properties = activity.getProperties(); ObjectNode propertiesJSON = new ObjectMapper().createObjectNode(); for (String key : properties.keySet()) { Object prop = properties.get(key); if (prop instanceof String) propertiesJSON.put(key, (String) properties.get(key)); else if (prop instanceof Integer) propertiesJSON.put(key, (Integer) properties.get(key)); else if (prop instanceof Boolean) propertiesJSON.put(key, (Boolean) properties.get(key)); else if ("initial".equals(key)) { ActivityImpl act = (ActivityImpl) properties.get(key); propertiesJSON.put(key, act.getId()); } else if ("timerDeclarations".equals(key)) { ArrayList<TimerDeclarationImpl> timerDeclarations = (ArrayList<TimerDeclarationImpl>) properties .get(key); ArrayNode timerDeclarationArray = new ObjectMapper().createArrayNode(); if (timerDeclarations != null) for (TimerDeclarationImpl timerDeclaration : timerDeclarations) { ObjectNode timerDeclarationJSON = new ObjectMapper().createObjectNode(); timerDeclarationJSON.put("isExclusive", timerDeclaration.isExclusive()); if (timerDeclaration.getRepeat() != null) timerDeclarationJSON.put("repeat", timerDeclaration.getRepeat()); timerDeclarationJSON.put("retries", String.valueOf(timerDeclaration.getRetries())); timerDeclarationJSON.put("type", timerDeclaration.getJobHandlerType()); timerDeclarationJSON.put("configuration", timerDeclaration.getJobHandlerConfiguration()); // timerDeclarationJSON.put("expression", // timerDeclaration.getDescription()); timerDeclarationArray.add(timerDeclarationJSON); } if (timerDeclarationArray.size() > 0) propertiesJSON.put(key, timerDeclarationArray); // TODO: implement getting description } else if ("eventDefinitions".equals(key)) { ArrayList<EventSubscriptionDeclaration> eventDefinitions = (ArrayList<EventSubscriptionDeclaration>) properties .get(key); ArrayNode eventDefinitionsArray = new ObjectMapper().createArrayNode(); if (eventDefinitions != null) { for (EventSubscriptionDeclaration eventDefinition : eventDefinitions) { ObjectNode eventDefinitionJSON = new ObjectMapper().createObjectNode(); if (eventDefinition.getActivityId() != null) eventDefinitionJSON.put("activityId", eventDefinition.getActivityId()); eventDefinitionJSON.put("eventName", eventDefinition.getEventName()); eventDefinitionJSON.put("eventType", eventDefinition.getEventType()); eventDefinitionJSON.put("isAsync", eventDefinition.isAsync()); eventDefinitionJSON.put("isStartEvent", eventDefinition.isStartEvent()); eventDefinitionsArray.add(eventDefinitionJSON); } } if (eventDefinitionsArray.size() > 0) propertiesJSON.put(key, eventDefinitionsArray); // TODO: implement it } else if ("errorEventDefinitions".equals(key)) { ArrayList<ErrorEventDefinition> errorEventDefinitions = (ArrayList<ErrorEventDefinition>) properties .get(key); ArrayNode errorEventDefinitionsArray = new ObjectMapper().createArrayNode(); if (errorEventDefinitions != null) { for (ErrorEventDefinition errorEventDefinition : errorEventDefinitions) { ObjectNode errorEventDefinitionJSON = new ObjectMapper().createObjectNode(); if (errorEventDefinition.getErrorCode() != null) errorEventDefinitionJSON.put("errorCode", errorEventDefinition.getErrorCode()); else errorEventDefinitionJSON.putNull("errorCode"); errorEventDefinitionJSON.put("handlerActivityId", errorEventDefinition.getHandlerActivityId()); errorEventDefinitionsArray.add(errorEventDefinitionJSON); } } if (errorEventDefinitionsArray.size() > 0) propertiesJSON.put(key, errorEventDefinitionsArray); } } if ("callActivity".equals(properties.get("type"))) { CallActivityBehavior callActivityBehavior = null; if (activityBehavior instanceof CallActivityBehavior) { callActivityBehavior = (CallActivityBehavior) activityBehavior; } if (callActivityBehavior != null) { propertiesJSON.put("processDefinitonKey", callActivityBehavior.getProcessDefinitonKey()); // get processDefinitonId from execution or get last // processDefinitonId // by key ArrayNode processInstanceArray = new ObjectMapper().createArrayNode(); if (processInstance != null) { List<Execution> executionList = runtimeService.createExecutionQuery() .processInstanceId(processInstanceId).activityId(activity.getId()).list(); if (!executionList.isEmpty()) { for (Execution execution : executionList) { ObjectNode processInstanceJSON = subProcessInstanceMap.get(execution.getId()); processInstanceArray.add(processInstanceJSON); } } } // If active activities nas no instance of this callActivity // then add // last definition if (processInstanceArray.size() == 0 && StringUtils.isNotEmpty(callActivityBehavior.getProcessDefinitonKey())) { // Get last definition by key ProcessDefinition lastProcessDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionKey(callActivityBehavior.getProcessDefinitonKey()).latestVersion() .singleResult(); if (lastProcessDefinition != null) { ObjectNode processInstanceJSON = new ObjectMapper().createObjectNode(); processInstanceJSON.put("processDefinitionId", lastProcessDefinition.getId()); processInstanceJSON.put("processDefinitionKey", lastProcessDefinition.getKey()); processInstanceJSON.put("processDefinitionName", lastProcessDefinition.getName()); processInstanceArray.add(processInstanceJSON); } } if (processInstanceArray.size() > 0) { propertiesJSON.put("processDefinitons", processInstanceArray); } } } activityJSON.put("activityId", activity.getId()); activityJSON.put("properties", propertiesJSON); if (multiInstance != null) activityJSON.put("multiInstance", multiInstance); if (collapsed) activityJSON.put("collapsed", collapsed); if (nestedActivityArray.size() > 0) activityJSON.put("nestedActivities", nestedActivityArray); if (isInterrupting != null) activityJSON.put("isInterrupting", isInterrupting); activityJSON.put("x", activity.getX()); activityJSON.put("y", activity.getY()); activityJSON.put("width", activity.getWidth()); activityJSON.put("height", activity.getHeight()); activityArray.add(activityJSON); // Nested activities (boundary events) for (ActivityImpl nestedActivity : activity.getActivities()) { getActivity(processInstanceId, nestedActivity, activityArray, sequenceFlowArray, processInstance, highLightedFlows, subProcessInstanceMap); } } private JsonNode getProcessDefinitionResponse(ProcessDefinitionEntity processDefinition) { ObjectMapper mapper = new ObjectMapper(); ObjectNode pdrJSON = mapper.createObjectNode(); pdrJSON.put("id", processDefinition.getId()); pdrJSON.put("name", processDefinition.getName()); pdrJSON.put("key", processDefinition.getKey()); pdrJSON.put("version", processDefinition.getVersion()); pdrJSON.put("deploymentId", processDefinition.getDeploymentId()); pdrJSON.put("isGraphicNotationDefined", isGraphicNotationDefined(processDefinition)); return pdrJSON; } private boolean isGraphicNotationDefined(ProcessDefinitionEntity processDefinition) { return ((ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinition.getId())) .isGraphicalNotationDefined(); } }
ProcessInstanceDiagramLayoutResource.javaweb
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.fasterxml.jackson.databind.node.ObjectNode; @RestController public class ProcessInstanceDiagramLayoutResource extends BaseProcessDefinitionDiagramLayoutResource { @RequestMapping(value = "/process-instance/diagram-layout.do", method = RequestMethod.GET, produces = "application/json") public ObjectNode getDiagram(@RequestParam("processInstanceId") String processInstanceId) { return getDiagramNode(processInstanceId, null); } }
ProcessInstanceHighlightsResource.javaspring
import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.PvmTransition; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.runtime.ProcessInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @RestController public class ProcessInstanceHighlightsResource { @Autowired private RuntimeService runtimeService; @Autowired private RepositoryService repositoryService; @Autowired private HistoryService historyService; protected ObjectMapper objectMapper = new ObjectMapper(); @RequestMapping(value = "/process-instance/highlights.do", method = RequestMethod.GET, produces = "application/json") public ObjectNode getHighlighted(@RequestParam("processInstanceId") String processInstanceId) { ObjectNode responseJSON = objectMapper.createObjectNode(); responseJSON.put("processInstanceId", processInstanceId); ArrayNode activitiesArray = objectMapper.createArrayNode(); ArrayNode flowsArray = objectMapper.createArrayNode(); try { ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId(processInstanceId).singleResult(); ProcessDefinitionEntity processDefinition = new ProcessDefinitionEntity(); if (null == processInstance) { HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() .processInstanceId(processInstanceId).singleResult(); processDefinition = (ProcessDefinitionEntity) repositoryService .getProcessDefinition(historicProcessInstance.getProcessDefinitionId()); responseJSON.put("processDefinitionId", historicProcessInstance.getProcessDefinitionId()); List<HistoricActivityInstance> historicActivityInstances = historyService .createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list(); for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { activitiesArray.add(historicActivityInstance.getActivityId()); } } else { processDefinition = (ProcessDefinitionEntity) repositoryService .getProcessDefinition(processInstance.getProcessDefinitionId()); responseJSON.put("processDefinitionId", processInstance.getProcessDefinitionId()); List<String> highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId); for (String activityId : highLightedActivities) { activitiesArray.add(activityId); } } List<String> highLightedFlows = getHighLightedFlows(processDefinition, processInstanceId); for (String flow : highLightedFlows) { flowsArray.add(flow); } } catch (Exception e) { e.printStackTrace(); } responseJSON.put("activities", activitiesArray); responseJSON.put("flows", flowsArray); return responseJSON; } /** * getHighLightedFlows * * @param processDefinition * @param processInstanceId * @return */ private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinition, String processInstanceId) { List<String> highLightedFlows = new ArrayList<String>(); List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) // order by startime asc is not correct. use default order is // correct. // .orderByHistoricActivityInstanceStartTime().asc()/*.orderByActivityId().asc()*/ .list(); LinkedList<HistoricActivityInstance> hisActInstList = new LinkedList<HistoricActivityInstance>(); hisActInstList.addAll(historicActivityInstances); getHighlightedFlows(processDefinition.getActivities(), hisActInstList, highLightedFlows); return highLightedFlows; } /** * getHighlightedFlows code logic: 1. Loop all activities by id asc order; * 2. Check each activity's outgoing transitions and eventBoundery outgoing * transitions, if outgoing transitions's destination.id is in other * executed activityIds, add this transition to highLightedFlows List; 3. * But if activity is not a parallelGateway or inclusiveGateway, only choose * the earliest flow. * * @param activityList * @param hisActInstList * @param highLightedFlows */ private void getHighlightedFlows(List<ActivityImpl> activityList, LinkedList<HistoricActivityInstance> hisActInstList, List<String> highLightedFlows) { // check out startEvents in activityList List<ActivityImpl> startEventActList = new ArrayList<ActivityImpl>(); Map<String, ActivityImpl> activityMap = new HashMap<String, ActivityImpl>(activityList.size()); for (ActivityImpl activity : activityList) { activityMap.put(activity.getId(), activity); String actType = (String) activity.getProperty("type"); if (actType != null && actType.toLowerCase().indexOf("startevent") >= 0) { startEventActList.add(activity); } } // These codes is used to avoid a bug: // ACT-1728 If the process instance was started by a callActivity, it // will be not have the startEvent activity in ACT_HI_ACTINST table // Code logic: // Check the first activity if it is a startEvent, if not check out the // startEvent's highlight outgoing flow. HistoricActivityInstance firstHistActInst = hisActInstList.getFirst(); String firstActType = (String) firstHistActInst.getActivityType(); if (firstActType != null && firstActType.toLowerCase().indexOf("startevent") < 0) { PvmTransition startTrans = getStartTransaction(startEventActList, firstHistActInst); if (startTrans != null) { highLightedFlows.add(startTrans.getId()); } } while (!hisActInstList.isEmpty()) { HistoricActivityInstance histActInst = hisActInstList.removeFirst(); ActivityImpl activity = activityMap.get(histActInst.getActivityId()); if (activity != null) { boolean isParallel = false; String type = histActInst.getActivityType(); if ("parallelGateway".equals(type) || "inclusiveGateway".equals(type)) { isParallel = true; } else if ("subProcess".equals(histActInst.getActivityType())) { getHighlightedFlows(activity.getActivities(), hisActInstList, highLightedFlows); } List<PvmTransition> allOutgoingTrans = new ArrayList<PvmTransition>(); allOutgoingTrans.addAll(activity.getOutgoingTransitions()); allOutgoingTrans.addAll(getBoundaryEventOutgoingTransitions(activity)); List<String> activityHighLightedFlowIds = getHighlightedFlows(allOutgoingTrans, hisActInstList, isParallel); highLightedFlows.addAll(activityHighLightedFlowIds); } } } /** * Check out the outgoing transition connected to firstActInst from * startEventActList * * @param startEventActList * @param firstActInst * @return */ private PvmTransition getStartTransaction(List<ActivityImpl> startEventActList, HistoricActivityInstance firstActInst) { for (ActivityImpl startEventAct : startEventActList) { for (PvmTransition trans : startEventAct.getOutgoingTransitions()) { if (trans.getDestination().getId().equals(firstActInst.getActivityId())) { return trans; } } } return null; } /** * getBoundaryEventOutgoingTransitions * * @param activity * @return */ private List<PvmTransition> getBoundaryEventOutgoingTransitions(ActivityImpl activity) { List<PvmTransition> boundaryTrans = new ArrayList<PvmTransition>(); for (ActivityImpl subActivity : activity.getActivities()) { String type = (String) subActivity.getProperty("type"); if (type != null && type.toLowerCase().indexOf("boundary") >= 0) { boundaryTrans.addAll(subActivity.getOutgoingTransitions()); } } return boundaryTrans; } /** * find out single activity's highlighted flowIds * * @param activity * @param hisActInstList * @param isExclusive if true only return one flowId(Such as * exclusiveGateway, BoundaryEvent On Task) * @return */ private List<String> getHighlightedFlows(List<PvmTransition> pvmTransitionList, LinkedList<HistoricActivityInstance> hisActInstList, boolean isParallel) { List<String> highLightedFlowIds = new ArrayList<String>(); PvmTransition earliestTrans = null; HistoricActivityInstance earliestHisActInst = null; for (PvmTransition pvmTransition : pvmTransitionList) { String destActId = pvmTransition.getDestination().getId(); HistoricActivityInstance destHisActInst = findHisActInst(hisActInstList, destActId); if (destHisActInst != null) { if (isParallel) { highLightedFlowIds.add(pvmTransition.getId()); } else if (earliestHisActInst == null || (earliestHisActInst.getId().compareTo(destHisActInst.getId()) > 0)) { earliestTrans = pvmTransition; earliestHisActInst = destHisActInst; } } } if ((!isParallel) && earliestTrans != null) { highLightedFlowIds.add(earliestTrans.getId()); } return highLightedFlowIds; } private HistoricActivityInstance findHisActInst(LinkedList<HistoricActivityInstance> hisActInstList, String actId) { for (HistoricActivityInstance hisActInst : hisActInstList) { if (hisActInst.getActivityId().equals(actId)) { return hisActInst; } } return null; } }
DispatcherServletConfiguration.javaexpress
import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.i18n.SessionLocaleResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import com.fasterxml.jackson.databind.ObjectMapper; @Configuration @ComponentScan({ "org.activiti.rest.editor", "org.activiti.rest.diagram" }) @EnableAsync public class DispatcherServletConfiguration extends WebMvcConfigurationSupport { private final Logger log = LoggerFactory.getLogger(DispatcherServletConfiguration.class); @Autowired private ObjectMapper objectMapper; @Autowired private Environment environment; @Bean public SessionLocaleResolver localeResolver() { return new SessionLocaleResolver(); } @Bean public LocaleChangeInterceptor localeChangeInterceptor() { log.debug("Configuring localeChangeInterceptor"); LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); localeChangeInterceptor.setParamName("language"); return localeChangeInterceptor; } @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { log.debug("Creating requestMappingHandlerMapping"); RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping(); requestMappingHandlerMapping.setUseSuffixPatternMatch(false); Object[] interceptors = { localeChangeInterceptor() }; requestMappingHandlerMapping.setInterceptors(interceptors); return requestMappingHandlerMapping; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { addDefaultHttpMessageConverters(converters); for (HttpMessageConverter<?> converter : converters) { if (converter instanceof MappingJackson2HttpMessageConverter) { MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter; jackson2HttpMessageConverter.setObjectMapper(objectMapper); break; } } } @Override protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); } }
FilterServletOutputStream.javaapache
import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletOutputStream; import javax.servlet.WriteListener; public class FilterServletOutputStream extends ServletOutputStream { private DataOutputStream stream; //private WriteListener writeListener; public FilterServletOutputStream(OutputStream output) { stream = new DataOutputStream(output); } public void write(int b) throws IOException { stream.write(b); } public void write(byte[] b) throws IOException { stream.write(b); } public void write(byte[] b, int off, int len) throws IOException { stream.write(b, off, len); } @Override public void setWriteListener(WriteListener writeListener) { //this.writeListener = writeListener; } @Override public boolean isReady() { return true; } }
GenericResponseWrapper.javajson
import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class GenericResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream output; private int contentLength; private String contentType; public GenericResponseWrapper(HttpServletResponse response) { super(response); output = new ByteArrayOutputStream(); } public byte[] getData() { return output.toByteArray(); } public ServletOutputStream getOutputStream() { return new FilterServletOutputStream(output); } public PrintWriter getWriter() { return new PrintWriter(getOutputStream(), true); } public void setContentLength(int length) { this.contentLength = length; super.setContentLength(length); } public int getContentLength() { return contentLength; } public void setContentType(String type) { this.contentType = type; super.setContentType(type); } public String getContentType() { return contentType; } }
JsonpCallbackFilter.java
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JsonpCallbackFilter implements Filter { private static Logger log = LoggerFactory.getLogger(JsonpCallbackFilter.class); public void init(FilterConfig fConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; Map<String, String[]> parms = httpRequest.getParameterMap(); if (parms.containsKey("callback")) { if (log.isDebugEnabled()) log.debug("Wrapping response with JSONP callback '" + parms.get("callback")[0] + "'"); OutputStream out = httpResponse.getOutputStream(); GenericResponseWrapper wrapper = new GenericResponseWrapper(httpResponse); chain.doFilter(request, wrapper); // handles the content-size truncation ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); outputStream.write(new String(parms.get("callback")[0] + "(").getBytes()); outputStream.write(wrapper.getData()); outputStream.write(new String(");").getBytes()); byte jsonpResponse[] = outputStream.toByteArray(); wrapper.setContentType("text/javascript;charset=UTF-8"); wrapper.setContentLength(jsonpResponse.length); out.write(jsonpResponse); out.close(); } else { chain.doFilter(request, response); } } public void destroy() { } }
3,前端頁面
這個也是從官方demo拷貝出來的,這裏單獨把這個文件夾打包出來,你們也能夠從官方demo裏提取。
4,如何顯示
訪問:http://localhost:8080/demo/diagram-viewer/index.html?processDefinitionId=project_approve:123:317507&processInstanceId=325001
其中對應的參數填寫本身的流程定義ID和實例ID
5,顯示效果