Activiti7通過(guò)代碼動(dòng)態(tài)生成工作流實(shí)現(xiàn)詳解
前言
最近項(xiàng)目有用到Activiti工作流,但是需求有點(diǎn)特殊,需要通過(guò)參數(shù)去生成BPMN圖,查閱了資料后,能實(shí)現(xiàn)簡(jiǎn)單的工作流生成,那接下來(lái)看看如何通過(guò)代碼動(dòng)態(tài)生成工作流的吧。
一.設(shè)計(jì)思路
1.以普通的請(qǐng)假流程為例

(1)生成開(kāi)始節(jié)點(diǎn)加第1個(gè)任務(wù)和調(diào)整申請(qǐng)任務(wù)(拒絕或者退回操作)以及其排他網(wǎng)關(guān)
(2)循環(huán)審批列表,生成第2至第N-1個(gè)任務(wù),并每個(gè)任務(wù)后都有1個(gè)排他網(wǎng)關(guān),用于連接調(diào)整申請(qǐng)任務(wù)
(3)最后1個(gè)節(jié)點(diǎn),后面無(wú)排他任務(wù),故需要單獨(dú)處理
二.具體實(shí)現(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))) {
//開(kāi)始連線
process.addFlowElement(createUserTask("task".concat("_").concat(auditRole), "審批".concat(auditRole), auditRole));
process.addFlowElement(createSequenceFlow("start", "task".concat("_").concat(auditRole), null));
//正常的 第一個(gè)網(wǎng)關(guān) process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole)));
//第一個(gè)排他網(wǎng)關(guān)連線 任務(wù)->排他網(wǎng)關(guān)
process.addFlowElement(createSequenceFlow("task".concat("_").concat(auditRole), "exclusiveGateWay".concat("_").concat(auditRole), null));
//重新申請(qǐng)分支 創(chuàng)建重新申請(qǐng)任務(wù)
process.addFlowElement(createUserTask("task".concat("_").concat("重新申請(qǐng)"), "指定人".concat("審批"), "${startBy}"));
//申請(qǐng)網(wǎng)關(guān)->申請(qǐng)任務(wù)
process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(auditRole), "task".concat("_").concat("重新申請(qǐng)"), "${flag==false}"));
//申請(qǐng)網(wǎng)關(guān)
process.addFlowElement(createExclusiveGateway("exclusiveGateWay".concat("_").concat("重新申請(qǐng)"), "exclusiveGateWay".concat("_").concat("重新申請(qǐng)")));
//申請(qǐng)任務(wù)->申請(qǐng)網(wǎng)關(guān)
process.addFlowElement(createSequenceFlow("task".concat("_").concat("重新申請(qǐng)"),"exclusiveGateWay".concat("_").concat("重新申請(qǐng)"), null));
} else if (!auditRole.equals(processParamsDto.getAuditRoles().get(processParamsDto.getAuditRoles().size() - 1))) {
//創(chuàng)建排他網(wǎng)關(guān) 每個(gè)任務(wù)后都有一個(gè)排他網(wǎng)關(guān)
//第二個(gè)任務(wù)至第size-1個(gè)任務(wù)
process.addFlowElement(createUserTask("task".concat("_").concat(auditRole), "審批".concat(auditRole), auditRole));
//第一個(gè)網(wǎng)關(guān)->第二個(gè)任務(wù) 任務(wù)之前的節(jié)點(diǎn) 網(wǎng)關(guān)->第二個(gè)任務(wù)....第N個(gè)任務(wù) true
process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(getPreAuditRole(auditRole,processParamsDto.getAuditRoles())), "task".concat("_").concat(auditRole), "${flag==true}"));
//網(wǎng)關(guān)->申請(qǐng)任務(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)—>重新申請(qǐng)任務(wù)
process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat(auditRole), "task".concat("_").concat("重新申請(qǐng)"),"#{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é)點(diǎn)"+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("重新申請(qǐng)"), "end", "${flag==false}"));
process.addFlowElement(createSequenceFlow("exclusiveGateWay".concat("_").concat("重新申請(qǐng)"), "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"));
三.注意事項(xiàng)
1.activiti-bpmn-layout.jar
//BPMN圖布局自動(dòng)調(diào)整需要添加 <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-bpmn-layout</artifactId> <version>7.1.0.M4</version> </dependency>
2.mxgraph-all.jar
//需要手動(dòng)添加,其自帶的mxgraph找不到方法,原因待確認(rèn),有時(shí)間去提個(gè)issue問(wèn)問(wèn) <dependency> <groupId>com.mxgraph</groupId> <artifactId>mxgraph-all</artifactId> <version>4.2.2</version> <scope>system</scope> </dependency>
3.使用了layout和不使用的生成的圖對(duì)比

四.總結(jié)
通過(guò)代碼生成的BPMN圖其實(shí)很亂,即使加了BpmnAutoLayout方法去調(diào)整布局,但是不影響流程正常使用。還有就是看了一遍源碼,沒(méi)有找到子流程(SubProcess的子任務(wù))的生成方法,暫時(shí)不支持生成子流程,待我再多研究研究。
后話
簡(jiǎn)單流程通過(guò)代碼生成沒(méi)問(wèn)題,復(fù)雜流程還是建議用工具繪圖,通過(guò)代碼生成有時(shí)候容易出問(wèn)題。畢竟有一些節(jié)點(diǎn)不能連線,而且復(fù)雜流程對(duì)于一些退回操作不是很友好,實(shí)現(xiàn)起來(lái)很麻煩。
以上就是Activiti7通過(guò)代碼動(dòng)態(tài)生成工作流實(shí)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于Activiti7動(dòng)態(tài)生成工作流的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java批量從svn導(dǎo)出多個(gè)項(xiàng)目代碼實(shí)例
這篇文章主要介紹了java批量從svn導(dǎo)出多個(gè)項(xiàng)目代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
Spring TransactionalEventListener事務(wù)未提交讀取不到數(shù)據(jù)的解決
這篇文章主要介紹了Spring TransactionalEventListener事務(wù)未提交讀取不到數(shù)據(jù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
Spring BeanPostProcessor接口使用詳解
本篇文章主要介紹了Spring BeanPostProcessor接口使用詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Mybatis遷移到Mybatis-Plus的實(shí)現(xiàn)方法
這篇文章主要介紹了Mybatis遷移到Mybatis-Plus的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
spring?jpa設(shè)置多個(gè)主鍵遇到的小坑及解決
這篇文章主要介紹了spring?jpa設(shè)置多個(gè)主鍵遇到的小坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Spring security如何實(shí)現(xiàn)記錄用戶登錄時(shí)間功能
這篇文章主要介紹了Spring security如何實(shí)現(xiàn)記錄用戶登錄時(shí)間功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03

