1. 程式人生 > >Activiti工作流之獲取流程定義中所有的節點

Activiti工作流之獲取流程定義中所有的節點

初步設想實現一個部署完工作流之後,為UserTask節點動態分配任務執行者,或者在分支節點上新增進入條件的功能。為了實現這個功能需要解析流程定義檔案取出檔案中定義的所有節點。這裡有兩個方法可以實現此功能。

方法一(流程部署至伺服器上之後可使用):

//<span style="font-family: Arial, Helvetica, sans-serif;">processDefinitionId</span><span style="font-family: Arial, Helvetica, sans-serif;">    為流程定義Id,該Id可以通過多種方式獲得,如通過ProcessDefinitionQuery可以查詢一個ProcessDefinition物件,Task物件中也包含</span><span style="font-family: Arial, Helvetica, sans-serif;">processDefinitionId</span><span style="font-family: Arial, Helvetica, sans-serif;"> </span>
BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
if(model != null) {
    Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();
    for(FlowElement e : flowElements) {
        System.out.println("flowelement id:" + e.getId() + "  name:" + e.getName() + "   class:" + e.getClass().toString());
    }
}
該方法適用於流程部署至伺服器上之後,通過該方法可以簡單快速的獲取流程定義檔案中各個節點資訊。

方法二 讀取流程定義檔案方式

<pre name="code" class="java">//import java.io.InputStream;
//import java.io.InputStreamReader;
//import javax.xml.stream.XMLInputFactory;
//import javax.xml.stream.XMLStreamException;
//import javax.xml.stream.XMLStreamReader;
//
//import org.activiti.bpmn.converter.BpmnXMLConverter;
//import org.activiti.bpmn.model.BpmnModel;
//import org.activiti.bpmn.model.FlowElement;

InputStream resouceStream = this.getClass().getClassLoader().getResourceAsStream("leave-formkey.bpmn20.xml");
XMLInputFactory xif = XMLInputFactory.newInstance();
InputStreamReader in;
XMLStreamReader xtr;
try {
	in = new InputStreamReader(resouceStream, "UTF-8");
	xtr = xif.createXMLStreamReader(in);
	BpmnModel model = new BpmnXMLConverter().convertToBpmnModel(xtr);
	Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();
	for(FlowElement e : flowElements) {
		System.out.println("flowelement id:" + e.getId() + "  name:" + e.getName() + "   class:" + e.getClass().toString());
	}
} catch (XMLStreamException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
} catch (UnsupportedEncodingException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}
        該方法使用到了activiti的activiti-bpmn-converter-5.20.0.jar和activiti-bpmn-model-5.20.0.jar,用到了其中比較關鍵的一個類BpmnXMLConverter,該類將xml定義檔案解析成BpmnModel物件,使用BpmnModel的getMainProcess()獲取一個Process物件,該物件實際是一個繼承自BaseElement、FlowElementContainer的節點容器,通過getFlowElements()獲取當前流程定義檔案中所有的節點物件。        該方法的好處在於可以解析本地或者未部署至Activiti引擎中的流程定義檔案。

兩次測試列印結果如下:
flowelement id:startevent1  name:Start   class:class org.activiti.bpmn.model.StartEvent
flowelement id:deptLeaderAudit  name:部門領導審批   class:class org.activiti.bpmn.model.UserTask
flowelement id:exclusivegateway5  name:Exclusive Gateway   class:class org.activiti.bpmn.model.ExclusiveGateway
flowelement id:modifyApply  name:調整申請   class:class org.activiti.bpmn.model.UserTask
flowelement id:hrAudit  name:人事審批   class:class org.activiti.bpmn.model.UserTask
flowelement id:exclusivegateway6  name:Exclusive Gateway   class:class org.activiti.bpmn.model.ExclusiveGateway
flowelement id:reportBack  name:銷假   class:class org.activiti.bpmn.model.UserTask
flowelement id:endevent1  name:End   class:class org.activiti.bpmn.model.EndEvent
flowelement id:exclusivegateway7  name:Exclusive Gateway   class:class org.activiti.bpmn.model.ExclusiveGateway
flowelement id:flow2  name:   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow3  name:   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow4  name:不同意   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow5  name:同意   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow6  name:   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow7  name:同意   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow8  name:   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow9  name:不同意   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow10  name:重新申請   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow11  name:   class:class org.activiti.bpmn.model.SequenceFlow
flowelement id:flow12  name:結束流程   class:class org.activiti.bpmn.model.SequenceFlow

流程定義檔案leave-formkey.bpmn20.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="OFFICE">
  <process id="leave-formkey" name="病事假申請">
    <documentation>請假流程演示</documentation>
    <startEvent id="startevent1" name="Start" activiti:initiator="applyUserId"></startEvent>
    <userTask id="deptLeaderAudit" name="部門領導審批" activiti:assignee="${applyUserId}" activiti:formKey="leaveHandle.form"></userTask>
    <exclusiveGateway id="exclusivegateway5" name="Exclusive Gateway"></exclusiveGateway>
    <userTask id="modifyApply" name="調整申請" activiti:assignee="${applyUserId}" activiti:formKey="leaveApplyAgain.form"></userTask>
    <userTask id="hrAudit" name="人事審批" activiti:assignee="${applyUserId}" activiti:formKey="leaveHandle.form"></userTask>
    <exclusiveGateway id="exclusivegateway6" name="Exclusive Gateway"></exclusiveGateway>
    <userTask id="reportBack" name="銷假" activiti:assignee="${applyUserId}" activiti:formKey="leaveHandle.form"></userTask>
    <endEvent id="endevent1" name="End"></endEvent>
    <exclusiveGateway id="exclusivegateway7" name="Exclusive Gateway"></exclusiveGateway>
    <sequenceFlow id="flow2" name="" sourceRef="startevent1" targetRef="deptLeaderAudit"></sequenceFlow>
    <sequenceFlow id="flow3" name="" sourceRef="deptLeaderAudit" targetRef="exclusivegateway5"></sequenceFlow>
    <sequenceFlow id="flow4" name="不同意" sourceRef="exclusivegateway5" targetRef="modifyApply">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderPass == 'false'}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow5" name="同意" sourceRef="exclusivegateway5" targetRef="hrAudit">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${deptLeaderPass == 'true'}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow6" name="" sourceRef="hrAudit" targetRef="exclusivegateway6"></sequenceFlow>
    <sequenceFlow id="flow7" name="同意" sourceRef="exclusivegateway6" targetRef="reportBack">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrPass == 'true'}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow8" name="" sourceRef="reportBack" targetRef="endevent1"></sequenceFlow>
    <sequenceFlow id="flow9" name="不同意" sourceRef="exclusivegateway6" targetRef="modifyApply">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${hrPass == 'false'}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow10" name="重新申請" sourceRef="exclusivegateway7" targetRef="deptLeaderAudit">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${reApply == 'true'}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow11" name="" sourceRef="modifyApply" targetRef="exclusivegateway7"></sequenceFlow>
    <sequenceFlow id="flow12" name="結束流程" sourceRef="exclusivegateway7" targetRef="endevent1">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${reApply == 'false'}]]></conditionExpression>
    </sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_leave-formkey">
    <bpmndi:BPMNPlane bpmnElement="leave-formkey" id="BPMNPlane_leave-formkey">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35" width="35" x="10" y="90"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="deptLeaderAudit" id="BPMNShape_deptLeaderAudit">
        <omgdc:Bounds height="55" width="105" x="90" y="80"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="exclusivegateway5" id="BPMNShape_exclusivegateway5">
        <omgdc:Bounds height="40" width="40" x="250" y="87"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="modifyApply" id="BPMNShape_modifyApply">
        <omgdc:Bounds height="55" width="105" x="218" y="190"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="hrAudit" id="BPMNShape_hrAudit">
        <omgdc:Bounds height="55" width="105" x="358" y="80"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="exclusivegateway6" id="BPMNShape_exclusivegateway6">
        <omgdc:Bounds height="40" width="40" x="495" y="87"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="reportBack" id="BPMNShape_reportBack">
        <omgdc:Bounds height="55" width="105" x="590" y="80"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35" width="35" x="625" y="283"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="exclusivegateway7" id="BPMNShape_exclusivegateway7">
        <omgdc:Bounds height="40" width="40" x="250" y="280"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="45" y="107"></omgdi:waypoint>
        <omgdi:waypoint x="90" y="107"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="195" y="107"></omgdi:waypoint>
        <omgdi:waypoint x="250" y="107"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="270" y="127"></omgdi:waypoint>
        <omgdi:waypoint x="270" y="190"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="11" width="100" x="10" y="0"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
        <omgdi:waypoint x="290" y="107"></omgdi:waypoint>
        <omgdi:waypoint x="358" y="107"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="11" width="100" x="-24" y="-17"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
        <omgdi:waypoint x="463" y="107"></omgdi:waypoint>
        <omgdi:waypoint x="495" y="107"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
        <omgdi:waypoint x="535" y="107"></omgdi:waypoint>
        <omgdi:waypoint x="590" y="107"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="11" width="100" x="-22" y="-17"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
        <omgdi:waypoint x="642" y="135"></omgdi:waypoint>
        <omgdi:waypoint x="642" y="283"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
        <omgdi:waypoint x="515" y="127"></omgdi:waypoint>
        <omgdi:waypoint x="514" y="217"></omgdi:waypoint>
        <omgdi:waypoint x="323" y="217"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="11" width="100" x="10" y="0"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
        <omgdi:waypoint x="250" y="300"></omgdi:waypoint>
        <omgdi:waypoint x="142" y="299"></omgdi:waypoint>
        <omgdi:waypoint x="142" y="135"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="11" width="100" x="10" y="0"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
        <omgdi:waypoint x="270" y="245"></omgdi:waypoint>
        <omgdi:waypoint x="270" y="280"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow12" id="BPMNEdge_flow12">
        <omgdi:waypoint x="290" y="300"></omgdi:waypoint>
        <omgdi:waypoint x="625" y="300"></omgdi:waypoint>
        <bpmndi:BPMNLabel>
          <omgdc:Bounds height="11" width="100" x="10" y="0"></omgdc:Bounds>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>