Activiti工作流總結(常用部分)

2020-08-12 01:58:25

Activiti工作流

一、工作流的概念

1.生活中常見的工作流

1,請假
2,報銷
3,申請轉武漢戶口
4,購物

2.概述

工作流(Workflow),就是「業務過程的部分或整體在計算機應用環境下的自動化」,它主要解決的是「使在多個參與者之間按照某種預定義的規則傳遞文件、資訊或任務的過程自動進行,從而實現某個預期的業務目標,或者促使此目標的實現」。

工作流管理系統(Workflow Management System, WfMS)是一個軟件系統,它完成工作量的定義和管理,並按照在系統中預先定義好的工作流規則進行工作流範例的執行。工作流管理系統不是企業的業務系統,而是爲企業的業務系統的執行提供了一個軟體的支撐環境。

工作流管理聯盟(WfMC,Workflow Management Coalition)給出的關於工作流管理系統的定義是:工作流管理系統是一個軟件系統,它通過執行經過計算的流程定義去支援一批專門設定的業務流程。工作流管理系統被用來定義、管理、和執行工作流程。

工作流管理系統的目標:管理工作的流程以確保工作在正確的時間被期望的人員所執行——在自動化進行的業務過程中插入人工的執行和幹預。

二、Activiti介紹

1,概述

Activiti5是由Alfresco軟體在2010年5月17日發佈的業務流程管理(BPM)框架,它是覆蓋了業務流程管理、工作流、服務共同作業等領域的一個開源的、靈活的、易擴充套件的可執行流程語言框架。Activiti基於Apache許可的開源BPM平臺,創始人Tom Baeyens是JBoss jBPM的專案架構師,它特色是提供了eclipse外掛,開發人員可以通過外掛直接繪畫出業務

2,工作流引擎

ProcessEngine物件,這是Activiti工作的核心。負責生成流程執行時的各種範例及數據、監控和管理流程的執行。

3,BPMN

業務流程建模與標註(Business Process Model and Notation,BPMN) ,描述流程的基本符號,包括這些圖元如何組合成一個業務流程圖(Business Process Diagram)

4,數據庫

1)Activiti數據庫支援:

Activiti的後臺是有數據庫的支援,所有的表都以ACT_開頭。 第二部分是表示表的用途的兩個字母標識。 用途也和服務的API對應。
ACT_RE_: 'RE’表示repository。 這個字首的表包含了流程定義和流程靜態資源 (圖片,規則,等等)。
ACT_RU_
: 'RU’表示runtime。 這些執行時的表,包含流程範例,任務,變數,非同步任務,等執行中的數據。 Activiti只在流程範例執行過程中儲存這些數據, 在流程結束時就會刪除這些記錄。 這樣執行時表可以一直很小速度很快。
ACT_ID_: 'ID’表示identity。 這些表包含身份資訊,比如使用者,組等等。
ACT_HI_
: 'HI’表示history。 這些表包含歷史數據,比如歷史流程範例, 變數,任務等等。
ACT_GE_*: 通用數據, 用於不同場景下,如存放資原始檔。

2)資源庫流程規則表

  1. act_re_deployment 部署資訊表
  2. act_re_model 流程設計模型部署表
  3. act_re_procdef 流程定義數據表
    2:執行時數據庫表
  4. act_ru_execution 執行時流程執行範例表
  5. act_ru_identitylink 執行時流程人員表,主要儲存任務節點與參與者的相關資訊
  6. act_ru_task 執行時任務節點表
  7. act_ru_variable 執行時流程變數數據表
    3:歷史數據庫表
  8. act_hi_actinst 歷史節點表
  9. act_hi_attachment 歷史附件表
  10. act_hi_comment 歷史意見表
  11. act_hi_identitylink 歷史流程人員表
  12. act_hi_detail 歷史詳情表,提供歷史變數的查詢
  13. act_hi_procinst 歷史流程範例表
  14. act_hi_taskinst 歷史任務範例表
  15. act_hi_varinst 歷史變數表
    4:組織機構表
  16. act_id_group 使用者組資訊表
  17. act_id_info 使用者擴充套件資訊表
  18. act_id_membership 使用者與使用者組對應資訊表
  19. act_id_user 使用者資訊表
    這四張表很常見,基本的組織機構管理,關於使用者認證方面建議還是自己開發一套,元件自帶的功能太簡單,使用中有很多需求難以滿足
    5:通用數據表
  20. act_ge_bytearray 二進制數據表
  21. act_ge_property 屬性數據表儲存整個流程引擎級別的數據,初始化表結構時,會預設插入三條記錄,

3)與Service的對應

#RepositoryService
SELECT * FROM act_ge_bytearray; #二進制檔案表
SELECT * FROM act_re_deployment;#流程部署表
SELECT * FROM act_re_procdef;#流程定義
SELECT * FROM act_ge_property;#工作流的ID演算法和版本資訊表

#RuntimeService TaskService
SELECT * FROM act_ru_execution;#流程啓動一次只要沒有執行完,就會有一條數據
SELECT * FROM act_ru_task;#可能有多條數據
SELECT * FROM act_ru_variable;#記錄流程執行時的流程變數
SELECT * FROM act_ru_identitylink;#存放流程辦理人的資訊

#HistroyService
SELECT * FROM act_hi_procinst;#歷史流程範例
SELECT * FROM act_hi_taskinst;#歷史任務範例
SELECT * FROM act_hi_actinst;#歷史活動節點表
SELECT * FROM act_hi_varinst;#歷史流程變數表
SELECT * FROM act_hi_identitylink;##歷史辦理人表
SELECT * FROM act_hi_comment;#批註表
SELECT * FROM act_hi_attachment;#附件表

#IdentityService
SELECT * FROM act_id_group #角色
SELECT * FROM act_id_membership#使用者和角色之間的關係
SELECT * FROM act_id_info#使用者的詳細資訊
SELECT * FROM act_id_user#使用者表

三、Activiti5開發環境

1、準備工作

1.建立專案

2.設定pom.xml

3.設定log4j.properties

2、初始化數據

1).建立數據庫

2).建立類去初始化表方式一

	@Test
	public void initTables() {
		//建立數據源
		DriverManagerDataSource dataSource=new DriverManagerDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/0705activiti");
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		
		// 建立流程引擎的設定
		ProcessEngineConfiguration configuration = ProcessEngineConfiguration
				.createStandaloneProcessEngineConfiguration();
		configuration.setJdbcDriver("com.mysql.jdbc.Driver");
		configuration.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/0705activiti");
		configuration.setJdbcUsername("root");
		configuration.setJdbcPassword("123456");
//		configuration.setDataSource(dataSource);
		/** 
		 * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE  如果數據庫裏面沒有activit的表,也不會建立
		 * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP 建立表,使用完之後刪除
		 * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE  如果數據庫裏面沒有表,就建立
		 * 
		 * dorp-create 代表如果數據庫裏面有表,那麼先刪除再建立
		 * 
		 */
		//設定表的初始化的方式
		configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
		
		//得到流程引擎
		ProcessEngine processEngine=configuration.buildProcessEngine();
		System.out.println(processEngine);
	}

3).建立類去初始化表方式二

建立activiti.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd">
	
	
   <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
   		<property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
   		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/0705activiti"></property>
   		<property name="jdbcUsername" value="root"></property>
   		<property name="jdbcPassword" value="123456"></property>
		<!--    		
		flase: 預設值。activiti在啓動時,會對比數據庫表中儲存的版本,如果沒有表或者版本不匹配,將拋出異常。
		true: activiti會對數據庫中所有表進行更新操作。如果表不存在,則自動建立。
		create_drop: 在activiti啓動時建立表,在關閉時刪除表(必須手動關閉引擎,才能 纔能刪除表)。
		drop-create: 在activiti啓動時刪除原來的舊錶,然後在建立新表(不需要手動關閉引擎)。 -->
   		<property name="databaseSchemaUpdate" value="drop-create"></property>
   </bean>
</beans>

建立方法


	@Test
	public void intiTables2() {
		ProcessEngineConfiguration configuration = ProcessEngineConfiguration
				.createProcessEngineConfigurationFromResource("/activiti.cfg.xmls");
		// 得到流程引擎
		ProcessEngine processEngine = configuration.buildProcessEngine();
		System.out.println(processEngine);

	}

4).建立類去初始化表方式三

	@Test
	public void intiTables3() {
		//必須建立activiti.cfg.xml  並設定好數據庫的資訊
		ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
		System.out.println(processEngine);
	}

四、activiti.cfg.xml的說明

1,Activiti核心組態檔,設定流程引擎建立工具的基本參數和數據庫連線池參數。

定義數據庫設定參數:
1,jdbcUrl: 數據庫的JDBC URL。
2,jdbcDriver: 對應不同數據庫型別的驅動。
3,jdbcUsername: 連線數據庫的使用者名稱。
4,jdbcPassword: 連線數據庫的密碼。
基於JDBC參數設定的數據庫連線 會使用預設的MyBatis連線池。 下面 下麪的參數可以用來設定連線池(來自MyBatis參數):
1,jdbcMaxActiveConnections: 連線池中處於被使用狀態的連線的最大值。預設爲10。
2,jdbcMaxIdleConnections: 連線池中處於空閒狀態的連線的最大值。
3,jdbcMaxCheckoutTime: 連線被取出使用的最長時間,超過時間會被強制回收。 預設爲20000(20秒)。
4,jdbcMaxWaitTime: 這是一個底層設定,讓連線池可以在長時間無法獲得連線時, 列印一條日誌,並重新嘗試獲取一個連線。(避免因爲錯誤設定導致沉默的操作失敗)。 預設爲20000(20秒)。
5,dataSource 可以設定其它數據源
6,databaseSchemaUpdate 設定數據庫表的建立策略

2,範例數據庫設定:

在这里插入图片描述

3,使用其它數據源:

在这里插入图片描述

五、核心API

ProcessEngine
說明:
1)在Activiti中最核心的類,其他的類都是由他而來。
2)產生方式。

1,ProcessEngine獲取方式

	@Test
	public void intiTables3() {
		//必須建立activiti.cfg.xml  並設定好數據庫的資訊
		ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
		System.out.println(processEngine);
		//流程圖的部署  修改  刪除的伺服器 act_ge_bytearray, act_re_deployment, act_re_model, act_re_procdef
		RepositoryService repositoryService = processEngine.getRepositoryService();
		//流程的執行 act_ru_event_subscr, act_ru_execution, act_ru_identitylink, act_ru_job, act_ru_task, act_ru_variable
		RuntimeService runtimeService = processEngine.getRuntimeService();
		TaskService taskService = processEngine.getTaskService();
		//查詢歷史記錄的伺服器act_hi_actinst, act_hi_attachment, act_hi_comment, act_hi_detail, act_hi_identitylink, act_hi_procinst, act_hi_taskinst, act_hi_varinst
		HistoryService historyService = processEngine.getHistoryService();
		//頁面表單的伺服器[瞭解]
		FormService formService = processEngine.getFormService();
		//對工作流的使用者管理的表的操作act_id_group, act_id_info, act_id_membership, act_id_user
		IdentityService identityService = processEngine.getIdentityService();
		//管理器
		ManagementService managementService = processEngine.getManagementService();
	}

2,RepositoryService

是Activiti的倉庫服務類。所謂的倉庫指流程定義文件的兩個檔案,bpmn檔案和流程圖片。
1)產生方式

2)可以產生DeploymentBuilder,用來定義流程部署的相關參數

3)刪除流程定義

3,RuntimeService

是activiti的流程執行服務類。可以從這個服務類中獲取很多關於流程執行相關的資訊。

4,TaskService

是activiti的任務服務類。可以從這個類中獲取任務的資訊。

5,HistoryService

是activiti的查詢歷史資訊的類。在一個流程執行完成後,這個物件爲我們提供查詢歷史資訊。

6,ProcessDefinition act_re_procdef

流程定義類。可以從這裏獲得資原始檔等。當流程圖被部署之後,查詢出來的數據就是流程定義的數據

7,ProcessInstance act_ru_execution

代表流程定義的執行範例。如範冰冰請了一天的假,她就必須發出一個流程範例的申請。一個流程範例包括了所有的執行節點。我們可以利用這個物件來了解當前流程範例的進度等資訊。流程範例就表示一個流程從開始到結束的最大的流程分支,即一個流程中流程範例只有一個。

8,Execution act_ru_execution

Activiti用這個物件去描述流程執行的每一個節點。在沒有併發的情況下,Execution就是同ProcessInstance。流程按照流程定義的規則執行一次的過程,就可以表示執行物件Execution。
如圖爲ProcessInstance的原始碼,

9,TaskInstance 任務範例act_ru_task

六 HelloWorld程式(模擬流程的執行)

1.畫流程圖

1)畫流程圖

1.画流程图

在这里插入图片描述

2).設定任務的辦理人

在这里插入图片描述

在这里插入图片描述

3).設定流程的ID和NAME

在这里插入图片描述

2.部署流程定義

在这里插入图片描述

3.啓動流程

在这里插入图片描述

4.查詢任務

在这里插入图片描述

5.辦理任務

在这里插入图片描述

七、管理流程定義

功能:對流程的增加 修改 刪除 查詢
act_ge_bytearray act_re_deployment act_re_procdef

1.流程圖

在这里插入图片描述

2.部署流程定義【兩種方式 classpath zip】

//得到流程引擎
	private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
	
	/**
	 * 部署流程使用classpath
	 */
	@Test
	public void deployProcess01() {
		//得到流程部署的service
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		Deployment deploy = repositoryService.createDeployment().name("請假流程001")
		.addClasspathResource("HelloWorld.bpmn")
		.addClasspathResource("HelloWorld.png")
		.deploy();
		System.out.println("部署成功:流程部署ID:"+deploy.getId());
	}
	
	/**
	 * 部署流程使用zip
	 * 流程圖的檔案必須是xxxx.zip結尾
	 */
	@Test
	public void deployProcess02() {
		//如果不加/代表從當前包裏面找檔案 
		InputStream inputStream = this.getClass().getResourceAsStream("/HelloWorld.zip");
		//如果加/代表從classpath的根目錄裏面找檔案
		//InputStream inputStream = this.getClass().getResourceAsStream("/HelloWorld.zip");
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		ZipInputStream zipInputStream =new ZipInputStream(inputStream);
		Deployment deploy = repositoryService.createDeployment().name("請假流程001")
		.addZipInputStream(zipInputStream)//新增流程圖的流
		.deploy();//確定部署
		System.out.println("部署成功,部署ID:"+deploy.getId());
	}
	

3.查詢部署資訊act_re_deployment

/**
	 * 查詢流程部署資訊  act_re_deployment
	 */
	@Test
	public void queryProcessDeploy () {
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		//建立部署資訊的查詢
		String deploymentId="1";
//		Deployment deploy = repositoryService.createDeploymentQuery()
		List<Deployment> list= repositoryService.createDeploymentQuery()
		//條件
		//.deploymentId(deploymentId)  //根據部署ID去查詢
		//.deploymentName(name)//根據部署名稱去查詢
		//.deploymentTenantId(tenantId)//根據tenantId去查詢
//		.deploymentNameLike(nameLike)//根據部署名稱模糊查詢
		//.deploymentTenantIdLike(tenantIdLike)//根據tenantId模糊查詢
		//排序
//		.orderByDeploymentId().asc()  //根據部署ID升序
		//.orderByDeploymenTime().desc() //根據部署時間降序
		//.orderByDeploymentName()//根據部署名稱升序
		//結果集
		.list();  //查詢返回list集合
//		.listPage(firstResult, maxResults)  分頁查詢返回list集合
		//.singleResult(); //返回單個物件
//		.count();
		
		/*System.out.println("部署ID:"+deploy.getId());
		System.out.println("部署名稱:"+deploy.getName());
		System.out.println("部署時間:"+deploy.getDeploymentTime());*/
//		System.out.println(count);
		for (Deployment deployment : list) {
			System.out.println("部署ID:"+deployment.getId());
			System.out.println("部署名稱:"+deployment.getName());
			System.out.println("部署時間:"+deployment.getDeploymentTime());
			System.out.println("########################");
		}
	}


4.查詢流程定義資訊act_re_procdef


	/**
	 * 查詢流程定義
	 */
	@Test
	public void queryProcDef() {
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
		//條件
//		.deploymentId(deploymentId) 根據部署ID查詢
//		.deploymentIds(deploymentIds) 根據部署ID的集合查詢Set<String> deploymentIds
//		.processDefinitionId(processDefinitionId)//根據流程定義IDHelloWorld:1:4
//		.processDefinitionIds(processDefinitionIds)//根據流程定義的IDS查詢
//		.processDefinitionKey(processDefinitionKey)//根據流程定義的的key查詢
//		.processDefinitionKeyLike(processDefinitionKeyLike)//根據流程定義的的key模糊查詢
//		.processDefinitionName(processDefinitionName)//根據流程定義的名稱查詢
//		.processDefinitionNameLike(processDefinitionNameLike)//根據流程定義的名稱模糊查詢
//		.processDefinitionResourceName(resourceName)//根據流程圖的BPMN檔名查詢
//		.processDefinitionResourceNameLike(resourceNameLike)//根據流程圖的BPMN檔名模糊查詢
//		.processDefinitionVersion(processDefinitionVersion)//根據流程定義的版本查詢
//		.processDefinitionVersionGreaterThan(processDefinitionVersion)//version>num
//		.processDefinitionVersionGreaterThanOrEquals(processDefinitionVersion)//version>=num
//		.processDefinitionVersionLowerThan(processDefinitionVersion)//version<num
//		.processDefinitionVersionLowerThanOrEquals(processDefinitionVersion)//version<=num
		//排序
//		.orderByDeploymentId()
//		.orderByProcessDefinitionId()
//		.orderByProcessDefinitionKey()
//		.orderByProcessDefinitionName()
//		.orderByProcessDefinitionVersion()
		//結果集
		.list();
//		.listPage(firstResult, maxResults)\
//		.count()
//		.singleResult()
		if(null!=list&&list.size()>0) {
			for (ProcessDefinition pd : list) {
				System.out.println("流程定義ID:"+pd.getId());
				System.out.println("流程部署ID:"+pd.getDeploymentId());
				System.out.println("流程定義KEY:"+pd.getKey());
				System.out.println("流程定義的名稱:"+pd.getName());
				System.out.println("流程定義的bpmn檔名:"+pd.getResourceName());//bpmn的name
				System.out.println("流程圖片名:"+pd.getDiagramResourceName());//png的name
				System.out.println("流程定義的版本號:"+pd.getVersion());
				System.out.println("##################");
			}
		}
		
	}

5.刪除流程定義資訊

	/**
	 * 刪除流程定義
	 */
	@Test
	public void deleteProcessDef() {
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		String deploymentId="2501";
		//根據流程部署id刪除流程定義 如果當前id的流程正在執行,那麼會報錯
		//repositoryService.deleteDeployment(deploymentId);
		//根據流程部署id刪除刪除流程定義 如果當前id的流程正在執行,會把正在執行的流程數據刪除 act_ru_*和act_hi_*表裏面的數據
		repositoryService.deleteDeployment(deploymentId, true);
//		repositoryService.deleteDeploymentCascade(deploymentId);==repositoryService.deleteDeployment(deploymentId, true);
		System.out.println("刪除成功");
	}

6.修改流程定義資訊

修改流程圖之後重新部署,只要key不變,它的版本號就會+1

在这里插入图片描述

7.查詢流程圖

	/**
	 * 查詢流程圖  根據流程定義ID
	 */
	@Test
	public void viewProcessImg() {
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		String processDefinitionId="HelloWorld:1:4";
		InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);
		
		File file=new File("d:/HelloWorld.png");
		try {
			BufferedOutputStream outputStream=new BufferedOutputStream(new FileOutputStream(file));
			int len=0;
			byte[] b=new byte[1024];
			while((len=inputStream.read(b))!=-1) {
				outputStream.write(b, 0, len);
				outputStream.flush();
			}
			outputStream.close();
			inputStream.close();
			System.out.println("查詢成功");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 查詢流程圖  根據流流程部署ID
	 */
	@Test
	public void viewProcessImg2() {
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		//根據流程部署ID查詢流程定義物件
		String deploymentId="1";
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
		//從流程定義物件裏面查詢出流程定義ID
		String processDefinitionId=processDefinition.getId();
		InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);
		
		File file=new File("d:/"+processDefinition.getDiagramResourceName());
		try {
			BufferedOutputStream outputStream=new BufferedOutputStream(new FileOutputStream(file));
			int len=0;
			byte[] b=new byte[1024];
			while((len=inputStream.read(b))!=-1) {
				outputStream.write(b, 0, len);
				outputStream.flush();
			}
			outputStream.close();
			inputStream.close();
			System.out.println("查詢成功");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

8.附加功能:查詢最新版本的流程定義

	/**
	 * 查詢最新的流程定義
	 */
	@Test
	public void queryNewProcessDef() {
		Map<String, ProcessDefinition> map = new HashMap<>();

		// 查詢所有的流程定義根據版本號升序
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
				.orderByProcessDefinitionVersion().asc().list();
		if(null!=list&&list.size()>0) {
			for (ProcessDefinition pd : list) {
				map.put(pd.getKey(), pd);
			}
		}
		//回圈map集合
		Collection<ProcessDefinition> values = map.values();
		for (ProcessDefinition pd : values) {
			System.out.println("流程定義ID:" + pd.getId());
			System.out.println("流程部署ID:" + pd.getDeploymentId());
			System.out.println("流程定義KEY:" + pd.getKey());
			System.out.println("流程定義的名稱:" + pd.getName());
			System.out.println("流程定義的bpmn檔名:" + pd.getResourceName());// bpmn的name
			System.out.println("流程圖片名:" + pd.getDiagramResourceName());// png的name
			System.out.println("流程定義的版本號:" + pd.getVersion());
			System.out.println("##################");
		}
	}


9.附加功能:刪除流程定義(刪除key相同的所有不同版本的流程定義)

	/**
	 * 已知key 附加功能:刪除流程定義(刪除key相同的所有不同版本的流程定義)
	 */
	public void deleteAllSameVersion() {
		String processDefinitionKey = "HelloWorld";
		RepositoryService repositoryService = this.processEngine.getRepositoryService();
		// 根據流程定義的key查詢流程集合
		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
				.processDefinitionKey(processDefinitionKey).list();

		if (null != list && list.size() > 0) {
			for (ProcessDefinition pd : list) {
				repositoryService.deleteDeployment(pd.getDeploymentId(), true);

			}
		}

	}

八、流程範例、任務的執行

1,流程圖

在这里插入图片描述

2,部署流程定義

3,啓動流程範例

	/**
	 * 啓動流程
	 */
	@Test
	public void startProcess() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
//		runtimeService.startProcessInstanceById(processDefinitionId)//根據流程定義ID啓動流程
		/**
		 * 參數1:流程定義ID
		 * 參數2:Map<String,Object> 流程變數
		 */
//		runtimeService.startProcessInstanceById(processDefinitionId, variables);
		/**
		 * 參數1:流程定義ID
		 * 參數2:String 業務ID 把業務ID和流程執行範例進行系結
		 */
//		runtimeService.startProcessInstanceById(processDefinitionId, businessKey);
		/**
		 * 參數1:流程定義ID
		 * 參數2:String 業務ID 把業務ID和流程執行範例進行系結
		 * 參數3:Map<String,Object> 流程變數
		 */
//		runtimeService.startProcessInstanceById(processDefinitionId, businessKey, variables)
//		
//		runtimeService.startProcessInstanceByKey(processDefinitionKey)//根據流程定義的key啓動
		/**
		 * 參數1:流程定義的Key
		 * 參數2:Map<String,Object> 流程變數
		 */
//		runtimeService.startProcessInstanceByKey(processDefinitionKey, variables)
		/**
		 * 參數1:流程定義Key
		 * 參數2:String 業務ID 把業務ID和流程執行範例進行系結
		 */
//		runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey);
		/**
		 * 參數1:流程定義Key
		 * 參數2:String 業務ID 把業務ID和流程執行範例進行系結
		 * 參數3:Map<String,Object> 流程變數
		 */
//		runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey, variables)
		
		//範例開發中使用的
		//runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey, variables)
		//runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey);
		
		String processDefinitionKey="HelloWorld";
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
		System.out.println("流程啓動成功:"+processInstance.getId()+"   "+processInstance.getProcessDefinitionId()+"  "+processInstance.getProcessInstanceId());
		
	}

4,查詢我的個人任務

	/**
	 * 查詢我的個人任務act_ru_task
	 */
	@Test
	public void queryMyTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String assignee="張三";
		List<Task> list = taskService.createTaskQuery()
		//條件
		.taskAssignee(assignee)//根據任務辦理人查詢任務
//		.deploymentId(deploymentId)//根據部署ID查詢 where id=id
//		.deploymentIdIn(deploymentIds)//根據部署ID集合查詢   where id in (1,2,3,4)
//		.executionId(executionId)//根據執行範例ID
//		.processDefinitionId(processDefinitionId)//根據流程定義ID
//		.processDefinitionKey(processDefinitionKey)//根據流程定義的key
//		.processDefinitionKeyIn(processDefinitionKeys)
//		.processDefinitionKeyLike(processDefinitionKeyLike)
//		.processDefinitionName(processDefinitionName)
//		.processDefinitionNameLike(processDefinitionNameLike)
//		.processInstanceBusinessKey(processInstanceBusinessKey)
		//排序
		.orderByTaskCreateTime().desc()
		//結果集
		.list();
//		.listPage(firstResult, maxResults)
//		.count();
//		.singleResult()
		
		if(null!=list&&list.size()>0) {
			for (Task task : list) {
				System.out.println("任務ID:"+task.getId());
				System.out.println("任務辦理人:"+task.getAssignee());
				System.out.println("執行範例ID:"+task.getExecutionId());
				System.out.println("任務名稱:"+task.getName());
				System.out.println("流程定義ID:"+task.getProcessDefinitionId());
				System.out.println("流程範例ID:"+task.getProcessInstanceId());
				System.out.println("任務建立時間:"+task.getCreateTime());
				System.out.println("####################");
			}
		}
	}
	
	

5,辦理任務

	/**
	 * 辦理任務
	 */
	@Test
	public void completeTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String taskId="2504";
		//根據任務ID去完成任務
		taskService.complete(taskId);
		//根據任務ID去完成任務並指定流程變數
//		taskService.complete(taskId, variables);
		System.out.println("任務完成");
	}
	

6,查詢流程狀態(判斷流程正在執行,還是結束)

	/**
	 * 判斷流程是否結束 作用:更新業務表裏面的狀態
	 */
	@Test
	public void isComplete() {
		// 已知流程範例ID
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String processInstanceId = "2501";
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		if (null != processInstance) {
			System.out.println("流程未結束");
		} else {
			System.out.println("流程已結束");
		}

		//已知任務ID 5002 [瞭解]
		//根據任務ID查詢任務範例物件
		/*TaskService taskService = this.processEngine.getTaskService();
		String taskId="5002";
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		//從任務範例裏面取出流程範例ID
		String processInstanceId2 = task.getProcessInstanceId();
		//使用流程範例ID去流程範例表裏面查詢有沒有數據
		ProcessInstanceQuery processInstance2 = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId2);
		if (null != processInstance2) {
			System.out.println("流程未結束");
		} else {
			System.out.println("流程已結束");
		}*/
		
		
		
	}

7,查詢正在執行的流程範例

	/**
	 * 7,查詢當前的流程範例 act_ru_execution
	 * 
	 */
	@Test
	public void queryProcessInstance() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
		if(null!=list&&list.size()>0) {
			for (ProcessInstance pi : list) {
				System.out.println("執行範例ID:"+pi.getId());
				System.out.println("流程定義ID:"+pi.getProcessDefinitionId());
				System.out.println("流程範例ID:"+pi.getProcessInstanceId());
				System.out.println("########################");
			}
		}
	}

8,總結

1)Execution 執行物件

按流程定義的規則執行一次的過程.
對應的表:
act_ru_execution, 正在執行的資訊
act_hi_procinst,已經執行完的歷史流程範例資訊
act_hi_actinst,存放歷史所有完成的活動

2)ProcessInstance 流程範例

特指流程從開始到結束的那個最大的執行分支,一個執行的流程中,流程範例只有1個。
注意
(1)如果是單例流程,執行物件ID就是流程範例ID
(2)如果一個流程有分支和聚合,那麼執行物件ID和流程範例ID就不相同
(3)一個流程中,流程範例只有1個,執行物件可以存在多個。

3)Task 任務

執行到某任務環節時生成的任務資訊。
對應的表:
act_ru_task,正在執行的任務資訊
act_hi_taskinst,已經執行完的歷史任務資訊

4)相關ID總結

部署ID —act_re_deployment id
流程定義ID act_re_procdef id
流程範例ID act_ru_execution id
執行範例ID act_ru_task execution_id
任務ID act_run_task id

九、流程變數

1:流程圖

在这里插入图片描述

流程變數在整個工作流中扮演很重要的作用。例如:請假流程中有請假天數、請假原因等一些參數都爲流程變數的範圍。流程變數的作用域範圍是只對應一個流程範例。也就是說各個流程範例的流程變數是不相互影響的。流程範例結束完成以後流程變數還儲存在數據庫中(存放到流程變數的歷史表中)。

設定流程變數的值

存在形式 key —value

2:部署流程定義

3:啓動流程範例並設定流程變數

	/**
	 * 啓動流程
	 */
	@Test
	public void startProcess() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String processDefinitionKey = "HelloWorld";
//		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
		//建立流程變數物件
		Map<String,Object> variables=new HashMap<>();
		variables.put("請假天數", 5);//int
		variables.put("請假原因", "約會");
		variables.put("請假時間", new Date());
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
		System.out.println("流程啓動成功:" + processInstance.getId() + "   " + processInstance.getProcessDefinitionId() + "  "
				+ processInstance.getProcessInstanceId());

	}

4:設定流程變數

	/**
	 * 設定流程變數1
	 */
	@Test
	public void setVariables() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String executionId="2501";
		//runtimeService.setVariable(executionId, "請假人", "小明");
		Map<String,Object> variables=new HashMap<>();
		variables.put("請假天數", 6);//int
		variables.put("請假原因", "約會妹子");
		variables.put("請假時間", new Date());
		variables.put("使用者物件", new User(1,"小明"));
		runtimeService.setVariables(executionId, variables);
		System.out.println("流程變數設定成功");
		
		
	}
	/**
	 * 設定流程變數2
	 */
	@Test
	public void setVariables2() {
		TaskService taskService = this.processEngine.getTaskService();
		
		String taskId="2507";
		//runtimeService.setVariable(executionId, "請假人", "小明");
		Map<String,Object> variables=new HashMap<>();
		variables.put("任務ID設定的", 9);//int
//		taskService.setVariable(taskId, variableName, value);
		taskService.setVariables(taskId, variables);
		System.out.println("流程變數設定成功");
	}

5:獲取流程變數

/**
	 * 獲取流程變數
	 */
	@Test
	public void getVariables() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String executionId="2501";
		Integer days=(Integer) runtimeService.getVariable(executionId, "請假天數");
		Date date=(Date) runtimeService.getVariable(executionId, "請假時間");
		User user=(User) runtimeService.getVariable(executionId, "使用者物件");
		System.out.println(days);
		System.out.println(date.toLocaleString());
		System.out.println(user.getId()+"  "+user.getName());
		

	}

6:流程變數的支援的型別

在这里插入图片描述

7:總結

1):流程變數

在流程執行或者任務執行的過程中,用於設定和獲取變數,使用流程變數在流程傳遞的過程中傳遞業務參數。
對應的表:
act_ru_variable:正在執行的流程變數表
act_hi_varinst:流程變數歷史表

2):擴充套件知識:setVariable和setVariableLocal的區別

setVariable:設定流程變數的時候,流程變數名稱相同的時候,後一次的值替換前一次的值,而且可以看到TASK_ID的欄位不會存放任務ID的值
setVariableLocal:
1:設定流程變數的時候,針對當前活動的節點設定流程變數,如果一個流程中存在2個活動節點,對每個活動節點都設定流程變數,即使流程變數的名稱相同,後一次的版本的值也不會替換前一次版本的值,它會使用不同的任務ID作爲標識,存放2個流程變數值,而且可以看到TASK_ID的欄位會存放任務ID的值 例如act_hi_varinst 表的數據:不同的任務節點,即使流程變數名稱相同,存放的值也是不同的。
如圖:

2:還有,使用setVariableLocal說明流程變數系結了當前的任務,當流程繼續執行時,下個任務獲取不到這個流程變數(因爲正在執行的流程變數中沒有這個數據),所有查詢正在執行的任務時不能查詢到我們需要的數據,此時需要查詢歷史的流程變數。

十、流程執行歷史記錄

1,查詢歷史流程範例

	/* 1,查詢歷史流程範例 */
	@Test
	public void historyProcessInstince() {
		List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery()
		//條件
//		.processDefinitionId(processDefinitionId)
//		.processDefinitionKey(processDefinitionKey)
//		.processDefinitionKeyIn(processDefinitionKeys)
//		.processDefinitionName(processDefinitionName)
//		.processDefinitionVersion(processDefinitionVersion)
//		.processInstanceBusinessKey(processInstanceBusinessKey)
//		.processInstanceId(processInstanceId)
//		.processInstanceIds(processInstanceIds)
		//排序
//		.orderByProcessDefinitionId()
//		.orderByProcessInstanceBusinessKey()
//		.orderByProcessInstanceDuration()
//		.orderByProcessInstanceStartTime()
//		.orderByProcessInstanceId()
		//結果集
		.list();
//		.listPage(firstResult, maxResults)
//		.count()
//		.singleResult();
		
		if(null!=list&&list.size()>0) {
			for (HistoricProcessInstance hpi : list) {
				System.out.println("歷史流程範例ID:" + hpi.getId());
				System.out.println("流程定義ID:" + hpi.getProcessDefinitionId());
				System.out.println("歷史流程範例的業務ID:" + hpi.getBusinessKey());
				System.out.println("流程部署ID:" + hpi.getDeploymentId());
				System.out.println("流程定義KEY:" + hpi.getProcessDefinitionKey());
				System.out.println("開始活動ID:" + hpi.getStartActivityId());
				System.out.println("結束活動ID:" + hpi.getEndActivityId());
				System.out.println("########################");
			}
		}
		
	}

2,查詢歷史活動

	/* 2,查詢歷史活動 */
	@Test
	public void queryHistoryAct() {
		List<HistoricActivityInstance> list = this.historyService.createHistoricActivityInstanceQuery()
		//條件
//		.activityId(activityId)
//		.activityInstanceId(activityInstanceId)
//		.activityName(activityName)
		//排序
//		.orderByActivityId()
//		.orderByActivityName()
		//結果集
		.list();
		if(null!=list&&list.size()>0)
		{
			for (HistoricActivityInstance hai : list) {
				System.out.println("ID:"+hai.getId());
				System.out.println("流程定義ID:"+hai.getProcessDefinitionId());
				System.out.println("流程範例ID:"+hai.getProcessInstanceId());
				System.out.println("執行範例ID:"+hai.getExecutionId());
				System.out.println("活動ID:"+hai.getActivityId());
				System.out.println("任務ID:"+hai.getTaskId());
				System.out.println("活動名稱:"+hai.getActivityName());
				System.out.println("活動型別:"+hai.getActivityType());
				System.out.println("任務辦理人:"+hai.getAssignee());
				System.out.println("開始時間:"+hai.getStartTime());
				System.out.println("結束時間:"+hai.getEndTime());
				System.out.println("持續時間:"+hai.getDurationInMillis());
				System.out.println("#######################################");
			}
		}
	}

3,查詢歷史任務

/* 3,查詢歷史任務 act_hi_taskinst */
	@Test
	public void queryHistoryTask() {
		List<HistoricTaskInstance> list = this.historyService.createHistoricTaskInstanceQuery()
		//條件
//		.deploymentId(deploymentId)
//		.deploymentIdIn(deploymentIds)
//		.executionId(executionId)
//		.processDefinitionId(processDefinitionId)
//		.processDefinitionKey(processDefinitionKey)
//		.processDefinitionKeyIn(processDefinitionKeys)
//		.processDefinitionKeyLike(processDefinitionKeyLike)     processDefinitionKeyLike="%Hello%"
//		.processDefinitionName(processDefinitionName)
//		.processDefinitionNameLike(processDefinitionNameLike)
		//排序
//		.orderByTaskDefinitionKey()
		//結果集
		.list();
//		.listPage(firstResult, maxResults)
//		.count()
//		.singleResult()
		if(null!=list&&list.size()>0)
		{
			for (HistoricTaskInstance task : list) {
				System.out.println("任務ID:" + task.getId());
				System.out.println("任務辦理人:" + task.getAssignee());
				System.out.println("執行範例ID:" + task.getExecutionId());
				System.out.println("任務名稱:" + task.getName());
				System.out.println("流程定義ID:" + task.getProcessDefinitionId());
				System.out.println("流程範例ID:" + task.getProcessInstanceId());
				System.out.println("任務建立時間:" + task.getCreateTime());
				System.out.println("任務結束時間:" + task.getEndTime());
				System.out.println("#######################################");
			}
		}
	}

4,查詢歷史流程變數

/**
	 * 7:查詢歷史的流程變數
	 */
	@Test
	public void getHistoryVariables() {
		HistoryService historyService = this.processEngine.getHistoryService();
		
		/*HistoricVariableInstance singleResult = historyService.createHistoricVariableInstanceQuery().id("2503").singleResult();;
		System.out.println(singleResult.getId());
		System.out.println(singleResult.getValue());
		System.out.println(singleResult.getVariableName());
		System.out.println(singleResult.getVariableTypeName());*/
		String processInstanceId="2501";
		List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();
		
		for (HistoricVariableInstance hvs : list) {
			System.out.println("ID"+hvs.getId());
			System.out.println("變數值"+hvs.getValue());
			System.out.println("變數名"+hvs.getVariableName());
			System.out.println("變數型別"+hvs.getVariableTypeName());
			System.out.println("#####################");
		}
	}
	

十一、連線

使用流程變數去控制流程的走向

1,流程圖

在这里插入图片描述

提交申請節點

在这里插入图片描述

部門經理審批節點

在这里插入图片描述

部門經理審批節點連線

在这里插入图片描述

總經理審批節點

在这里插入图片描述

2,部署流程定義+啓動流程範例

3,查詢我的個人任務

4,完成任務

/**
	 * 辦理任務
	 */
	@Test
	public void completeTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String taskId = "15003";
		// 根據任務ID去完成任務
		taskService.complete(taskId);
		// 根據任務ID去完成任務並指定流程變數
//		taskService.complete(taskId, variables);
		System.out.println("任務完成");
	}
	/**
	 * 辦理任務並使用流程變數指定流程走向
	 */
	@Test
	public void completeTask2() {
		TaskService taskService = this.processEngine.getTaskService();
		String taskId = "12502";
		Map<String, Object> variables=new HashMap<>();
		variables.put("outcome", "重要");
		// 根據任務ID去完成任務並指定流程變數
		taskService.complete(taskId, variables);
		System.out.println("任務完成");
	}

5,總結

1)、一個活動中可以指定一個或多個SequenceFlow(Start中有一個,End中沒有)。

  • 開始活動中有一個SequenceFlow (即連線)。
  • 結束活動中沒有SequenceFlow 。
  • 其他活動中有1條或多條SequenceFlow

2)、如果只有一個,則可以不使用流程變數設定codition的名稱;

在这里插入图片描述

3)如果有多個,則需要使用流程變數設定codition的名稱。

outcomes表示流程變數的名稱,‘不重要’表示流程變數的值,${}中間的內容要使用boolean型別的表達式,用來判斷應該執行的連線。

在这里插入图片描述

十二、排他閘道器(ExclusiveGateWay)

1,流程圖

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2,部署流程定義+啓動流程範例

3,查詢我的個人任務

4,完成我的個人任務

/**
	 * 辦理任務
	 */
	@Test
	public void completeTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String taskId = "22504";
		// 根據任務ID去完成任務
		taskService.complete(taskId);
		// 根據任務ID去完成任務並指定流程變數
//		taskService.complete(taskId, variables);
		System.out.println("任務完成");
	}
	/**
	 * 辦理任務並使用流程變數指定流程走向
	 */
	@Test
	public void completeTask2() {
		TaskService taskService = this.processEngine.getTaskService();
		String taskId = "20004";
		Map<String, Object> variables=new HashMap<>();
		variables.put("money", 1200);
		// 根據任務ID去完成任務並指定流程變數
		taskService.complete(taskId, variables);
		System.out.println("任務完成");
	}

5,說明

1)一個排他閘道器對應一個以上的順序流(連線)

2)由排他閘道器流出的順序流都有個conditionExpression元素,在內部維護返回boolean型別的決策結果。

3)決策閘道器只會返回一條結果。當流程執行到排他閘道器時,流程引擎會自動檢索網關出口,從上到下檢索如果發現第一條決策結果爲true或者沒有設定條件的(預設爲成立),則流出。

4)如果沒有任何一個出口符合條件,則拋出異常

5)使用流程變數,設定連線的條件,並按照連線的條件執行工作流,如果沒有條件符合的條件,則以預設的連線離開。

十三、並行閘道器(parallelGateWay)

1,流程圖

在这里插入图片描述

2,部署流程定義+啓動流程範例

3,查詢我的個人任務

4,完成我的個人任務

/**
	 * 辦理任務
	 */
	@Test
	public void completeTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String taskId = "10002";
		// 根據任務ID去完成任務
		taskService.complete(taskId);
		// 根據任務ID去完成任務並指定流程變數
		System.out.println("任務完成");
	}

5,說明

1)一個流程中流程範例只有1個,執行物件有多個

2)並行閘道器的功能是基於進入和外出的順序流的
分支(fork):
並行後的所有外出順序流,爲每個順序流都建立一個併發分支。
匯聚(join):
所有到達並行閘道器,在此等待的進入分支, 直到所有進入順序流的分支都到達以後, 流程就會通過匯聚閘道器。

3)並行閘道器的進入和外出都是使用相同節點標識

4)如果同一個並行閘道器有多個進入和多個外出順序流, 它就同時具有分支和匯聚功能。 這時,閘道器會先匯聚所有進入的順序流,然後再切分成多個並行分支。

5)並行閘道器不會解析條件。 即使順序流中定義了條件,也會被忽略。

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

在这里插入图片描述

十四、個人任務

1,流程圖

在这里插入图片描述

2,分配個人任務方式一(直接指定辦理人)

在这里插入图片描述

缺點 辦理人固定了,但是實際開發中,辦理人是不固定的

3,分配個人任務方式二(使用流程變數)

1).部署

2).啓動並指定下一個任務的辦理人【從session裏面取】

	/**
	 * 啓動流程並指定下一個任務的辦理人
	 */
	@Test
	public void startProcess() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String processDefinitionKey="HelloWorld";
		Map<String,Object> variables=new HashMap<>();
		variables.put("username", "張三");
		runtimeService.startProcessInstanceByKey(processDefinitionKey,variables);
		System.out.println("流程啓動成功");
	}

3). 查詢個人任務

4).完成任務並指定下一個任務的辦理人

/**
	 * 辦理任務
	 */
	@Test
	public void completeTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String taskId="12505";
		Map<String,Object> variables=new HashMap<>();
		variables.put("username", "李四");
		taskService.complete(taskId,variables);
		System.out.println("任務完成");
	}

4,分配個人任務方式三(使用類)

建立一個監聽類
作用:當任務到達相應的節點時,會觸發監聽,讓監聽器去指定下個任務的辦理人

在这里插入图片描述

修改流程圖

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5,總結

個人任務及三種分配方式:
1,在taskProcess.bpmn中直接寫 assignee=「張三豐"

2,在taskProcess.bpmn中寫 assignee=「#{userID}」,變數的值要是String的,使用流程變數指定辦理人

3,使用TaskListener介面,要使類實現該介面,在類中定義,
delegateTask.setAssignee(assignee);// 指定個人任務的辦理人
使用任務ID和辦理人重新指定辦理人:
processEngine.getTaskService()//
.setAssignee(taskId, userId);

十五、使用者組任務

1,流程圖

在这里插入图片描述

2,分配組任務方式一(直接指定辦理人)

1).修改流程圖

在这里插入图片描述

2).部署流程

3).相關程式碼


/**
 * 組任務使用流程變數去設定
 * 
 *
 */
public class GroupTask01 {

	
	/**
	 * 啓動流程
	 */
	@Test
	public void startProcess() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String processDefinitionKey = "HelloWorld";
		runtimeService.startProcessInstanceByKey(processDefinitionKey);
		System.out.println("流程啓動成功");
	}

	/**
	 * 查詢組任務
	 */
	@Test
	public void findGroupTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String candidateUser = "小B";
		List<Task> list = taskService.createTaskQuery().taskCandidateUser(candidateUser).list();
		if (null != list && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任務ID:" + task.getId());
				System.out.println("流程範例ID:" + task.getProcessInstanceId());
				System.out.println("執行範例ID:" + task.getExecutionId());
				System.out.println("流程定義ID:" + task.getProcessDefinitionId());
				System.out.println("任務名稱:" + task.getName());
				System.out.println("任務辦理人:" + task.getAssignee());
				System.out.println("################################");
			}
		}
	}

	/**
	 * 查詢個人任務
	 */
	@Test
	public void findTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String assignee = "小A";
		List<Task> list = taskService.createTaskQuery().taskAssignee(assignee).list();
		if (null != list && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任務ID:" + task.getId());
				System.out.println("流程範例ID:" + task.getProcessInstanceId());
				System.out.println("執行範例ID:" + task.getExecutionId());
				System.out.println("流程定義ID:" + task.getProcessDefinitionId());
				System.out.println("任務名稱:" + task.getName());
				System.out.println("任務辦理人:" + task.getAssignee());
				System.out.println("################################");
			}
		}
	}

	/**
	 * 任務拾取
	 */
	@Test
	public void claim() {
		String taskId="2504";
		TaskService taskService = this.processEngine.getTaskService();
		taskService.claim(taskId, "小A");
		System.out.println("任務拾取成功");
	}
	/**
	 * 任務回退
	 */
	@Test
	public void claimBack() {
		String taskId="2504";
		TaskService taskService = this.processEngine.getTaskService();
		taskService.setAssignee(taskId, null);
		System.out.println("任務回退成功");
	}
	
    //5 查詢組任務成員列表
    @Test
    public void findGroupUser(){
        String taskId = "2504";
        List<IdentityLink> list = processEngine.getTaskService()//
                        .getIdentityLinksForTask(taskId);
         //List<IdentityLink> list = processEngine.getRuntimeService()//
        //                .getIdentityLinksForProcessInstance(instanceId);
        for(IdentityLink identityLink:list ){
            System.out.println("userId="+identityLink.getUserId());
            System.out.println("taskId="+identityLink.getTaskId());
            System.out.println("piId="+identityLink.getProcessInstanceId());
            System.out.println("TYPE="+identityLink.getType());
            System.out.println("######################");
        }
    }
	

	/**
	 * 辦理任務
	 */
	@Test
	public void completeTask() {
		TaskService taskService = this.processEngine.getTaskService();
		String taskId = "5002";
		taskService.complete(taskId);
		System.out.println("任務完成");
	}
}


3,分配組任務方式二(使用流程變數)

1).修改流程圖

在这里插入图片描述

2) 部署流程

3).相關程式碼

/**
 * 組任務使用流程變數去設定
 * 
 * @author LJH
 *
 */
public class GroupTask01 {

	/**
	 * 啓動流程
	 */
	 @Test
	public void startProcess() {
		RuntimeService runtimeService = this.processEngine.getRuntimeService();
		String processDefinitionKey = "HelloWorld";
		Map<String,Object> variables=new HashMap<>();
		variables.put("usernames", "小A,小B,小C,小D");
		runtimeService.startProcessInstanceByKey(processDefinitionKey,variables);
		System.out.println("流程啓動成功");
	}

(其他與上面一致)

4,分配組任務方式三(使用類)

1).建立監聽器

在这里插入图片描述

2).修改流程圖

在这里插入图片描述

3).相關程式碼

與第一種方法一致

5,總結

在这里插入图片描述

1)組任務及三種分配方式,

1、在taskProcess.bpmn中直接寫 candidate-users=「小A,小B,小C,小D"

2、在taskProcess.bpmn中寫 candidate-users =「#{userIDs}」,變數的值要是String的。

使用流程變數指定辦理人

	Map<String, Object> variables = new HashMap<String, Object>();
	variables.put("userIDs", "大大,小小,中中");

3、使用TaskListener介面,使用類實現該介面

	delegateTask.addCandidateUser(userId1);//新增組任務的使用者
	delegateTask.addCandidateUser(userId2);
	//組任務分配給個人任務(認領任務),
     processEngine.getTaskService().claim(taskId, userId);
	//個人任務分配給組任務,
     processEngine.getTaskService(). setAssignee(taskId, null);
	//向組任務新增人員,
     processEngine.getTaskService().addCandidateUser(taskId, userId);
	//向組任務刪除人員,
     processEngine.getTaskService().deleteCandidateUser(taskId, userId);

2)個人任務和組任務存放辦理人對應的表,

act_ru_identitylink表存放任務的辦理人,包括個人任務和組任務,表示正在執行的任務
act_hi_identitylink表存放任務的辦理人,包括個人任務和組任務,表示歷史任務

區別在於,如果是個人任務TYPE的型別表示participant(參與者)
如果是組任務TYPE的型別表示candidate(候選者)和participant(參與者)

十六、Activiti總結

在这里插入图片描述

在这里插入图片描述