在企業或事業單位,經常需要把乙個任務分派給多條線去處理,每條線可以由乙個或多個步驟構成,多條線的任務完成後需要再彙總一起於某個任務上。最常見的應用例子就是總經理把乙個任務分發下去給多個部門領導,每個部門領導再分發給多個主管,每個主管再分發給多個人處理,然後再彙總給每個主管,每個主管再彙總給部門領導,每個部門領導再彙總至總經理。這就是我們說的任務層層分發,再層層彙總的概念,我們統稱為多級分發與彙總。
以下示意圖為該流程在執行過程中的例項產生任務的示例,可以看到分發出來的任務是動態的,並且其後續的任務也會隨著產生出來。
解決方法一:
我們可以把多個任務線用子流程去實現也可以,這樣在分發那裡會產生多個子流程,子流程完成後,需要彙總。但若有多級分發與彙總,則需要子流程再巢狀子流程。
解決方法二:
把分發的任務線當作普通的任務來實現,該產生多少個任務可由分發任務決定,這些任務的名稱是一樣的,但任務例項id不一樣,執行人不一樣。
在jbpm4或activiti5上,動態建立子流程及對子流程的處理上,相對要完成的工作多一些,主要是activity或jbpm4上沒有提供這塊 api。而動態建立任務在jbpm4或activiti5上也是沒有提供的,只有activiti5上提供了乙個 taskservice.newtask,而該方法產生的新任務則跟流程定義無關,則表示該任務完成後,不能產生後續的任務。在此,我們先提供 activiti5的解決辦法。jbpm4的解決方法可以參照該方式實現,以下為解決方案的步驟:
以下我們來分析如按第二種方法來實現,首先要解決兩個問題,乙個是分發,另乙個是彙總。
分發任務其實就是複製任務的實現,activiti任務產生後,我們再基於該任務複製新的任務出來以實現任務分發的功能。實現**如下所示:
/*** 從乙個任務中複製另一任務出來
* @param taskentity
* @param uids 使用者id或組織id或角色id或崗位id
* @param usertype 值來自taskuser裡的type值
*/public void newforktasks(taskentity taskentity,setuids,string usertype)elsecatch(exception ex)}}
}在任務分發時,還包括了分發的令牌處理,令牌的作用是用於區別不同分發線上的任務,如上圖,「主管2分發」退回至「部門領導分發 」時,不會對主管3的任務產生影響,當主管1,主管2彙總任務時,僅產生乙個「部門領導彙總」的任務。令牌的變化規則如下圖所示:
t令牌格式為:t_層序號,分發的時候,不斷加上層序號,如兩層分發則令牌變化為t_層序號_層序號。令牌的儲存目前是存於任務的變數中,以方便任務獲取,作用域僅限於任務。任務的彙總就是需要把多個任務合併回乙個任務,實現該目標的方法就是利用任務跳轉時,檢查其後面的任務節點是否為彙總節點,若是的話,還要看同線上的兄弟節點是否已經完成,若沒有完成,則僅是完成該任務則可,若已經完成,則產生後續的彙總節點。實現的**如下所示:
//若目標節點為空,則代表沒有進行自由跳轉,同時後續的節點也不為彙總節點
if (destact == null)
//是否需要去除當前任務的後續跳轉線
boolean isneedremovetran=false;
//檢查目標任務是否為彙總節點,若為彙總節點,需要拿到當前任務的令牌,檢查該令牌對應的taskfork的已經彙總的任務個數,若目前的任務為最後乙個彙總,則刪除taskfork,並且任務進行下一步的跳轉,
//若目前任務不是最後乙個彙總,則需要更新彙總完成的任務個數,並且只是完成當前任務,不作跳轉。
if(bpmnodeset==null)
if(bpmnodeset!=null)
isneedremovetran=true;
}elseelse if(tokensplits.length>=3)}}
}}//進行鎖定
locktransto.lock();
//記錄原來的跳轉線
listbacktranslist = new arraylist();
backtranslist.addall(curacti.getoutgoingtransitions());
try//完成當前任務
taskservice.complete(task.getid(), variables);
}finally
//解除鎖定。
locktransto.unlock();
表名:bpm_task_fork
功能說明:任務的分發與彙總記錄
欄位名 字段型別 備註
taskforkid number(18) taskforkid
actinstid varchar2(128) 流程例項id
forktaskname varchar2(256) 分發任務名稱
forktaskkey varchar2(256) 分發任務key
forksn number(0,0) 分發序號
forkcount number(0,0) 分發個數
fininshcount number(0,0) 完成個數
forktime date 分發時間
jointaskname varchar2(256) 彙總任務名稱
jointaskkey varchar2(256) 彙總任務key
forktokens varchar2(512) 分發令牌號 格式如: t_1_1,t_1_2,t_1_3, 或 t_1,t_2,t_3,
forktokenpre varchar2(64) 格式為t_ 或格式t_1 或t_1_2等
當任務進行分發時,需要在此表加記錄,任務完成時,也需要對此表進行記錄,任務的分發與彙總設定在bpm_node_set表中也有記錄,如下表的紅色部分:
表名:bpm_node_set
功能說明:bpm_node_set
欄位名 字段型別 備註
setid number(18) setid
defid number(18) 流程定義id
nodename varchar2(128) 節點名
nodeid varchar2(128) activiti 節點id
formurl varchar2(128) 當表單型別為1時,表單對應的url
actdefid varchar2(127) act流程發布id
formdefname varchar2(128) formdefname
nodetype number(0,0) nodetype
jointaskkey varchar2(128) jointaskkey
jointaskname varchar2(128) jointaskname
beforehandler varchar2(100) 前置處理器
afterhandler varchar2(100) 後置處理器
isallowback number(0,0) 1=允許 2=不允許
jumptype varchar2(32) jumptype
settype number(1) 設定型別 0.任務節點1.開始表單2.預設表單
formkey number(18) 表單key
剩下的工作則是進行分發節點的設定與如何根據分發的使用者人數進行分發處理。
分發節點的設定類似如下所示:
任務的分發其實就是任務複製的過程,可以在taskcreatelistener裡進行處理,任務彙總時,需要進行任務的合併,則不是最後乙個分支,不進行新的後續的任務產生則可。
如何跑起Activiti5
最近想自己搭個架子,需要用到工作流,想看看activiti。下面是跑例子的過程 2 將activiti 5.5.zip在本地解壓 5 在dos視窗 activiti5 setup下執行命令 ant demo.start 說明 3 apache tomcat 6.0.32.zip,activiti m...
Activiti5 常用方法
任務委託 簽收了的 taskservice.delegatetask taskid,userid 未簽收的 taskservice.addcandidateuser taskid,userid 有乙個節點的id怎麼得到這個節點的activity processdefinitionentity.fin...
JBPM4 獲取任務
示例 1 xml version 1.0 encoding utf 8 23 process name test key test xmlns 4 start name start1 g 255,35,48,48 5 transition name 提交到科長 to 科長審批 g 63,25 6st...