基于Activiti的简单流程历史图形展示

以前采用jbpm编写流程,后来决定采用activiti在新系统中进行流程实现,所以重新编写了流程历史图形展示


[list=1]
  • 首先需要获取流程定义图
  • ByteArrayOutputStream os = new ByteArrayOutputStream();
    InputStream is = getProcessEngine().getRepositoryService().getProcessDiagram(processDefinitionId);
    
    try {
    	new BASE64Encoder().encode(is, os);
    	is.close();
    } catch (Exception e) {
    	;
    }
    
    String image = os.toString();
    

    将image缓存起来备用

  • 读取流程定义信息,获取流程节点信息
  • 基于BPMN2.0的Activiti流程图定义是以xml形式记录的,内容中不仅保存了流程信息,还保存了流程图示信息,我们可以解析流程图示信息,用于之后流程节点的展示
    我们定义如下的流程图
    基于Activiti的简单流程历史图形展示_第1张图片
    它的xml定义为
    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
    	xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
    	expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
    	<process id="process1" name="process1">
    		<startEvent id="startevent1" name="Start"></startEvent>
    		<endEvent id="endevent1" name="End"></endEvent>
    		<userTask id="usertask1" name="User Task1"></userTask>
    		<sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    		<sequenceFlow id="flow2" name="" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    		<userTask id="usertask2" name="User Task2"></userTask>
    		<sequenceFlow id="flow3" name="" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>
    	</process>
    	<bpmndi:BPMNDiagram id="BPMNDiagram_process1">
    		<bpmndi:BPMNPlane bpmnElement="process1" id="BPMNPlane_process1">
    			<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
    				<omgdc:Bounds height="35" width="35" x="70" y="20"></omgdc:Bounds>
    			</bpmndi:BPMNShape>
    			<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
    				<omgdc:Bounds height="35" width="35" x="70" y="260"></omgdc:Bounds>
    			</bpmndi:BPMNShape>
    			<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
    				<omgdc:Bounds height="55" width="105" x="35" y="90"></omgdc:Bounds>
    			</bpmndi:BPMNShape>
    			<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
    				<omgdc:Bounds height="55" width="105" x="35" y="170"></omgdc:Bounds>
    			</bpmndi:BPMNShape>
    			<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
    				<omgdi:waypoint x="87" y="55"></omgdi:waypoint>
    				<omgdi:waypoint x="87" y="90"></omgdi:waypoint>
    			</bpmndi:BPMNEdge>
    			<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
    				<omgdi:waypoint x="87" y="145"></omgdi:waypoint>
    				<omgdi:waypoint x="87" y="170"></omgdi:waypoint>
    			</bpmndi:BPMNEdge>
    			<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
    				<omgdi:waypoint x="87" y="225"></omgdi:waypoint>
    				<omgdi:waypoint x="87" y="260"></omgdi:waypoint>
    			</bpmndi:BPMNEdge>
    		</bpmndi:BPMNPlane>
    	</bpmndi:BPMNDiagram>
    </definitions>
    

    其中bpmndi:BPMNDiagram记录了流程图示信息,bpmndi:BPMNShape记录节点,omgdc:Bounds记录节点的位置和大小信息,我们只需要通过sax解析该xml文件,即可获得节点图示信息
    
    InputStream is = getProcessEngine().getRepositoryService().getProcessModel(processDefinitionId);
    try {
    	SAXParserFactory.newInstance().newSAXParser().parse(is, new DefaultHandler() {
    		@Override
    		public void startElement(String uri, String localName, String qName, Attributes attributes)
    				throws SAXException {
    			switch (qName) {
    			case SHAPE:
    				n = attributes.getValue(SHAPE_NAME);
    				ds = new Double[4];
    				break;
    			case BOUND:
    				if (ds != null) {
    					ds[0] = Double.parseDouble(attributes.getValue("x"));
    					ds[1] = Double.parseDouble(attributes.getValue("y"));
    					ds[2] = Double.parseDouble(attributes.getValue("width"));
    					ds[3] = Double.parseDouble(attributes.getValue("height"));
    				}
    				break;
    			default:
    			}
    		}
    
    		@Override
    		public void endElement(String uri, String localName, String qName) throws SAXException {
    			if (qName.equals(SHAPE)) {
    				// TODO 存储节点图示信息
    				// k = processDefinitionId + n
    				// v = ds
    				n = null;
    				ds = null;
    			}
    		}
    
    		private static final String SHAPE = "bpmndi:BPMNShape";
    		private static final String SHAPE_NAME = "bpmnElement";
    		private static final String BOUND = "omgdc:Bounds";
    		private String n;
    		private Double[] ds;
    	});
    } catch (Exception e) {
    	e.printStackTrace();
    }
    

    在代码的TODO部分,将节点图示信息缓存起来备用

  • 展示流程运行情况
  • 通过activiti api获取历史审核情况
    HistoricTaskInstanceQuery taskQuery = getProcessEngine().getHistoryService().createHistoricTaskInstanceQuery();
    taskQuery.processInstanceId(processInstanceId);
    List<HistoricTaskInstance> list = taskQuery.list();
    for (HistoricTaskInstance taskInstance : list) {
    	Double[] shape = getShape(processDefinitionId, taskInstance.getTaskDefinitionKey()); // TODO 从缓存获取节点图示信息
    	taskInstance.getAssignee();
    	taskInstance.getStartTime();
    	taskInstance.getEndTime();
    }
    

    在代码的TODO部分,从缓存获取节点图示信息;
    并且可以从taskInstance获取节点审核相关信息,这些信息就可以用于在页面上通过html进行展示

    页面上,由于流程定义图已经以base64编码,所以可以直接用 展示,而审核历史节点,则采用<div style="left:px,top:px,width:px,height:px"></div>以position:absolute;展示在流程定义图上
    由于流程图上的节点可能有圆角,所以css上还需要加上radius来展示

    实际使用效果如图
    基于Activiti的简单流程历史图形展示_第2张图片

  • 我们还可以
  • 除了审核历史节点,还可以通过taskquery查询等待审核的节点,以不同的效果展现
    我们还可以在鼠标放到节点上的时候,展示节点的审核信息,如审核人、审核时间、审核意见和办结花费时间等
    由于流程审核过程可能比较复杂,所以还可以作一个过程展示,按审核顺序依次加亮审核节点,用于过程展示

    基于Activiti的简单流程历史图形展示_第3张图片

    [/list]

    你可能感兴趣的:(java,xml,Activiti,bpmn,apage)