Flowable7.x學習筆記(九)部署 BPMN XML 流程

前言

????????到本篇為止,我們已經完成了流程定義以及其 BPMN XML 本身的查詢和新增功能,那我們有有了XML之后就可以開始著手研究實現 Flowable7對流程的各種操作了,比如部署,掛起,發起等等。

????????首先第一步,我們本篇文章先來探討一下 BPMN XML 的部署(deploy)的知識點以及基于當前框架的實踐操作。

一、部署(deploy)是什么?

????????部署(deploy)是 Flowable7 中將流程定義、表單、決策規則等資源打包、解析、校驗并持久化到引擎數據庫的關鍵環節。

二、部署(deploy)發揮的作用

①?資源解析與合法性校驗

????????Flowable 在部署階段將 BPMN XML 轉為內存模型(BpmnModel),并對流程結構(如 StartEvent、連線正確性等)進行基礎校驗,以避免運行時異常?。

②?持久化部署數據

????????部署操作會寫入多張數據庫表:

  • ACT_RE_DEPLOYMENT:部署元信息;

  • ACT_GE_BYTEARRAY:流程定義、圖像等二進制資源;

  • ACT_RE_PROCDEF:流程定義記錄,包含 key、version、deploymentId 等字段?。

③?流程定義注冊

????????只有部署后的流程定義才能被 RuntimeService.startProcessInstanceByKey() 識別并實例化,部署是流程從“設計”到“執行”的必要橋梁?。?

④?版本管理

????????每次部署同一流程 key 時,Flowable 會在 ACT_RE_PROCDEF.version 上遞增版本號,舊版可繼續服務已運行實例,新版可用于新實例,實現灰度發布和快速回滾?。

⑤?集群高可用

????????集群模式下,各節點共享同一數據庫的部署信息,確保任意節點都能加載相同流程定義,實現負載均衡與故障切換?。

⑥?審計與追蹤

????????部署記錄與資源持久化后,可通過 API 或管理界面查詢歷史部署、導出流程圖等,對合規審計和故障排查至關重要?。

三、執行部署(deploy)的必要性

①?流程實例啟動前提

????????未部署的流程定義對引擎“不可見”,無法創建實例,也無法執行任何任務或事件?。

②?提前發現設計問題

????????部署時的解析和校驗能在 CI/CD 流程中及早捕獲模型缺陷,降低生產環境風險?。

③?支持多版本并存

????????通過部署版控,可平滑升級流程、驗證新版行為,并在出現問題時迅速回滾到舊版,提高系統可靠性?。

④?資源統一管理

????????將流程、表單與決策規則集中存儲并分類(如設置 namecategorytenantId),便于檢索與運維管理?。

⑤?程序化與自動化

????????無論是通過 Java API、Spring Boot 自動部署還是 REST 接口,部署都可集成至 DevOps 管道,確保每次版本發布都能穩定、可控。

四、后端:完成部署功能

① 創建一個常量類

package com.ceair.constant;/*** @author wangbaohai* @ClassName Flowable7Constants* @description: Flowable7 常量類* @date 2025年04月18日* @version: 1.0.0*/
public class Flowable7Constants {/*** 流程 xml 文件后綴*/public static final String BPMN_XML_SUFFIX = ".bpmn20.xml";}

② 創建一個流程狀態枚舉類

package com.ceair.enums;import lombok.Getter;/*** @author wangbaohai* @ClassName ProcessStatus* @description: 流程狀態* @date 2025年04月18日* @version: 1.0.0*/
@Getter
public enum ProcessStatus {/*** 0:草稿*/DRAFT(0, "草稿"),/*** 0:發布*/PUBLISH(1, "發布"),/*** 0:草稿*/DEACTIVATE(2, "停用");/*** 狀態碼*/private final Integer code;/*** 狀態描述*/private final String value;ProcessStatus(Integer code, String value) {this.code = code;this.value = value;}}

③ 創建一個流程引擎配置類

主要是為了讓Flowable支持中文,具體什么字體可以自由指定,我使用【宋體】

package com.ceair.config;import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;/*** @author wangbaohai* @ClassName FlowableConfig* @description: Flowable配置類* @date 2025年04月18日* @version: 1.0.0*/
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {/*** 配置流程引擎的字體設置,以解決流程圖中中文顯示亂碼的問題。** @param engineConfiguration SpringProcessEngineConfiguration 對象,用于配置流程引擎的相關屬性。*                            該參數不能為空,且應為已初始化的配置對象。** 此方法通過設置活動字體、標簽字體和注解字體為“宋體”,確保生成的流程圖中中文能夠正確顯示。*/@Overridepublic void configure(SpringProcessEngineConfiguration engineConfiguration) {// 設置流程圖中活動節點的字體為宋體,避免中文亂碼問題engineConfiguration.setActivityFontName("宋體");// 設置流程圖中標簽的字體為宋體,確保標簽中的中文正常顯示engineConfiguration.setLabelFontName("宋體");// 設置流程圖中注解的字體為宋體,防止注解內容出現中文亂碼engineConfiguration.setAnnotationFontName("宋體");}
}

④ 創建一個請求類

package com.ceair.entity.request;import lombok.Data;import java.io.Serial;
import java.io.Serializable;/*** @author wangbaohai* @ClassName DeployProcessDefinitionXmlReq* @description: 部署流程定義XML請求對象* @date 2025年04月18日* @version: 1.0.0*/
@Data
public class DeployProcessDefinitionXmlReq implements Serializable {@Serialprivate static final long serialVersionUID = 1L;/*** 流程唯一標識(業務中使用的 key)*/private String processKey;/*** 流程版本號*/private Integer processVersion;}

⑤ 創建一個部署服務

/*** 部署BPMN XML文件的函數。** 該函數接收一個包含流程定義XML部署請求的對象,并返回部署結果。** @param deployProcessDefinitionXmlReq 包含流程定義XML部署請求的參數對象。*        該對象通常包含BPMN XML文件的內容、部署的相關配置信息等。** @return Boolean 返回部署結果。*         - 如果部署成功,返回true;*         - 如果部署失敗,返回false。*/
Boolean deployBpmnXml(DeployProcessDefinitionXmlReq deployProcessDefinitionXmlReq);

⑥ 創建服務的實現

private final RepositoryService repositoryService;/*** 部署 BPMN XML 流程定義。** @param deployProcessDefinitionXmlReq 包含部署流程定義所需信息的請求對象。*                                      必須包含有效的流程定義標識和相關信息。* @return 返回布爾值,表示部署是否成功。如果方法執行完成且未拋出異常,則返回 true。* @throws BusinessException 如果在部署過程中發生業務異常,則拋出此異常。*                           異常信息會記錄日志并重新拋出。* @throws Exception         如果在部署過程中發生未知異常,則包裝為 BusinessException 拋出。*/
@Override
public Boolean deployBpmnXml(DeployProcessDefinitionXmlReq deployProcessDefinitionXmlReq) {try {// 校驗請求參數的合法性,確保輸入數據符合業務要求validateRequest(deployProcessDefinitionXmlReq);// 查詢流程定義信息,獲取與請求參數匹配的流程定義對象ProcessDefinition processDefinition = fetchProcessDefinition(deployProcessDefinitionXmlReq);// 獲取流程定義對應的 BPMN XML 數據,用于后續部署操作String bpmnXml = fetchBpmnXml(processDefinition);// 使用 Flowable 的 RepositoryService 部署流程定義repositoryService.createDeployment().addString(processDefinition.getProcessKey() + Flowable7Constants.BPMN_XML_SUFFIX, bpmnXml).name(processDefinition.getProcessName()).key(processDefinition.getProcessKey()).deploy();// 將流程定義的狀態變更為 1:發布processDefinition.setProcessStatus(ProcessStatus.PUBLISH.getCode());updateById(processDefinition);} catch (BusinessException e) {// 記錄業務異常日志,并重新拋出異常以便調用方處理log.error("部署流程時出現業務異常,具體異常原因: {}", e.getMessage(), e);throw e;} catch (Exception e) {// 記錄未知異常日志,并將異常包裝為 BusinessException 拋出log.error("部署流程時出現未知異常,具體異常原因: {}", e.getMessage(), e);throw new BusinessException("部署流程時出現未知異常", e);}return true;
}// 參數校驗方法
private void validateRequest(DeployProcessDefinitionXmlReq deployProcessDefinitionXmlReq) {if (deployProcessDefinitionXmlReq == null|| StringUtils.isBlank(deployProcessDefinitionXmlReq.getProcessKey())|| deployProcessDefinitionXmlReq.getProcessVersion() == null) {log.error("部署流程時參數校驗失敗,請重新選擇流程定義");throw new BusinessException("部署流程時參數校驗失敗,請重新選擇流程定義");}
}// 查詢流程定義信息方法
private ProcessDefinition fetchProcessDefinition(DeployProcessDefinitionXmlReq deployProcessDefinitionXmlReq) {ProcessDefinition processDefinition = lambdaQuery().eq(ProcessDefinition::getProcessKey, deployProcessDefinitionXmlReq.getProcessKey()).eq(ProcessDefinition::getProcessVersion, deployProcessDefinitionXmlReq.getProcessVersion()).one();if (processDefinition == null) {log.error("部署流程時流程定義已不存在");throw new BusinessException("部署流程時流程定義已不存在");}return processDefinition;
}// 獲取 BPMN XML 數據方法
private String fetchBpmnXml(ProcessDefinition processDefinition) {Optional<BpmnDefinitions> bpmnDefinitions = bpmnDefinitionRepository.findById(processDefinition.getXmlMongoId());return bpmnDefinitions.map(def -> {String bpmnXml = def.getBpmnXml();if (StringUtils.isBlank(bpmnXml)) {log.error("部署流程時流程定義的 BPMN XML 數據為空");throw new BusinessException("部署流程時流程定義的 BPMN XML 數據為空");}return bpmnXml;}).orElseThrow(() -> {log.error("部署流程時流程定義的 BPMN XML 數據為空");return new BusinessException("部署流程時流程定義的 BPMN XML 數據為空");});
}

⑦ 創建接口

/*** 部署流程定義XML的接口方法。** 該方法通過接收一個部署流程定義XML的請求對象,調用服務層方法完成流程定義的部署。* 如果部署過程中發生異常,會根據異常類型返回具體的錯誤信息。** @param deployProcessDefinitionXmlReq 部署流程定義XML請求對象,包含部署所需的必要信息(必填)。* @return 返回一個Result對象,包含布爾值表示部署是否成功。*         - 如果成功,返回Result.success(true)。*         - 如果失敗,返回Result.error(),并附帶具體的錯誤信息。*/
@PreAuthorize("hasAnyAuthority('/api/v1/definition/deployProcessDefinitionXml')")
@Parameter(name="deployProcessDefinitionXmlReq", description = "部署流程定義XML請求對象", required = true)
@Operation(summary = "部署流程定義XML")
@PostMapping("/deployProcessDefinitionXml")
public Result<Boolean> deployProcessDefinitionXml(@RequestBody DeployProcessDefinitionXmlReq deployProcessDefinitionXmlReq) {try {// 調用服務層方法部署流程定義XML,并返回成功結果return Result.success(processDefinitionService.deployBpmnXml(deployProcessDefinitionXmlReq));} catch (BusinessException e) {// 捕獲業務邏輯異常,返回具體的錯誤信息return Result.error("部署流程定義失敗,發生已知業務異常,具體原因:" + e);} catch (Exception e) {// 捕獲其他未知異常,返回通用錯誤信息return Result.error("部署流程定義失敗,發生未知業務異常,具體原因:" + e);}
}

五、前端:完成部署界面

① 創建請求對象

// 發布流程 xml 請求對象
export interface PublishProcessDefinitionXmlReq {processKey?: string // 流程唯一標識(業務中使用的 key)processVersion?: number
}

② 創建請求接口

// 發布流程定義 xml
export function publishProcessDefinition(data: PublishProcessDefinitionXmlReq) {return request.post<any>({url: '/pm-process/api/v1/definition/deployProcessDefinitionXml',data,})
}

③ 引入請求接口

④ 創建按鈕方法

/*** 發布流程定義的異步函數。** @param {ProcessDefinitionVO} row - 包含流程定義信息的對象,需提供 processKey 和 processVersion 屬性。* @returns {Promise<void>} - 無返回值,函數主要通過調用接口和更新狀態來完成操作。*/
async function onPublishProcessDefinition(row: ProcessDefinitionVO) {try {// 調用發布流程定義的接口,并傳遞流程鍵和版本信息const result: any = await publishProcessDefinition({processKey: row.processKey,processVersion: row.processVersion,})// 根據接口返回的結果判斷發布是否成功,并執行相應操作if (result.success && result.code === 200) {// 如果發布成功,提示用戶操作成功ElMessage({message: '發布成功',type: 'success',})// 初始化分頁參數為默認值:當前頁為第一頁,每頁顯示10條數據currentPage.value = 1pageSize.value = 10// 清空流程名稱的輸入框內容processName.value = ''// 重新獲取流程定義數據以刷新頁面getProcessDefinitionPageData()}else {// 如果發布失敗,提示用戶具體的錯誤信息ElMessage({message: result.message,})}}catch (error) {// 捕獲異常并提取錯誤信息,確保提供有意義的錯誤提示let errorMessage = '未知錯誤'if (error instanceof Error) {errorMessage = error.message}// 顯示異常錯誤消息,提示用戶發布失敗的具體原因ElMessage({message: `發布失敗: ${errorMessage || '未知錯誤'}`,type: 'error',})}
}

⑤ 操作列增加按鈕

<!-- 發布流程功能按鈕 -->
<el-button type="primary" @click="onPublishProcessDefinition(scope.row)">
? 發布
</el-button>

六、添加權限?

① 增加按鈕

② 綁定角色權限

七、XML開啟允許發布

填寫基礎信息并且按照圖中勾選即可

八、執行發布操作以及驗證

驗證 【ACT_RE_DEPLOYMENT】表中的NAME和KEY字段都和我們自己的流程定義的對應

驗證 【ACT_GE_BYTEARRAY】

驗證【ACT_RE_PROCDEF】

后記

本篇文章的前后端倉庫地址請查詢專欄第一篇文章

本文的后端分支是 process-4

本文的前端分支是 process-6

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/77687.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77687.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/77687.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

electron 渲染進程按鈕創建新window,報BrowserWindow is not a constructor錯誤;

在 Electron 中&#xff0c;有主進程和渲染進程 主進程&#xff1a;在Node.js環境中運行—意味著能夠使用require模塊并使用所有Node.js API 渲染進程&#xff1a;每個electron應用都會為每個打開的BrowserWindow&#xff08;與每個網頁嵌入&#xff09;生成一個單獨的渲染器進…

深入規劃 Elasticsearch 索引:策略與實踐

一、Elasticsearch 索引概述 &#xff08;一&#xff09;索引基本概念 Elasticsearch 是一個分布式、高性能的全文搜索引擎&#xff0c;其核心概念之一便是索引。索引本質上是一個存儲文檔的邏輯容器&#xff0c;它使得數據能夠在高效的檢索機制下被查詢到。當我們對文檔進行…

llamafactory的包安裝

cuda版本12.1&#xff0c;python版本3.10&#xff0c;torch版本2.4.0&#xff0c;幾個關鍵包版本如下&#xff1a; torch2.4.0cu121 transformers4.48.3 triton3.0.0 flash-attn2.7.1.post4 xformers0.0.27.post2 vllm0.6.3.post1 vllm-flash-attn2.6.1 unsloth2025.3.18 unsl…

Redis專題

前言 Redis的各種思想跟機組Cache和操作系統對進程的管理非常類似&#xff01; 一&#xff1a;看到你的簡歷上寫了你的項目里面用到了redis&#xff0c;為啥用redis&#xff1f; 因為傳統的關系型數據庫如Mysql,已經不能適用所有的場景&#xff0c;比如秒殺的庫存扣減&#xff…

【Rust 精進之路之第7篇-函數之道】定義、調用與參數傳遞:構建代碼的基本單元

系列: Rust 精進之路:構建可靠、高效軟件的底層邏輯 作者: 碼覺客 發布日期: 2025-04-20 引言:封裝邏輯,代碼復用的基石 在之前的文章中,我們已經探索了 Rust 如何處理數據(變量、標量類型、復合類型)以及如何控制程序的執行流程(if/else、循環)。這些構成了編寫簡…

文件有幾十個T,需要做rag,用ragFlow能否快速落地呢?

一、RAGFlow的優勢 1、RAGFlow處理大規模數據性能&#xff1a; &#xff08;1&#xff09;、RAGFlow支持分布式索引構建&#xff0c;采用分片技術&#xff0c;能夠處理TB級數據。 &#xff08;2&#xff09;、它結合向量搜索和關鍵詞搜索&#xff0c;提高檢索效率。 &#xf…

安卓的桌面 launcher是什么

安卓的桌面Launcher是一種安卓應用程序&#xff0c;它主要負責管理和展示手機主屏幕的界面以及相關功能&#xff0c;為用戶提供與設備交互的主要入口。以下是其詳細介紹&#xff1a; 功能 主屏幕管理&#xff1a;用戶可以在主屏幕上添加、刪除和排列各種應用程序圖標、小部件…

【學習筆記】計算機網絡(九)—— 無線網絡和移動網絡

第9章 無線網絡和移動網絡 文章目錄 第9章 無線網絡和移動網絡9.1 無線局域網WLAN9.1.1 無線局域網的組成9.1.2 802.11局域網的物理層9.1.3 802.11局域網的MAC層協議CSMA 協議CSMA/CD 協議 - 總線型 - 半雙工CSMA/CA 協議 9.1.4 802.11局域網的MAC幀 9.2 無線個人區域網WPAN9.3…

無線網絡入侵檢測系統實戰 | 基于React+Python的可視化安全平臺開發詳解

隨著無線網絡的普及&#xff0c;網絡攻擊風險也日益嚴峻。本項目旨在構建一個實時監測、智能識別、高效防護的無線網絡安全平臺&#xff0c;通過結合前后端技術與安全算法&#xff0c;實現對常見攻擊行為的有效監控和防御。 一、項目簡介與功能目的 本系統是一款基于 React 前…

速通FlinkCDC3.0

1.FlinkCDC概述 1.1FlinkCDC是什么&#xff1f; FlinkCDC&#xff08;Flink Change Data Capture&#xff09;是一個用于實時捕獲數據庫變更日志的工具&#xff0c;它可以將數據庫的變更實時同步到ApacheFlink系統中。 1.2 FlinkCDC的三個版本&#xff1f; 1.x 這個版本的Fli…

B+樹節點與插入操作

B樹節點與插入操作 設計B樹節點 在設計B樹的數據結構時&#xff0c;我們首先需要定義節點的格式&#xff0c;這將幫助我們理解如何進行插入、刪除以及分裂和合并操作。以下是對B樹節點設計的詳細說明。 節點格式概述 所有的B樹節點大小相同&#xff0c;這是為了后續使用自由…

C# 檢查字符串是否包含在另一個字符串中

string shopList "我是大浪,你的小狼"; this.ShopId"你的小狼"; bool existsShopId false; if (!string.IsNullOrEmpty(shopList)) {existsShopId shopList.Split(,).Any(part > part.Trim() this.ShopId); }檢查 goodsIdSet 中的每個元素是否都在 …

珈和科技遙感賦能農業保險創新 入選省級衛星應用示范標桿

為促進空天信息與數字經濟深度融合&#xff0c;拓展衛星數據應用場景價值&#xff0c;提升衛星數據應用效能和用戶體驗&#xff0c;加速衛星遙感技術向民生領域轉化應用&#xff0c;近日&#xff0c;湖北省國防科工辦組織開展了2024年湖北省衛星應用示范項目遴選工作。 經多渠…

深入理解 React 組件的生命周期:從創建到銷毀的全過程

React 作為當今最流行的前端框架之一&#xff0c;其組件生命周期是每個 React 開發者必須掌握的核心概念。本文將全面剖析 React 組件的生命周期&#xff0c;包括類組件的各個生命周期方法和函數組件如何使用 Hooks 模擬生命周期行為&#xff0c;幫助開發者編寫更高效、更健壯的…

緩存 --- Redis性能瓶頸和大Key問題

緩存 --- Redis性能瓶頸和大Key問題 內存瓶頸網絡瓶頸CPU 瓶頸持久化瓶頸大key問題優化方案 Redis 是一個高性能的內存數據庫&#xff0c;但在實際使用中&#xff0c;可能會在內存、網絡、CPU、持久化、大鍵值對等方面遇到性能瓶頸。下面從這些方面詳細分析 Redis 的性能瓶頸&a…

Python爬蟲與代理IP:高效抓取數據的實戰指南

目錄 一、基礎概念解析 1.1 爬蟲的工作原理 1.2 代理IP的作用 二、環境搭建與工具選擇 2.1 Python庫準備 2.2 代理IP選擇技巧 三、實戰步驟分解 3.1 基礎版&#xff1a;單線程免費代理 3.2 進階版&#xff1a;多線程付費代理池 3.3 終極版&#xff1a;Scrapy框架自動…

Nginx HTTP 414 與“大面積”式洪水攻擊聯合防御實戰

一、引言 在大規模分布式應用中&#xff0c;Nginx 常作為前端負載均衡和反向代理服務器。攻擊者若結合超長 URI/頭部攻擊&#xff08;觸發 HTTP 414&#xff09;與海量洪水攻擊&#xff0c;可在網絡層與應用層形成雙重打擊&#xff1a;一方面耗盡緩沖區和內存&#xff0c;另一…

【上位機——MFC】運行時類信息機制

運行時類信息機制的使用 類必須派生自CObject類內必須添加聲明宏DECLARE_DYNAMIC(theClass)3.類外必須添加實現宏 IMPLEMENT_DYNAMIC(theClass,baseClass) 具備上述三個條件后&#xff0c;CObject::IsKindOf函數就可以正確判斷對象是否屬于某個類。 代碼示例 #include <…

Maven插件管理的基本原理

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;精通Java編…

卷積神經網絡--手寫數字識別

本文我們通過搭建卷積神經網絡模型&#xff0c;實現手寫數字識別。 pytorch中提供了手寫數字的數據集 &#xff0c;我們可以直接從pytorch中下載 MNIST中包含70000張手寫數字圖像&#xff1a;60000張用于訓練&#xff0c;10000張用于測試 圖像是灰度的&#xff0c;28x28像素 …