Activiti 流程部署方式 activi 動態部署(高階原始碼篇)
Activiti的流程 部署方式有很多種方式,我們可以根據activit工作流引擎提供的ap方式進行部署。
當然了實際需求決定你要使用哪一種api操作,後面的總結詳細介紹了使用場景。
下面看一下部署方式。
流程部署的方式在類org.activiti.engine.repository.DeploymentBuilder中定義的部署方介面式如下 :
DeploymentBuilder addInputStream(String resourceName, InputStream inputStream); DeploymentBuilder addClasspathResource(String resource); DeploymentBuilder addString(String resourceName, String text); DeploymentBuilder addZipInputStream(ZipInputStream zipInputStream); DeploymentBuilder addBpmnModel(String resourceName, BpmnModel bpmnModel);
可以看出activit工作流引擎一共提供五種方式進行流程對的部署。
addInputStream 根據流進行部署。
addClasspathResource 根據resource部署。
addString根據字串部署。
addZipInputStream根據zip流進行部署。
addBpmnModel 根據BpmnModel進行部署。這種方式使用的場景就是我們自己設計一個流程設計器畫布,自己去解析成bpmn規範檔案。適合動態的拓展。自定義。
下面一一講解如何使用api去進行部署。
1.1.1. addInputStream方式
流程定義如下所示:
<?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:xsd="http://www.w3.org/2001/XMLSchema" 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="daling"> <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d"> <startEvent id="startevent1" name="Start"></startEvent> <userTask id="usertask1" name="usertask1審批" activiti:candidateGroups="1,2"></userTask> <userTask id="usertask2" name="usertask2審批" activiti:candidateUsers="b,c"></userTask> <endEvent id="endevent1" name="End"></endEvent> <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow> <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow> <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_daling"> <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling"> <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"> <omgdc:Bounds height="35.0" width="35.0" x="230.0" y="10.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1"> <omgdc:Bounds height="55.0" width="105.0" x="300.0" y="110.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2"> <omgdc:Bounds height="55.0" width="105.0" x="280.0" y="192.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"> <omgdc:Bounds height="35.0" width="35.0" x="230.0" y="340.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"> <omgdi:waypoint x="247.0" y="45.0"></omgdi:waypoint> <omgdi:waypoint x="352.0" y="110.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"> <omgdi:waypoint x="352.0" y="165.0"></omgdi:waypoint> <omgdi:waypoint x="332.0" y="192.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"> <omgdi:waypoint x="332.0" y="247.0"></omgdi:waypoint> <omgdi:waypoint x="247.0" y="340.0"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
程式程式碼如下所示:
InputStream inputStream=ProcessEnginesDemo.class.getClassLoader().getResourceAsStream("demo1.bpmn");
Deployment deploy = repositoryService2.createDeployment().addInputStream("addInputStream", inputStream).deploy();
System.out.println(deploy);
程式的執行結果如下所示:
1.1.2. addClasspathResource方式
流程的定義還是第一種方式的流程圖,程式如下所示:
Deployment deploy2 =repositoryService2.createDeployment().addClasspathResource().deploy();
addClasspathResource中的引數是根據classpath方式載入,如果demo1.bpmn路徑在com.daling.ch1.ProcessEnginesDemo包下面則引數參入com/daling/ch1/ProcessEnginesDemo/demo1.bpmn
程式的執行如下圖所示:
1.1.3. addString方式
流程的定義還是第一種方式的流程圖,程式如下所示:
String str=read("D:\\WorkSpace\\activitidemo\\src\\main\\resources/demo1.bpmn");
Deployment deploy2 = repositoryService2.createDeployment().addString("string", str).deploy();
public static String read(String filePath) {
// 讀取txt內容為字串
StringBuffer txtContent = new StringBuffer();
// 每次讀取的byte數
byte[] b = new byte[8 * 1024];
InputStream in = null;
try {
// 檔案輸入流
in = new FileInputStream(filePath);
while (in.read(b) != -1) {
// 字串拼接
txtContent.append(new String(b));
}
// 關閉流
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return txtContent.toString();
}
程式的執行效果如下圖所示:
1.1.4. addZipInputStream方式
流程的定義還是第一種方式的流程圖,只不過講demo1.bpmn打包成zip檔案,結構如下:
程式操作如下所示:
InputStream inputStream=ProcessEnginesDemo.class.getClassLoader().getResourceAsStream("demo1.zip");
ZipInputStream zipInputStream=newZipInputStream(inputStream);
Deployment deploy2 =repositoryService2.createDeployment().addZipInputStream(zipInputStream).deploy();
程式的輸出結果如下圖所示:
1.1.5. addBpmnModel方式
這一種方式比較複雜需要自己去手動拼接物件,這裡我們就寫一個簡單的吧。實際開發中如果不夠用可以自己擴充套件根據這個demo具體的實現方式如下:
ProcessEnginesDemo demo = new ProcessEnginesDemo();
RepositoryService repositoryService2 = demo.getRepositoryService();
BpmnModel bpmnModel=new BpmnModel();
StartEvent startEvent=new StartEvent();
startEvent.setId("start1shareniu");
startEvent.setName("start1shareniu");
UserTask userTask=new UserTask();
userTask.setId("userTask1shareniu");
userTask.setName("userTask1shareniu");
EndEvent endEvent=new EndEvent();
endEvent.setId("endEventshareniu");
endEvent.setName("endEventshareniu");
List<SequenceFlow> sequenceFlows=new ArrayList<SequenceFlow>();
List<SequenceFlow> toEnd=new ArrayList<SequenceFlow>();
SequenceFlow s1=new SequenceFlow();
s1.setId("starttouserTask");
s1.setName("starttouserTask");
s1.setSourceRef("start1shareniu");
s1.setTargetRef("userTask1shareniu");
sequenceFlows.add(s1);
SequenceFlow s2=new SequenceFlow();
s2.setId("userTasktoend");
s2.setName("userTasktoend");
s2.setSourceRef("userTask1shareniu");
s2.setTargetRef("endEventshareniu");
toEnd.add(s2);
startEvent.setOutgoingFlows(sequenceFlows);
userTask.setOutgoingFlows(toEnd);
userTask.setIncomingFlows(sequenceFlows);
endEvent.setIncomingFlows(toEnd);
Process process=new Process();
process.setId("process1");
process.addFlowElement(startEvent);
process.addFlowElement(s1);
process.addFlowElement(userTask);
process.addFlowElement(s2);
process.addFlowElement(endEvent);
bpmnModel.addProcess(process);
repositoryService2.createDeployment().addBpmnModel("bpmnModel", bpmnModel).deploy();
程式的輸出截下圖所示:
總結:
五種方式的總結:
1.如果需要自己開發一套流程設計的話就使用addBpmnModel這種方法吧。這種方式更加靈活,缺點就是需要了解每一個物件的含義,需要對bpmnMode物件中的各個子物件都有所瞭解。
2.如果專案中的流程圖是固定的但是一些候選組或者人或者名稱不是固定的,需要從資料庫中查詢出來賦值在部署使用addString這種方法,配合velocity等葉面靜態化工具一起使用。
3.如果需要使用者自己上傳檔案部署的話,可以使用addInputStream和addZipInputStream這兩種方式。