JBPM工作流(七)——詳解流程圖


概念:

流程圖的組成:

a. 活動 Activity / 節點 Node

b. 流轉 Transition / 連線(單向箭頭)

c. 事件

1.流轉(Transition)

  a) 一般情況一個活動中可以指定一個或多個Transition

    i. 開始活動(Start)中只能有一個Transition。

    ii. 結束活動(End)中沒有Transition。

    iii. 其他活動中有一條或多條Transition

  b) 如果Transition只有一個,則可以不指定名稱(名稱是null);如果有多個,則要分別指定唯一的名稱。

2.活動(Activity)

  a) 流轉控制活動(預定義活動)

  

   

 

            i. start開始活動

 

          代表流程的開始邊界,一個流程有且只能有一個Start活動。開始活動只能指定一個Transition。在流程實例啟動后,會 自動的使用這個唯一的Transition離開開始活動,到一下個活動。

    ii. end/end-error/end-cancel(結束活動)

      代表流程的結束邊界,可以有多個,也可以沒有。如果有多個,則到達任一個結束活動,整個流程就都結束了;如果沒 有,則到達最后那個沒有Transition的活動,流程就結束了。

 

           iii. state狀態活動

 

 

      作用:等待。可以使用signal使其結束等待,並向后執行一步。

         

 

    iv. task任務活動

 

 

-->個人任務的分配

  

 

    1. 使用流程變量:assignee="#{manager}"

    2. AssignmentHandler:assignable.setAssignee(userId); // 指定當前任務的辦理人(分配任務)

      a) 需要在.jbdl.xml的<task>元素中寫

      

?
1
<assignment-handler class = "cn.grace.AssignmentHandlerImpl" />

      b) 指定的AssignmentHandlerImpl類要實現AssignmentHandler接口

      c) 在AssignmentHandlerImpl類中可以使用assignable.setAssignee(userId),分配個人任務。

    3. TaskService.assignTask(taskId, userId)// 把指定的任務分配給指定的人

      

?
1
processEngine.getTaskService().assignTask(taskId, userId);

  -->組任務的分配

    1.  使用流程變量:assignee="#{userIdsString}" // 要是String型的變量,多個候選人之前用','隔開

    2. AssignmentHandler:assignable.addCandidateUser(userId);// 添加組任務的候選人

      a) 需要在.jbdl.xml的<task>元素中寫

      

?
1
<assignment-handler class = "cn.grace.GroupTaskAssignmentHandlerImpl" />

     b) 指定的AssignmentHandlerImpl類要實現AssignmentHandler接口

     c) 在AssignmentHandlerImpl類中可以使用assignable.addCandidateUser(userId),添加組任務候選人。

     3. TaskService.addTaskParticipatingUser(taskId,userId,Participation.CANDIDATE);//添加組任務的候選人

  v. Decision判斷活動

    1. 使用expression,如:expr="#{'to state2'}"

    2. 使用Handler,在Handler Class里配置指定的DecisionHandlerImpl類的路徑

    DecisionHandlerImpl.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class DecisionHandlerImpl implements DecisionHandler {
 
     // 計算離開當前節點用的Transition的名稱並返回
     @Override
     public String decide(OpenExecution execution) {
         System.out.println( "DecisionHandlerImpl.decide()" );
         // 獲取業務數據
         Integer days = (Integer) execution.getVariable( "請假天數" );
         // 選擇Transition
         if (days > 7 ) {
             return "to 總經理審批" ;
         } else {
             return "to end1" ;
         }
     }
}

  ProcessTest.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void test() {
     // 1,部署流程定義
     InputStream in = this .getClass().getResourceAsStream( "test.jpdl.xml" ); // 當前類所在包中的文件
     processEngine.getRepositoryService() //
             .createDeployment() //
             .addResourceFromInputStream( "test.jpdl.xml" , in) //
             .deploy();
 
     // 2,啟動流程實例
     Map<String, Object> variables = new HashMap<String, Object>();
     // variables.put("請假天數", 10);啟動流程實例后,進行到to 總經理審批環節。
     variables.put( "請假天數" , 3 ); //啟動流程實例后,進行到to end1環節。
     ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey( "test" , variables);
}

  此時,如果variables.put("請假天數", 3);啟動流程實例后,進行到to end1環節。

  此時,如果variables.put("請假天數", 10);啟動流程實例后,進行到to 總經理審批環節。

3. 如果同時配置了expression與Handler,則expression有效,忽略Handler。

  vi. fork、join分支/聚合活動


 

  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ProcessTest {
 
     private ProcessEngine processEngine = Configuration.getProcessEngine();
 
     @Test
     public void test() {
         // 1,部署流程定義
         InputStream in = this .getClass().getResourceAsStream( "test.jpdl.xml" ); // 當前類所在包中的文件
         processEngine.getRepositoryService() //
                 .createDeployment() //
                 .addResourceFromInputStream( "test.jpdl.xml" , in) //
                 .deploy();
 
         // 2,啟動流程實例
         ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey( "test" );
         System.out.println( "processInstanceId = " + pi.getId());
         System.out.println( "當前正在執行的活動:" + pi.findActiveActivityNames());
     }
}

  輸出結果為:

    processInstanceId = test.330007

    當前正在執行的活動:[匯款, 發貨]

    可以看出,匯款和發貨同時執行中。並且,只有當2條路線都到join活動,流程才會繼續往后執行。

  b) 自定義活動(custom)

    i. 在<custom>元素中指定class屬性為指定的類ExternalActivityBehaviourImpl

    ii. 這個類要實現ExternalActivityBehaviour接口,其中有兩個方法:

      1. execute(ActivityExecution):節點的功能代碼

2. signal(ActivityExecution, String, Map):在當前節點等待時,外部發信號時的行為

3. 在execute()方法中,可以調用以下方法對流程進行控制

 

  a) ActivityExecution.waitForSignal():在當前節點等待。
  b) ActivityExecution.takeDefaultTransition():使用默認的Transition離開,當前節點中定義的第一個為默認的。
  c) ActivityExecution.take(String transitionName):使用指定的Transition離開
  d) ActivityExecution.end():結束流程實例
4. 也可以實現ActivityBehaviour接口,只有一個方法execute(ActivityExecution),這樣就不能等待,否則signal時會有類轉換異常。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ExternalActivityBehaviourImpl implements ExternalActivityBehaviour {
 
     // 到達這個活動時執行的方法
     @Override
     public void execute(ActivityExecution execution) throws Exception {
         System.out.println( "已發送信息." ); //此處寫自己要執行的事件
 
         // 默認是執行完代碼后離開當前活動,不會執行signal方法,也可以寫如下代碼
         // execution.takeDefaultTransition(); // 離開當前活動
 
         // // 使用指定名稱的Transition離開當前活動
         // execution.take(transitionName);
 
         // 執行完后不要離開,而是要等待外部調用signal()方法時才離開
         execution.waitForSignal();
     }
 
     // 調用signal()方法離開當前節點前執行的方法(如果在execute()中直接離開當前節點了,這個方法就不會被執行)
     @Override
     public void signal(ActivityExecution execution, String signalName, Map<String, ?> parameters) throws Exception {
         System.out.println( "ExternalActivityBehaviourImpl.signal()" );
     }
}

  

3.事件

a) 在根元素中,或在節點元素中,使用<on event="">元素指定事件,其中event屬性代表事件的類型。

b) 在<on>中用子元素<event-listener class="EventListenerImpl" />,指定處理的類,要求指定的類要實現EventListener接口

c) 事件類型:

i. <on>元素放在根元素(<process>)中,可以指定event為start或end,表示流程的開始與結束。

ii. <on>元素放在節點元素中,可以指定event為start或end,表示節點的進入與離開

iii. 在Start節點中只有end事件,在End節點中只有start事件。

iv. 在<transition>元素中直接寫<event-listener class="">,就是配置事件。(因為在這里只有一個事件,所以不用寫on與類型)

v. 在<task>元素中還可以配置assign事件,是在分配任務時觸發的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version= "1.0" encoding= "UTF-8" ?>
 
<process name= "test" xmlns= "http://jbpm.org/4.4/jpdl" >
 
     <!-- 流程實例的啟動事件 -->
     <on event= "start" >
         <event-listener class = "cn.grace.EventListenerImpl" ></event-listener>
     </on>
     <!-- 流程實例的結束事件 -->
     <on event= "end" >
         <event-listener class = "cn.grace.EventListenerImpl" ></event-listener>
     </on>
 
     <start name= "start1" g= "86,69,7,1" >
         <!-- 開始活動中只有離開活動的事件 -->
         <on event= "end" >
             <event-listener class = "cn.grace.EventListenerImpl" ></event-listener>
         </on>
         <transition name= "to task1" to= "task1" g= "-53,-17" />
     </start>
 
     <task name= "task1" g= "61,171,92,52" assignee= "張三" >
         <!-- 進入活動的事件 -->
         <on event= "start" >
             <event-listener class = "cn.grace.EventListenerImpl" ></event-listener>
         </on>
         <!--離開活動的事件 -->
         <on event= "end" >
             <event-listener class = "cn.grace.EventListenerImpl" ></event-listener>
         </on>
         <transition name= "to end1" to= "end1" g= "-47,-17" />
     </task>
 
     <end name= "end1" g= "86,272,48,48" >
         <!-- 結束活動中只有進入活動的事件 -->
         <on event= "start" >
             <event-listener class = "cn.grace.EventListenerImpl" ></event-listener>
         </on>
     </end>
</process>

  根據上述.jpdl.xml和對應的.png圖,啟動流程實例會執行3次EventListenerImpl事件,結束流程實例也會執行3次EventListenerImpl事件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM