1. 程式人生 > >Activiti的學習(六)——閘道器

Activiti的學習(六)——閘道器

閘道器用來控制流程的流向。

閘道器顯示成菱形圖形,內部有有一個小圖示。 圖標表示閘道器的型別。

一、排他閘道器(ExclusiveGateWay)

排他閘道器(也叫異或(XOR)閘道器,或更技術性的叫法 基於資料的排他閘道器), 用來在流程中實現決策。

圖形標記

排他閘道器顯示成一個普通閘道器(比如,菱形圖形), 內部是一個“X”圖示,表示異或(XOR)語義。 注意,沒有內部圖示的閘道器,預設為排他閘道器。 BPMN 2.0規範不允許在同一個流程定義中同時使用沒有X和有X的菱形圖形。

XML內容

排他閘道器的XML內容是很直接的:用一行定義了閘道器, 條件表示式定義在外出順序流中。 參考條件順序流 獲得這些表示式的可用配置。

對應的XML內容如下:

<exclusiveGatewayid="exclusiveGw"name="Exclusive Gateway"/>
<sequenceFlowid="flow2"sourceRef="exclusiveGw"targetRef="theTask1">  
        <conditionExpressionxsi:type="tFormalExpression">${input == 1}</conditionExpression> 
</sequenceFlow>	
<sequenceFlowid="flow3"sourceRef="exclusiveGw"targetRef="theTask2">    
        <conditionExpressionxsi:type="tFormalExpression">${input == 2}</conditionExpression> 
</sequenceFlow>
<sequenceFlowid="flow4"sourceRef="exclusiveGw"targetRef="theTask3">  
        <conditionExpressionxsi:type="tFormalExpression">${input == 3}</conditionExpression> 
</sequenceFlow>

說明:

  • 一個排他閘道器對應一個以上的順序流
  • 由排他閘道器流出的順序流都有個conditionExpression元素,在內部維護返回boolean型別的決策結果。
  • 決策閘道器只會返回一條結果。當流程執行到排他閘道器時,流程引擎會自動檢索網關出口,從上到下檢索如果發現第一條決策結果為true或者沒有設定條件的(預設為成立),則流出。
  • 如果沒有任何一個出口符合條件則丟擲異常。

設計流程圖,使用排他閘道器

執行流程,由框架根據設定的流程變數選擇執行其中的一個分支

/**
 * 排他閘道器測試
 */
public class ExclusiveGateWayTest {

	ProcessEngine pe = null;

	@Before
	public void init() {
		pe = ProcessEngines.getDefaultProcessEngine();
	}
	
	/**
	 * 01-部署流程定義
	 */
	@Test
	public void test1() {
		DeploymentBuilder deploymentBuilder = pe.getRepositoryService().createDeployment();
		deploymentBuilder.addClasspathResource("com/activiti/ExclusiveGateWay/ExclusiveGateWay.bpmn");
		deploymentBuilder.addClasspathResource("com/activiti/ExclusiveGateWay/ExclusiveGateWay.png");
		Deployment deployment = deploymentBuilder.deploy();
		System.out.println("流程定義部署成功...");
	}
	

	/**
	 * 02-查詢流程定義列表
	 */
	@Test
	public void test2() {
		// 流程定義查詢物件,用於查詢表act_re_procdef
		ProcessDefinitionQuery query = pe.getRepositoryService().createProcessDefinitionQuery();
		// 新增排序條件
		query.orderByProcessDefinitionVersion().desc();
		// 新增分頁查詢
		query.listPage(0, 10);
		List<ProcessDefinition> list = query.list();
		for (ProcessDefinition pd : list) {
			System.out.println(pd.getId() + "--" + pd.getName() + "--key:" + pd.getKey());
		}
	}
	
	/**
	 * 03-啟動流程例項
	 */
	@Test
	public void test3(){
		String processDefinitionId = "ExclusiveGateWayTest:1:102504";
		pe.getRuntimeService().startProcessInstanceById(processDefinitionId);
		System.out.println("流程例項啟動成功.....");
	}
	
	/**
	 * 04-查詢個人任務列表
	 */
	@Test
	public void test4() {
		TaskQuery query = pe.getTaskService().createTaskQuery();
		String assignee = "小B";
		query.taskAssignee(assignee);
		List<Task> list = query.list();
		for (Task task : list) {
			System.out.println("待辦任務ID:"+task.getId());
			System.out.println("待辦任務名稱:"+task.getName());
			System.out.println("任務建立時間:"+task.getCreateTime());
			System.out.println("任務辦理人:"+task.getAssignee());
			System.out.println("流程例項ID:"+task.getProcessInstanceId());
			System.out.println("執行物件ID:"+task.getExecutionId());
			System.out.println("流程定義ID:"+task.getProcessDefinitionId());
			Map<String, Object> map = task.getProcessVariables();
			Set<Entry<String, Object>> entrySet = map.entrySet();
			for (Entry<String, Object> entry : entrySet) {
				System.out.println(entry.getKey());
				System.out.println(entry.getValue());
			}
		}
	}
	
	/**
	 * 05-辦理任務,設定流程變數
	 */
	@Test
	public void test5(){
		String taskId = "107504";
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("money", 800);
		pe.getTaskService().complete(taskId, variables);
		System.out.println("辦理任務完成....");
	}
}

二、並行閘道器(parallelGateWay)

閘道器也可以表示流程中的並行情況。最簡單的並行閘道器是parallelGateWay,它允許將流程 分成多條分支,也可以把多條分支 匯聚到一起。

圖形標記

並行閘道器顯示成一個普通閘道器(菱形)內部是一個“加號”圖示, 表示“與(AND)”語義。

當兩個任務都完成時,第二個並行閘道器會匯聚兩個分支,因為它只有一條外出連線, 不會建立並行分支, 只會建立歸檔訂單任務。

說明:

  1. 並行閘道器的功能是基於進入和外出的順序流的:

分支(fork) 並行後的所有外出順序流,為每個順序流都建立一個併發分支。

匯聚(join) 所有到達並行閘道器,在此等待的進入分支, 直到所有進入順序流的分支都到達以後, 流程就會通過匯聚閘道器。

  1. 並行閘道器的進入和外出都是使用相同節點標示
  2. 如果同一個並行閘道器有多個進入和多個外出順序流, 它就同時具有分支和匯聚功能。 這時,閘道器會先匯聚所有進入的順序流,然後再切分成多個並行分支。
  3. 並行閘道器不會解析條件。 即使順序流中定義了條件,也會被忽略。

並行閘道器不需要是“平衡的”(比如, 對應並行閘道器的進入和外出節點數目相等)。如圖中標示是合法的:

設計流程圖,使用並行閘道器

測試並行閘道器

/**
 * 並行閘道器測試
 */
public class ParallelGateWayTest {

	ProcessEngine pe = null;

	@Before
	public void init() {
		pe = ProcessEngines.getDefaultProcessEngine();
	}
	
	/**
	 * 01-部署流程定義
	 */
	@Test
	public void test1() {
		DeploymentBuilder deploymentBuilder = pe.getRepositoryService().createDeployment();
		deploymentBuilder.addClasspathResource("com/activiti/parallelGateWay/ParallelGateWay.bpmn");
		deploymentBuilder.addClasspathResource("com/activiti/parallelGateWay/ParallelGateWay.png");
		Deployment deployment = deploymentBuilder.deploy();
		System.out.println("流程定義部署成功...");
	}
	

	/**
	 * 02-查詢流程定義列表
	 */
	@Test
	public void test2() {
		// 流程定義查詢物件,用於查詢表act_re_procdef
		ProcessDefinitionQuery query = pe.getRepositoryService().createProcessDefinitionQuery();
		// 新增排序條件
		query.orderByProcessDefinitionVersion().desc();
		// 新增分頁查詢
		query.listPage(0, 10);
		List<ProcessDefinition> list = query.list();
		for (ProcessDefinition pd : list) {
			System.out.println(pd.getId() + "--" + pd.getName() + "--key:" + pd.getKey());
		}
	}
	
	/**
	 * 03-啟動流程例項
	 */
	@Test
	public void test3(){
		String processDefinitionId = "parallelGateWayTest:1:112504";
		pe.getRuntimeService().startProcessInstanceById(processDefinitionId);
		System.out.println("流程例項啟動成功.....");
	}
	
	/**
	 * 04-查詢個人任務列表
	 */
	@Test
	public void test4() {
		TaskQuery query = pe.getTaskService().createTaskQuery();
		String assignee = "賣家A";
		query.taskAssignee(assignee);
		List<Task> list = query.list();
		for (Task task : list) {
			System.out.println("待辦任務ID:"+task.getId());
			System.out.println("待辦任務名稱:"+task.getName());
			System.out.println("任務建立時間:"+task.getCreateTime());
			System.out.println("任務辦理人:"+task.getAssignee());
			System.out.println("流程例項ID:"+task.getProcessInstanceId());
			System.out.println("執行物件ID:"+task.getExecutionId());
			System.out.println("流程定義ID:"+task.getProcessDefinitionId());
			Map<String, Object> map = task.getProcessVariables();
			Set<Entry<String, Object>> entrySet = map.entrySet();
			for (Entry<String, Object> entry : entrySet) {
				System.out.println(entry.getKey());
				System.out.println(entry.getValue());
			}
		}
	}
	
	/**
	 * 05-辦理任務
	 */
	@Test
	public void test5(){
		String taskId = "120002";
		pe.getTaskService().complete(taskId);
		System.out.println("辦理任務完成....");
	}
}