初步设想实现一个部署完工作流之后,为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>