一、部署相关的表
- act_re_deployment:流程模型部署对象表
每部署一次生成一条记录,首先生成这条数据,它的id主键将会被act_re_procdef和act_ge_bytearray作为外键。 - act_re_procdef:流程定义表
一次部署可能采用zip/bar进行部署,里面是有多份流程定义文件xml的,这时候act_re_deployment只有一条部署信息,但act_re_procdef有多个记录(一个流程定义对应一条),这个表有DEPLOYMENT_ID_外键字段,用它关联act_re_deployment。 - act_ge_bytearray:资源文件表
流程模型资源文件的真正存放地方,它每部署一次就会产生2条记录,一条是关于bpmn规范的文件内容存放在BYTES字段中,另一条是图片信息,采用二进制格式存储。
提示:可以部署后解析bpmn文件的内容自动生成流程图,实现流程图的跟踪线路。 - act_re_model:这张表,在xml进行部署时,它没有内容(flowable放弃了此表改用act_de_model保存流程模型信息)
二、Maven依赖
针对Model部署需增加:
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>6.4.2</version>
</dependency>
<!--流程设计器-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-rest</artifactId>
<version>6.4.2</version>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
三、流程图部署
- 流程资源xml部署
@SpringBootTest
@Slf4j
class WorkflowFlowableApplicationTests {
@Autowired
private RepositoryService repositoryService;
@Resource
private ProcessEngine processEngine;
/**
* 流程资源xml部署
*/
@Test
void deployFlow() {
String filePath = "processes/OrderApproval.bpmn20.xml";
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
.addClasspathResource(filePath);
Deployment deployment = deploymentBuilder.deploy();
log.info("成功:部署工作流成:" + filePath);
log.info("部署ID:"+deployment.getId());
log.info("部署时间:"+deployment.getDeploymentTime());
}
}
- zip/bar打包,多个流程资源文件部署
/**
* zip/bar打包,多个流程资源文件部署
*/
@Test
void deployFlowZip() {
/**
* 需要将所有流程图进行打包
*/
String file = "diagrams/approve.zip";
InputStream in = this.getClass().getClassLoader().getResourceAsStream(file);
ZipInputStream zipInputStream = new ZipInputStream(in);
// 获取流程定义和部署对象相关的Service
Deployment deployment = processEngine.getRepositoryService()
// 创建部署对象
.createDeployment()
// 使用zip方式部署,将approve.bpmn和approve.png压缩成zip格式的文件
.addZipInputStream(zipInputStream)
.deploy(); // 完成部署
log.info("部署ID:" + deployment.getId());
log.info("部署时间:" + deployment.getDeploymentTime());
}
- Model部署
/**
* Model部署
*/
void deployFlowModel() {
String modelId = "modelId";
// 通过act_de_model中存放的Modeler内容来部署
Model modelData = repositoryService.getModel(modelId);
ObjectNode modelNode = null;
try {
// 获取模型
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
if (null == bytes) {
log.error("模型数据为空,请先设计流程并成功保存,再进行发布。");
}
modelNode = (ObjectNode) new ObjectMapper().readTree(bytes);
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
if (model.getProcesses().size() == 0) {
log.error("数据模型不符要求,请至少设计一条主线流程。");
}
byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
// 发布流程
String processName = modelData.getName() + ".bpmn20.xml";
repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes, "UTF-8")).deploy();
} catch (IOException e) {
e.printStackTrace();
}
}
四、流程部署示例
- 创建流程图
<?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:flowable="http://flowable.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.flowable.org/processdef">
<process id="test_bpmn" name="测试BPMN模型" isExecutable="true">
<documentation>测试BPMN模型</documentation>
<startEvent id="start" name="开始"></startEvent>
<endEvent id="end" name="结束"></endEvent>
<userTask id="testUser" name="用户任务测试"></userTask>
<sequenceFlow id="sid-8D834F3C-45A8-4C88-9AD1-1AC426CC9002" sourceRef="start" targetRef="testUser"></sequenceFlow>
<sequenceFlow id="sid-AB59612A-1B33-4FB8-8758-5D773EDF9C44" sourceRef="testUser" targetRef="end"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_test_bpmn">
<bpmndi:BPMNPlane bpmnElement="test_bpmn" id="BPMNPlane_test_bpmn">
<bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">
<omgdc:Bounds height="30.0" width="30.0" x="210.0" y="60.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end">
<omgdc:Bounds height="28.0" width="28.0" x="525.0" y="61.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="testUser" id="BPMNShape_testUser">
<omgdc:Bounds height="80.0" width="100.0" x="315.0" y="35.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-8D834F3C-45A8-4C88-9AD1-1AC426CC9002" id="BPMNEdge_sid-8D834F3C-45A8-4C88-9AD1-1AC426CC9002">
<omgdi:waypoint x="239.94999779398907" y="75.0"></omgdi:waypoint>
<omgdi:waypoint x="315.0" y="75.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-AB59612A-1B33-4FB8-8758-5D773EDF9C44" id="BPMNEdge_sid-AB59612A-1B33-4FB8-8758-5D773EDF9C44">
<omgdi:waypoint x="414.9499999999903" y="75.0"></omgdi:waypoint>
<omgdi:waypoint x="525.0" y="75.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
- 创建业务方法
public interface IFlowService {
/**
* 部署工作流
*/
Deployment createFlow(String filePath);
}
@Primary
@Service
@Slf4j
public class FlowServiceImpl implements IFlowService {
/**
* Flowable运行时服务
*/
@Autowired
private RepositoryService repositoryService;
@Override
public Deployment createFlow(String filePath) {
//解析BPMN模型看是否成功
XMLStreamReader reader = null;
InputStream inputStream = null;
try {
BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
XMLInputFactory factory = XMLInputFactory.newInstance();
inputStream=new FileInputStream(new File(filePath));
reader = factory.createXMLStreamReader(inputStream);
BpmnModel model = bpmnXMLConverter.convertToBpmnModel(reader);
List<Process> processes = model.getProcesses();
Process curProcess = null;
if (CollectionUtils.isEmpty(processes)) {
log.error("BPMN模型没有配置流程");
return null;
}
curProcess = processes.get(0);
inputStream=new FileInputStream(new File(filePath));
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().name("TEST_FLOW")
.addInputStream(curProcess.getName(),inputStream);
Deployment deployment= deploymentBuilder.deploy();
log.warn("部署流程 name:"+curProcess.getName() + " "+deployment);
return deployment;
}
catch (Exception e){
log.error("BPMN模型创建流程异常",e);
return null;
}
finally {
try {
reader.close();
} catch (XMLStreamException e) {
log.error("关闭异常",e);
}
}
}
}
- 创建控制器
@RestController
@RequestMapping(value = "flow")
@Slf4j
public class FlowController {
@Autowired
private IFlowService flowService;
@RequestMapping("/create")
public Map<String, String> createFlow() throws FileNotFoundException {
Map<String, String> res = new HashMap<>();
String flowPath = "processes/test.bpmn20.xml";
File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + flowPath);
if (null == flowService.createFlow(file.getAbsolutePath())) {
res.put("msg", "创建流程失败");
res.put("res", "0");
return res;
}
res.put("msg", "创建流程成功");
res.put("res", "1");
return res;
}
}
部署ID表:act_re_deployment
布署内容表:act_ge_bytearray