Activiti7通过代码动态生成工作流实现详解
自由了 人气:0前言
最近项目有用到Activiti工作流,但是需求有点特殊,需要通过参数去生成BPMN图,查阅了资料后,能实现简单的工作流生成,那接下来看看如何通过代码动态生成工作流的吧。
一.设计思路
1.以普通的请假流程为例
(1)生成开始节点加第1个任务和调整申请任务(拒绝或者退回操作)以及其排他网关
(2)循环审批列表,生成第2至第N-1个任务,并每个任务后都有1个排他网关,用于连接调整申请任务
(3)最后1个节点,后面无排他任务,故需要单独处理
二.具体实现代码
List<String> roles=new ArrayList<>(); roles.add("1508574"); roles.add("13765234"); roles.add("18834222"); listMap.put("province",roles); for (String auditRole : processParamsDto.getAuditRoles()) { if (auditRole.equals(processParamsDto.getAuditRoles().get(0))) { //开始连线 process.addFlowElement(createUserTask("task".concat("_").concat(auditRole), "审批".concat(auditRole), auditRole)); process.addFlowElement(createSequenceFlow("start", "task".concat("_").concat(auditRole), null)); //正常的 第一个网关 process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole))); //第一个排他网关连线 任务->排他网关 process.addFlowElement(createSequenceFlow("task".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole), null)); //重新申请分支 创建重新申请任务 process.addFlowElement(createUserTask("task".concat("_").concat("重新申请"), "指定人".concat("审批"), "${startBy}")); //申请网关->申请任务 process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(auditRole), "task".concat("_").concat("重新申请"), "${flag==false}")); //申请网关 process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat("重新申请"), "exclusiveGateWay".concat("_").concat("重新申请"))); //申请任务->申请网关 process.addFlowElement(createSequenceFlow("task".concat("_").concat("重新申请"),"exclusiveGateWay".concat("_").concat("重新申请"), null)); } else if (!auditRole.equals(processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1))) { //创建排他网关 每个任务后都有一个排他网关 //第二个任务至第size-1个任务 process.addFlowElement(createUserTask("task".concat("_").concat(auditRole), "审批".concat(auditRole), auditRole)); //第一个网关->第二个任务 任务之前的节点 网关->第二个任务....第N个任务 true process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(getPreAuditRole(auditRole,processParamsDto.getAuditRoles())), "task".concat("_").concat(auditRole), "${flag==true}")); //网关->申请任务 false process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat(auditRole), "exclusiveGateWay(当前)".concat("_").concat(auditRole))); process.addFlowElement(createSequenceFlow("task".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole), null)); //排他网关—>重新申请任务 process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(auditRole), "task".concat("_").concat("重新申请"),"#{flag==false}")); } else if (auditRole.equals(processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1))) { String lastNode=processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1); System.out.println("当前节点"+lastNode); process.addFlowElement(createUserTask("task".concat(lastNode), "审批".concat(auditRole), auditRole)); process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(getPreAuditRole(auditRole,processParamsDto.getAuditRoles())),"task".concat(lastNode),"#{flag==true}")); process.addFlowElement(createEndEvent()); process.addFlowElement(createSequenceFlow("task".concat(processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1)), "end", "${flag==true}")); process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat("重新申请"), "end", "${flag==false}")); process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat("重新申请"), "task".concat("_").concat(processParamsDto.getAuditRoles().get(0)), "${flag==true}")); } } new BpmnAutoLayout(model).execute(); //定义并设置流程变量 Map<String, Object> variables = new HashMap<>(); variables.put("flag", 1 == 2); //deploy Deployment deployment = repositoryService.createDeployment().addBpmnModel("process/dynamic-model.bpmn", model).name("Dynamic process deployment").key("test_bpmn").deploy(); processEngine.getRuntimeService().startProcessInstanceByKey(processDefinition.getKey(), variables); InputStream inputStreamXml = processEngine.getRepositoryService().getResourceAsStream(deployment.getId(), "process/dynamic-model.bpmn"); //保存到本地,方便查看生成后的文件 FileUtils.copyInputStreamToFile(inputStreamXml, new File("D:\bpmn_data\process.bpmn.xml"));
三.注意事项
1.activiti-bpmn-layout.jar
//BPMN图布局自动调整需要添加 <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-bpmn-layout</artifactId> <version>7.1.0.M4</version> </dependency>
2.mxgraph-all.jar
//需要手动添加,其自带的mxgraph找不到方法,原因待确认,有时间去提个issue问问 <dependency> <groupId>com.mxgraph</groupId> <artifactId>mxgraph-all</artifactId> <version>4.2.2</version> <scope>system</scope> </dependency>
3.使用了layout和不使用的生成的图对比
四.总结
通过代码生成的BPMN图其实很乱,即使加了BpmnAutoLayout方法去调整布局,但是不影响流程正常使用。还有就是看了一遍源码,没有找到子流程(SubProcess的子任务)的生成方法,暂时不支持生成子流程,待我再多研究研究。
后话
简单流程通过代码生成没问题,复杂流程还是建议用工具绘图,通过代码生成有时候容易出问题。毕竟有一些节点不能连线,而且复杂流程对于一些退回操作不是很友好,实现起来很麻烦。
加载全部内容