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實(shí)現(xiàn)批量導(dǎo)出導(dǎo)入數(shù)據(jù)及附件文件zip包
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)批量導(dǎo)出導(dǎo)入數(shù)據(jù)及附件文件zip包的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一2022-09-09
springboot實(shí)現(xiàn)yml里的自定義配置方法
這篇文章主要介紹了springboot實(shí)現(xiàn)yml里的自定義配置方法,主要介紹三種,字符串配置,數(shù)組配置和帶默認(rèn)值的配置,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Java中轉(zhuǎn)換器設(shè)計(jì)模式深入講解
這篇文章主要給大家介紹了關(guān)于Java中轉(zhuǎn)換器設(shè)計(jì)模式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
SpringBoot的WebSocket實(shí)現(xiàn)單聊群聊
這篇文章主要為大家詳細(xì)介紹了SpringBoot的WebSocket實(shí)現(xiàn)單聊群聊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02
SpringBoot配置Spring Native的詳細(xì)步驟
配置 Spring Native 以減少 Spring Boot 應(yīng)用的啟動(dòng)時(shí)間,涉及幾個(gè)關(guān)鍵步驟,包括設(shè)置相應(yīng)的依賴、配置文件以及構(gòu)建過(guò)程,本文給大家就介紹了詳細(xì)的步驟和配置示例,需要的朋友可以參考下2024-11-11

