首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JBPM 核心機制:流程實例變量與任務實例變量的區別與交互原理

     編輯:Java 相關知識

在 JBPM 架構中,變量按作用域劃分為流程實例變量(Process Instance Variable)與任務實例變量(Task Instance Variable)。二者在存儲機制、可見性、映射配置上存在本質差異。本文從底層實現、API 行為、配置映射三個維度,徹底釐清兩者關係。

一、流程實例變量:全局可見的持久化數據

兩類流程變量

類型API持久化生命週期用途
瞬時變量setTransientVariable() / getTransientVariable()不持久化,不寫入 jbpm_variableinstance隨流程實例銷毀而消失臨時計算中間值、敏感數據不落庫
普通變量setVariable() / setVariableLocally() / getVariable()持久化至 jbpm_variableinstance流程實例全生命週期業務數據、表單數據、流程狀態

普通變量的兩種設置方式差異

// 方式一:setVariable() - 全局可見
contextInstance.setVariable("foo", "fooValue");
// 存入 jbpm_variableinstance,taskinstance_ 為 NULL
// 可被流程內任意任務實例訪問

// 方式二:setVariableLocally() - 綁定當前任務
taskInstance.setVariableLocally("foo", "fooValue");
// 存入 jbpm_variableinstance,taskinstance_ = 當前任務 ID
// 同時創建同名流程變量(JBPM 設計特性)

關鍵結論:若需讓任務實例直接訪問流程變量,用 setVariable();若需變量綁定特定任務(如表單草稿),用 setVariableLocally()。

二、任務實例變量:節點級局部變量

變量查找鏈:從局部到全局

任務實例訪問變量時遵循就近原則:

  1. 先在當前任務實例變量中查找
  2. 未找到則委派給所屬流程實例查找
  3. 流程實例中也無則返回 null
// 流程實例設置
contextInstance.setVariable("globalVar", "fromProcess");

// 任務實例直接可讀
String val = taskInstance.getVariable("globalVar"); // 返回 "fromProcess"

// 任務實例寫入同名變量 -> 創建任務局部變量,遮蔽流程變量
taskInstance.setVariable("globalVar", "fromTask");
String val2 = taskInstance.getVariable("globalVar"); // 返回 "fromTask" (任務局部)
String val3 = contextInstance.getVariable("globalVar"); // 返回 "fromProcess" (流程未變)

三、Task Controller:任務與流程變量的雙向映射橋樑

配置機制

在流程定義的 <task> 節點下配置 <controller>,定義任務變量與流程變量的同步規則:

<task name="approval">
  <controller>
    <variable access="read,required" name="foo" />
    <variable access="read,write" name="foo" mapped-name="bar" />
  </controller>
</task>

映射行為詳解

配置任務建立時任務完成時備註
name="foo" 無 mapped-name查找流程變量 foo → 創建任務變量 foo任務變量 foo → 回寫流程變量 foo同名雙向同步
name="foo" mapped-name="bar"查找流程變量 foo → 創建任務變量 bar任務變量 bar → 回寫流程變量 foo名稱解耦,name 對應流程,mapped-name 對應任務
access="read"讀取流程值不回寫只讀展示
access="write"不讀取,任務變量初始為 null回寫任務值到流程純輸入
access="read,write"讀取流程值回寫任務值到流程雙向綁定
required-強制回寫,否則拋出異常必填保護

access 屬性實測結論

經實測,read、write、required 的組合在 JBPM 部分版本中行為一致,核心邏輯由 read/write 決定,required 僅在完成階段做非空檢查。建議顯式聲明意圖:read、write、read,write、read,write,required。

四、進階場景:無 Controller 映射時的訪問策略

問題

若流程變量未在 Task Controller 映射,直接用 TaskInstance.setVariable() 設置,則 jbpm_variableinstance.taskinstance_ 為 NULL,該變量無法通過任務實例 API 訪問。

解決方案

// 方案一:使用 setVariableLocally() 綁定任務
taskInstance.setVariableLocally("localVar", "value");
// 產生 taskinstance_ = 當前任務 ID,可被任務實例直接訪問
// 副作用:同時創建同名流程變量

// 方案二:在 Controller 顯式映射(推薦)
<variable name="localVar" access="read,write" />
// 語義清晰,生命週期可控

五、底層存儲結構速覽

表 jbpm_variableinstance 關鍵欄位:

欄位含義
id_主鍵
name_變量名
class_類型類名
processinstance_關聯流程實例 ID(流程變量非空)
taskinstance_關聯任務實例 ID(任務局部變量非空)
bytearray_ / long_ / ...不同類型值存儲欄位
  • 流程變量:processinstance_ 有值,taskinstance_ 為 NULL
  • 任務局部變量:taskinstance_ 有值,processinstance_ 通常也有值(JBPM 同步機制)

六、最佳實踐總結

  1. 默認用流程變量:跨節點共享數據,用 ContextInstance.setVariable()
  2. 任務私有數據用局部變量:草稿、臨時計算,用 TaskInstance.setVariableLocally()
  3. 表單交互必配 Controller:明確 access、mapped-name,避免隱式行為
  4. 避免同名遮蔽:任務與流程變量命名區分(如 task_ 前綴),減少認知負擔
  5. 數據庫層面排查:疑難雜症查 jbpm_variableinstance 表的 taskinstance_ 欄位,確認變量歸屬

總結:流程變量是「全局倉庫」,任務變量是「專用抽屜」。Controller 是「搬運工」,按 access 與 mapped-name 規則在兩者間搬運數據。理解底層 jbpm_variableinstance 的雙外鍵設計,能從根源上掌握變量可見性與生命週期。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved