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去进行部署。
流程定义如下所示:
<?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);
程序的运行结果如下所示:
流程的定义还是第一种方式的流程图,程序如下所示:
Deployment deploy2 =repositoryService2.createDeployment().addClasspathResource("demo1.bpmn").deploy();
addClasspathResource中的参数是根据classpath方式加载,如果demo1.bpmn路径在com.daling.ch1.ProcessEnginesDemo包下面则参数参入com/daling/ch1/ProcessEnginesDemo/demo1.bpmn
程序的运行如下图所示:
流程的定义还是第一种方式的流程图,程序如下所示:
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(); }
程序的运行效果如下图所示:
流程的定义还是第一种方式的流程图,只不过讲demo1.bpmn打包成zip文件,结构如下:
程序操作如下所示:
InputStream inputStream=ProcessEnginesDemo.class.getClassLoader().getResourceAsStream("demo1.zip");
ZipInputStream zipInputStream=new ZipInputStream(inputStream);
Deployment deploy2 =repositoryService2.createDeployment().addZipInputStream(zipInputStream).deploy();
程序的输出结果如下图所示:
这一种方式比较复杂需要自己去手动拼接对象,这里我们就写一个简单的吧。实际开发中如果不够用可以自己扩展根据这个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这两种方式。