Activiti7通過代碼動態(tài)生成工作流實現(xiàn)詳解
前言
最近項目有用到Activiti工作流,但是需求有點特殊,需要通過參數(shù)去生成BPMN圖,查閱了資料后,能實現(xiàn)簡單的工作流生成,那接下來看看如何通過代碼動態(tài)生成工作流的吧。
一.設(shè)計思路
1.以普通的請假流程為例
(1)生成開始節(jié)點加第1個任務(wù)和調(diào)整申請任務(wù)(拒絕或者退回操作)以及其排他網(wǎng)關(guān)
(2)循環(huán)審批列表,生成第2至第N-1個任務(wù),并每個任務(wù)后都有1個排他網(wǎng)關(guān),用于連接調(diào)整申請任務(wù)
(3)最后1個節(jié)點,后面無排他任務(wù),故需要單獨處理
二.具體實現(xiàn)代碼
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)); //正常的 第一個網(wǎng)關(guān) process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole))); //第一個排他網(wǎng)關(guān)連線 任務(wù)->排他網(wǎng)關(guān) process.addFlowElement(createSequenceFlow("task".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole), null)); //重新申請分支 創(chuàng)建重新申請任務(wù) process.addFlowElement(createUserTask("task".concat("_").concat("重新申請"), "指定人".concat("審批"), "${startBy}")); //申請網(wǎng)關(guān)->申請任務(wù) process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(auditRole), "task".concat("_").concat("重新申請"), "${flag==false}")); //申請網(wǎng)關(guān) process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat("重新申請"), "exclusiveGateWay".concat("_").concat("重新申請"))); //申請任務(wù)->申請網(wǎng)關(guān) process.addFlowElement(createSequenceFlow("task".concat("_").concat("重新申請"),"exclusiveGateWay".concat("_").concat("重新申請"), null)); } else if (!auditRole.equals(processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1))) { //創(chuàng)建排他網(wǎng)關(guān) 每個任務(wù)后都有一個排他網(wǎng)關(guān) //第二個任務(wù)至第size-1個任務(wù) process.addFlowElement(createUserTask("task".concat("_").concat(auditRole), "審批".concat(auditRole), auditRole)); //第一個網(wǎng)關(guān)->第二個任務(wù) 任務(wù)之前的節(jié)點 網(wǎng)關(guān)->第二個任務(wù)....第N個任務(wù) true process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(getPreAuditRole(auditRole,processParamsDto.getAuditRoles())), "task".concat("_").concat(auditRole), "${flag==true}")); //網(wǎng)關(guān)->申請任務(wù) false process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat(auditRole), "exclusiveGateWay(當(dāng)前)".concat("_").concat(auditRole))); process.addFlowElement(createSequenceFlow("task".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole), null)); //排他網(wǎng)關(guān)—>重新申請任務(wù) 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("當(dāng)前節(jié)點"+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(); //定義并設(shè)置流程變量 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圖布局自動調(diào)整需要添加 <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和不使用的生成的圖對比
四.總結(jié)
通過代碼生成的BPMN圖其實很亂,即使加了BpmnAutoLayout方法去調(diào)整布局,但是不影響流程正常使用。還有就是看了一遍源碼,沒有找到子流程(SubProcess的子任務(wù))的生成方法,暫時不支持生成子流程,待我再多研究研究。
后話
簡單流程通過代碼生成沒問題,復(fù)雜流程還是建議用工具繪圖,通過代碼生成有時候容易出問題。畢竟有一些節(jié)點不能連線,而且復(fù)雜流程對于一些退回操作不是很友好,實現(xiàn)起來很麻煩。
以上就是Activiti7通過代碼動態(tài)生成工作流實現(xiàn)詳解的詳細內(nèi)容,更多關(guān)于Activiti7動態(tài)生成工作流的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring TransactionalEventListener事務(wù)未提交讀取不到數(shù)據(jù)的解決
這篇文章主要介紹了Spring TransactionalEventListener事務(wù)未提交讀取不到數(shù)據(jù)的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09Spring BeanPostProcessor接口使用詳解
本篇文章主要介紹了Spring BeanPostProcessor接口使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01Mybatis遷移到Mybatis-Plus的實現(xiàn)方法
這篇文章主要介紹了Mybatis遷移到Mybatis-Plus的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08Spring security如何實現(xiàn)記錄用戶登錄時間功能
這篇文章主要介紹了Spring security如何實現(xiàn)記錄用戶登錄時間功能,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03