03 節點行為

審批流程圖

????????如下圖,在此流程圖中,存在兩個UserTask節點,第一個節點是主管審批,第二個節點是產品經理審批,兩個節點中間有一個排他網關,此網關用來對主管審批的結果進行判斷,如果主管審批通過,則流程走到產品經理審批節點,如果主管審批拒絕,則流程走到結束節點。

????????主管審批節點通過UEL表達式${assignManager}動態賦值,產品經理審批節點通過UEL表達式${assignProductLineManager}動態賦值,網關節點通過UEL表達式${isPass}動態賦值。

節點行為

????????上文提到,流程流轉到 UserTask 節點后,準備執行該節點上的行為,該節點的行為對應的類是 UserTaskActivityBehavior,入口為 executeActivityBehavior(ActivityBehavior, FlowNode)。

/*** 同步執行* @param flowNode*/
protected void executeSynchronous(FlowNode flowNode) {// 省略部分代碼// 執行實際的行為,UserTask對應的behavior是UserTaskActivityBehavior,// 這個UserTaskActivityBehavior里面會把task寫入到act_ru_taskActivityBehavior activityBehavior = (ActivityBehavior) flowNode.getBehavior();// 當 activityBehavior 不為空,走此方法,此方法后續也會調用 planTakeOutgoingSequenceFlowsOperation// activityBehavior 表示一個節點上擁有的行為// StartEvent 節點的行為是 NoneStartEventActivityBehavior,沒有做其它業務,僅僅是過度// UserTask   節點的行為是 UserTaskActivityBehavior,這個行為會把任務寫入到數據庫后,等待用戶完成任務,流程才會繼續走下去if (activityBehavior != null) {executeActivityBehavior(activityBehavior, flowNode);} else {logger.debug("No activityBehavior on activity '{}' with execution {}", flowNode.getId(), execution.getId());// 計劃執行 TakeOutgoingSequenceFlows 操作,這個操作是一個連線行為,第一步先找出當前節點的出口,第二步從出口走到下一個節點。Context.getAgenda().planTakeOutgoingSequenceFlowsOperation(execution, true);}
}

????????ContinueProcessOperation 中的 executeActivityBehavior(ActivityBehavior, FlowNode) 方法實現如下,這里參數 activityBehavior 的值是 UserTaskActivityBehavior 對象的實例。

/*** 執行節點上的行為* @param activityBehavior* @param flowNode*/
protected void executeActivityBehavior(ActivityBehavior activityBehavior,FlowNode flowNode) {logger.debug("Executing activityBehavior {} on activity '{}' with execution {}",activityBehavior.getClass(),flowNode.getId(),execution.getId());if (Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createActivityEvent(ActivitiEventType.ACTIVITY_STARTED,flowNode.getId(),flowNode.getName(),execution.getId(),execution.getProcessInstanceId(),execution.getProcessDefinitionId(),flowNode));}try {// 這方法里面后續會執行 planTakeOutgoingSequenceFlowsOperationactivityBehavior.execute(execution);} catch (RuntimeException e) {if (LogMDC.isMDCEnabled()) {LogMDC.putMDCExecution(execution);}throw e;}
}

????????UserTaskActivityBehavior 中的 execute(DelegateExecution) 方法實現如下:

public class UserTaskActivityBehavior extends TaskActivityBehavior {// 省略部分代碼protected UserTask userTask;// 在部署流程的時候,會把 bpmn20.xml 上解析到的 userTask 傳入構造函數中public UserTaskActivityBehavior(UserTask userTask) {this.userTask = userTask;}public void execute(DelegateExecution execution) {CommandContext commandContext = Context.getCommandContext();TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();// 創建任務,這個 TaskEntity 將會存儲在表 act_ru_task 中TaskEntity task = taskEntityManager.create();task.setExecution((ExecutionEntity) execution);task.setTaskDefinitionKey(userTask.getId());// 聲明變量,用于臨時存儲 bpmn20.xml 上 userTask 定義的變量信息,見下面的 圖 1.0String activeTaskName = null;String activeTaskDescription = null;String activeTaskDueDate = null;String activeTaskPriority = null;String activeTaskCategory = null;String activeTaskFormKey = null;String activeTaskSkipExpression = null;String activeTaskAssignee = null;String activeTaskOwner = null;List<String> activeTaskCandidateUsers = null;List<String> activeTaskCandidateGroups = null;ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {// 省去部分代碼          } else {// 這里的 userTask 解析自 bpmn20.xml 文件中定義的 UseTask 節點activeTaskName = userTask.getName();activeTaskDescription = userTask.getDocumentation();activeTaskDueDate = userTask.getDueDate();activeTaskPriority = userTask.getPriority();activeTaskCategory = userTask.getCategory();activeTaskFormKey = userTask.getFormKey();activeTaskSkipExpression = userTask.getSkipExpression();activeTaskAssignee = userTask.getAssignee();activeTaskOwner = userTask.getOwner();activeTaskCandidateUsers = userTask.getCandidateUsers();activeTaskCandidateGroups = userTask.getCandidateGroups();}// 省去部分代碼  /*** 任務寫入 act_ru_task 表中,但只是暫時存到緩存中,后面才會寫入數據庫*/taskEntityManager.insert(task, (ExecutionEntity) execution);// 省去部分代碼  boolean skipUserTask = false;if (StringUtils.isNotEmpty(activeTaskSkipExpression)) {Expression skipExpression = expressionManager.createExpression(activeTaskSkipExpression);skipUserTask = SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpression) && SkipExpressionUtil.shouldSkipFlowElement(execution, skipExpression);}// Handling assignments need to be done after the task is inserted, to have an idif (!skipUserTask) {// 處理UserTask節點中設置的UEL變量表達式,Assignee、CandidateUsers、CandidateGroups都是在這里解析handleAssignments(taskEntityManager, activeTaskAssignee, activeTaskOwner, activeTaskCandidateUsers, activeTaskCandidateGroups, task, expressionManager, execution);}// 如果有監聽 UserTask 創建事件的監聽器,就執行該監聽器processEngineConfiguration.getListenerNotificationHelper().executeTaskListeners(task, TaskListener.EVENTNAME_CREATE);// 省去部分代碼  // 如果 skipUserTask 是true,說明任務不會在UserTask節點等待用戶審批,而是直接就走向下個節點// 沒有設置跳過 UserTask 節點,所以 skipUserTask == false,不會走下面這個邏輯if (skipUserTask) {taskEntityManager.deleteTask(task, null, false, false);leave(execution);}}    
}

圖 1.0

總結

????????UserTask 節點上的 UserTaskActivityBehavior 行為,主要工作是解析 bpmn20.xml 流程文件上定義的 UserTask 節點變量信息,得到變量信息后,從 ExecutionEntity 上匹配變量的值,把匹配到的值設置到 TaskEntity 中。將 TaskEntity 存儲入庫,得益于未設置 skipExpression(跳過表達式),使得流程從 StartEvent 開始后流轉到了 UserTask 節點,并在 UserTask 節點上暫時停了下來等待,直到用戶完成審批,流程才會繼續往下走。

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

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

相關文章

深度卷積生成對抗網絡詳解與實現

深度卷積生成對抗網絡詳解與實現 0. 前言 1. 網絡架構 1.1 批歸一化 1.2 激活 1.3 上采樣 2. 構建 DCGAN 2.1 生成器 2.2 判別器 2.3 訓練 DCGAN 0. 前言 深度卷積生成對抗網絡 (Deep Convolutional Generative Adversarial Network, DCGAN) 是基于生成對抗網絡 (Generative A…

CF607B Zuma -提高+/省選-

CF607B Zuma codeforces 原鏈接 題目描述 Genos\texttt{Genos}Genos 最近在他的手機上下載了祖瑪游戲。在祖瑪游戲里&#xff0c;存在 nnn 個一行的寶石&#xff0c;第 iii 個寶石的顏色是 CiC_iCi?。這個游戲的目標是盡快的消滅一行中所有的寶石。 在一秒鐘&#xff0c;Ge…

拆分了解HashMap的數據結構

文章目錄 前言 一、底層數據結構總覽 二、核心組成部分詳解 1. 數組&#xff08;哈希表&#xff09; 2. 節點&#xff08;Node&#xff09; 3. 紅黑樹&#xff08;TreeNode&#xff09; 三、哈希函數與索引計算 四、哈希沖突的解決 五、擴容機制 六、關鍵特性與注意事…

關于電腦連接不到5g的WiFi時的一些解決辦法

方法一、設備管理器重卸載驅動后&#xff0c;重裝驅動。方法二、打開控制面板 “控制面板\網絡和 Internet\網絡連接” &#xff08;親測有效&#xff09;點擊更改適配器配置右擊當前的WLAN屬性點擊配置選擇“高級” 802.11a/b/g 無線模式選項欄 值&#xff1a;6.的雙…

Mathtype公式批量編號一鍵設置公式居中編號右對齊

插件[ygtools] 批量編號一鍵設置公式居中編號右對齊 單欄/多欄均可https://wwon.lanzout.com/i0NRf35vyw8j 下載密碼8543

基于ssm的小橘子出行客戶體驗評價系統[SSM]-計算機畢業設計源碼+LW文檔

摘要&#xff1a;隨著出行行業的快速發展&#xff0c;客戶體驗評價對于出行服務質量的提升至關重要。本文設計并實現了基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架的小橘子出行客戶體驗評價系統。該系統涵蓋系統用戶管理、司機信息管理、客戶評價管理等功…

算法日記---二分查找

目錄 前言 一、二分查找 1.思想 2.簡單二分 3.優點 4.局限性 二、模板 1.基本模板 2.簡單例題&#xff08;LeetCode&#xff09; 4.有重復元素的二分 5.0-1問題 總結 前言 本文通過講解簡單的二分查找配合leetcode例題對二分查找本質、模板進行了基礎的總結 提示&a…

Level Set(水平集)算法——形象化講解

目錄 維度一&#xff1a;核心思想與比喻&#xff08;它像什么&#xff1f;&#xff09; 維度二&#xff1a;要解決什么問題&#xff1f;&#xff08;它能干嘛&#xff1f;有什么用&#xff1f;&#xff09; 維度三&#xff1a;工作原理&#xff08;它是怎么做到的&#xff1…

DDoS 攻防“軍備競賽”的幕后

談到 DDoS&#xff08;分布式拒絕服務攻擊&#xff09;&#xff0c;很多人會想到“黑客租用肉雞發流量&#xff0c;網站直接崩”。但事實上&#xff0c;如今的 DDoS 攻防早已變成一場 軍備競賽。攻擊者的武器越來越“工業化”&#xff1a;僵尸網絡商品化&#xff1a;黑市上&…

如何用 Rust 重寫 SQLite 數據庫(二):是否有市場空間?

用 Rust 實現一個類似 SQLite 的嵌入式數據庫非常有意義&#xff0c;但需要結合具體目標和場景來評估其價值。以下從技術、生態、市場需求和個人成長等多個維度展開分析&#xff0c;并給出結論。一、技術價值&#xff1a;Rust 與數據庫的天然契合 SQLite 作為全球裝機量最大的數…

【Web】ImaginaryCTF 2025 wp

目錄 imaginary-notes certificate codenames-1 passwordless pearl imaginary-notes I made a new note taking app using Supabase! Its so secure, I put my flag as the password to the "admin" account. I even put my anonymous key somewhere in the si…

oracel如何找到外鍵子表

要找到導致外鍵約束沖突的子表&#xff08;即包含"child record"的表&#xff09;&#xff0c;可以通過以下SQL查詢在Oracle數據庫中定位&#xff1a;1. 查詢約束基本信息&#xff08;確定父表和子表&#xff09;SELECT owner, constraint_name, table_name AS child…

智源研究院新研究:突破物理世界智能邊界的RoboBrain 2.0,將重構具身AI能力天花板

當你對著家用機器人說"把杯子放在筆筒和鍵盤之間&#xff0c;對齊杯身logo"時&#xff0c;它能精準理解空間關系并執行動作&#xff1b;當多臺機器人在超市協作補貨時&#xff0c;它們能自主規劃軌跡、避免沖突并完成長周期任務——這些曾經出現在科幻電影中的場景&a…

【2025】Office核心組件Microsoft word,Excel,PowerPoint詳細使用指南

Office 核心組件使用指南 Microsoft Word 文字處理 Word主要用于創建和編輯文檔&#xff0c;如信件、報告、論文等。 2025Office&#x1f517; 1. 界面認識 快速訪問工具欄&#xff1a;位于左上角&#xff0c;可自定義保存、撤銷、恢復等常用命令。功能區&#xff1a;頂部…

【模型訓練篇】VeRL的使用 - RL(PPO)與源碼

繼續學習字節家的VeRL&#xff0c;今天來看看VeRL的RL&#xff0c;是VeRL系列的第三篇文章&#xff08;話說近期好多大事兒&#xff0c;我司發布了Longcat、韓立結嬰、阿里周五發布了QWen-Next都是好東西啊&#xff0c;學不過來了damn&#xff09; 底層分布式能力基礎Ray&…

QML Charts組件之折線圖的鼠標交互

目錄前言相關系列代碼示例詳解&#xff08;LineSeriesDemo3.qml&#xff09;功能概覽運行效果代碼說明工程下載參考前言 接上文&#xff08;QML Charts組件之折線圖的基礎屬性&#xff09;&#xff0c;本文將重點介紹LineSeries的鼠標交互&#xff0c;包括&#xff1a;鼠標拖拽…

二值信號量——學習筆記12

本文是筆者在學習 正點原子官方 的《【正點原子】手把手教你學FreeRTOS實時系統》系列視頻時整理的筆記。 視頻講解清晰透徹&#xff0c;非常感謝UP主的無私奉獻&#xff01;原課程鏈接如下&#xff1a; &#x1f449; B站視頻鏈接&#xff1a;??????【正點原子】手把手教…

裸機開發 時鐘配置,EPIT

1.概念時鐘(clock)&#xff1a;在電子系統中是一個產生穩定、周期性振蕩信號的電路或組件。這個信號像節拍器或心跳一樣&#xff0c;為數字電路中的各種操作提供同步時序基準。PLL&#xff08;phase locked loop&#xff09;鎖相環電路: 倍頻PFD&#xff08;phase fractional P…

Linux-文本三劍客(grep、sed、awk)

Linux-文本三劍客前言一、grep二、sed三、awk模式 -- 正則表達式關系表達式、運算符表達模式匹配表達式動作 輸出流程控制參數傳遞&#xff0c;awk接受外部變量統計數組的使用分組統計練習常用內置函數前言 grep、sed、awk 被稱為 “文本三劍客”&#xff0c;它們是處理文本文…

主流反爬蟲、反作弊防護與風控對抗手段

文章目錄1. 寫在前面2. 指紋檢測3. 行為驗證3. 加固防護4. 鏈路檢測5. 風控埋點6. 游客注冊7. 數據防護8. 賬號權重9. 反調阻斷【&#x1f3e0;作者主頁】&#xff1a;吳秋霖 【&#x1f4bc;作者介紹】&#xff1a;擅長爬蟲與JS加密逆向分析&#xff01;Python領域優質創作者、…