阅读 68

Activiti7 通过代码动态生成工作流

前言

最近项目有用到Activiti工作流,但是需求有点特殊,需要通过参数去生成BPMN图,查阅了资料后,能实现简单的工作流生成,那接下来看看如何通过代码动态生成工作流的吧。

一.设计思路

1.以普通的请假流程为例 image.png (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> 复制代码

四.总结

通过代码生成的BPMN图其实很乱,即使加了BpmnAutoLayout方法去调整布局,但是不影响流程正常使用。还有就是看了一遍源码,没有找到子流程(SubProcess的子任务)的生成方法,暂时不支持生成子流程,待我再多研究研究。

后话

简单流程通过代码生成没问题,复杂流程还是建议用工具绘图,通过代码生成有时候容易出问题。毕竟有一些节点不能连线,而且复杂流程对于一些退回操作不是很友好,实现起来很麻烦。


作者:自由了
链接:https://juejin.cn/post/7168707216478830599


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐