进行了流程引擎的构建和初始化之后,接下来要做的就是把写好的流程文档部署到流程引擎中,后续activiti.cfg.xml的配置如果没有特指的话,一般就用第一章提供的例子。
首先画一个bpmn的图,可以通过集成开发环境的插件,也可以直接写xml形式。这里先写一个xml形式的bpmn图firstBPM.bpmn:
<?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="http://www.activiti.org/test">
<process id="firstBpmProcess" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name="myTask1" activiti:assignee="sadoshi"></userTask>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
<bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="41.0" width="35.0" x="505.0" y="40.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="470.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="505.0" y="240.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="522.0" y="81.0"></omgdi:waypoint>
<omgdi:waypoint x="522.0" y="150.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="522.0" y="205.0"></omgdi:waypoint>
<omgdi:waypoint x="522.0" y="240.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
大概是这样的一张流程图,一个开始节点,一个userTask节点,一个结束节点:
接着对这张流程图进行部署。部署的方法有文本方式、classpath方式、inputStream方式和zipInputStream方式。classpath的话要求bpmn文档在工程的classpath下,而其他几种方式则可以选择物理路径,比较灵活。另外zipInputStream适用于部署多张流程图打包而成的zip文件。这里展示使用inputStream方式的:
package engineDeploy;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;
public class App {
private ProcessEngine pe;
public void getFromProcessEngineConfiguration() {
ProcessEngineConfiguration pec = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
pe = pec.buildProcessEngine();
}
public void deploy() {
RepositoryService repositoryService = pe.getRepositoryService();
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
InputStream inputStream = null;
try {
inputStream = App.class.getClassLoader().getResource("bpmn/firstBPM.bpmn").openStream();
deploymentBuilder.addInputStream("first.bpmn", inputStream);
deploymentBuilder.name("firstDeployment");
deploymentBuilder.deploy();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
App app = new App();
app.getFromProcessEngineConfiguration();
app.deploy();
}
}
注意,如果添加的资源是bpmn流程的话,第35行addInputStream的第一个参数,后缀名必须是bpmn或bpmn20.xml,否则流程引擎不会对其进行解析,部署之后不会生成流程实例,就无法进行流程的启动等操作。
部署之后,查看数据库,act_re_deployent表有我们刚才部署的流程
在act_ge_bytearray表上也有流程对应的资源,一般是bpmn图
在act_re_procdef表上应该会生成bpmn流程文档中process对应的流程定义:
这样流程就算完成部署了。
可以分析一下刚才App类中,deploy函数内的代码。activiti的部署由RepositoryService负责,而RepositoryService则委托DeploymentBuilder进行部署。这里使用了建造者模式。通过源码分析可知DeploymentBuilder为流程部署的实体DeploymentEntity进行属性设置,然后再调用deploy进行部署。部署了流程之后,下一章会介绍流程的启动。
扩展:
其实流程部署并不是一定需要通过bpmn文件。因为activiti会把bpmn文件中的元素转化到BpmnModel中。activiti还提供了一种编程式的方式去部署bpmn流程,就是用户可以新建一个BpmnModel,然后设置好流程中的元素,把BpmnModel部署到流程引擎中:
public void addBpmnModel() {
SequenceFlow flow1 = new SequenceFlow();
flow1.setId("flow1");
flow1.setName("start->userTask1");
flow1.setSourceRef("startEvent1");
flow1.setTargetRef("userTask1");
SequenceFlow flow2 = new SequenceFlow();
flow2.setId("flow2");
flow2.setName("userTask1->end");
flow2.setSourceRef("userTask1");
flow2.setTargetRef("endEvent1");
BpmnModel bpmnModel = new BpmnModel();
Process process = new Process();
process.setId("secondBpmProcess");
StartEvent startEvent = new StartEvent();
startEvent.setId("startEvent1");
startEvent.setOutgoingFlows(Arrays.asList(flow1));
UserTask userTask1 = new UserTask();
userTask1.setId("userTask1");
userTask1.setName("userTask1");
userTask1.setIncomingFlows(Arrays.asList(flow1));
userTask1.setOutgoingFlows(Arrays.asList(flow2));
EndEvent endEvent = new EndEvent();
endEvent.setId("endEvent1");
endEvent.setName("endEvent1");
endEvent.setIncomingFlows(Arrays.asList(flow2));
process.addFlowElement(startEvent);
process.addFlowElement(flow1);
process.addFlowElement(userTask1);
process.addFlowElement(flow2);
process.addFlowElement(endEvent);
bpmnModel.addProcess(process);
RepositoryService repositoryService = pe.getRepositoryService();
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
deploymentBuilder.addBpmnModel("second", bpmnModel);
deploymentBuilder.deploy();
}
这个部署的流程和上面的大致相同。可以查看act_re_deployent和act_ge_bytearray的效果,和之前的inputStream方式类似。