1. 程式人生 > >【Activiti工作流】7.流程定義的CRUD(上)

【Activiti工作流】7.流程定義的CRUD(上)

工作流的23張表是如何存取的?每一步操作邏輯是什麼樣子的?我們來學習一下。

一、管理流程定義
1設計流程定義文件
1.1流程圖
我們之前已經看過,常見流程圖如下如所示:

包含了開始節點/結束節點/任務/流向線

1.2bpmn檔案
BPMN 2.0根節點是definitions節點。 這個元素中,可以定義多個流程定義(不過我們建議每個檔案只包含一個流程定義, 可以簡化開發過程中的維護難度)。 一個空的流程定義看起來像下面這樣。注意,definitions元素 最少也要包含xmlns 和 targetNamespace的宣告。 targetNamespace可以是任意值,它用來對流程例項進行分類。

說明:流程定義文件有兩部分組成:
1)bpmn檔案
流程規則檔案。在部署後,每次系統啟動時都會被解析,把內容封裝成流程定義放入專案快取中。Activiti框架結合這個xml檔案自動管理流程,流程的執行就是按照bpmn檔案定義的規則執行的,bpmn檔案是給計算機執行用的。

2)展示流程圖的圖片
在系統裡需要展示流程的進展圖片,圖片是給使用者看的。

2部署流程定義(classpath路徑載入檔案)
/**部署流程定義*/
@Test
public void deploymentProcessDefinition(){
	//與流程定義和部署物件相關的Service
	RepositoryService repositoryService=processEngine.getRepositoryService();
	
	DeploymentBuilder deploymentBuilder=repositoryService.createDeployment();//建立一個部署物件
	deploymentBuilder.name("helloWorld入門程式");//新增部署的名稱
	deploymentBuilder.addClasspathResource("diagrams/MyProcess.bpmn");//從classpath的資源載入,一次只能載入一個檔案
	deploymentBuilder.addClasspathResource("diagrams/MyProcess.png");//從classpath的資源載入,一次只能載入一個檔案
	
	Deployment deployment=deploymentBuilder.deploy();//完成部署
	
	//列印我們的流程資訊
	System.out.println("部署Id:"+deployment.getId());
	System.out.println("部署名稱Name:"+deployment.getName());
}
說明:
1)先獲取流程引擎物件:在建立時會自動載入classpath下的activiti.cfg.xml
//獲取流程引擎物件
//getDefaultProcessEngine方法內部會自動讀取名為activiti.cfg.xml檔案的配置資訊
ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();


2)首先獲得預設的流程引擎,通過流程引擎獲取了一個RepositoryService物件(倉庫物件)

3)由倉庫的服務物件產生一個部署物件配置物件,用來封裝部署操作的相關配置。

4)這是一個鏈式程式設計,在部署配置物件中設定顯示名,上傳流程定義規則檔案

5)向資料庫表中存放流程定義的規則資訊。

6)這一步在資料庫中將操作三張表:
    a)act_re_deployment(部署物件表)
        存放流程定義的顯示名和部署時間,每部署一次增加一條記錄
    注:如果部署相同Key的流程,那麼Version將會升級,也就是版本升級:
    圖7.2.jpg
    啟動該Key的流程時,預設啟動最新版本(Version)的流程。


    b)act_re_procdef(流程定義表)
        存放流程定義的屬性資訊,部署每個新的流程定義都會在這張表中增加一條記錄。
    注意:當流程定義的key相同的情況下,使用的是版本升級。


    c)act_ge_bytearray(資原始檔表)
        儲存流程定義相關的部署資訊。即流程定義文件的存放地。每部署一次就會增加兩條記錄,    
    一條是關於bpmn規則檔案的,一條是圖片的(如果部署時只指定了bpmn一個檔案,activiti    
    會在部署時解析bpmn檔案內容自動生成流程圖)。兩個檔案不是很大,都是以二進位制形式儲存在資料庫中。


注意,部署流程定義的時候,可以把bpmn檔案和png檔案壓縮成ZIP格式的壓縮檔案
進行上傳:



處理程式碼有所改變:
/**部署流程定義(Zip)*/
@Test
public void deploymentProcessDefinitionZip(){
	//獲得上傳檔案的輸入流程
	InputStream in=this.getClass().getClassLoader().getResourceAsStream("diagrams/MyProcess.zip");
	ZipInputStream zipInputStream=new ZipInputStream(in);
	//獲取倉庫服務,從類路徑下完成部署
	RepositoryService repositoryService=processEngine.getRepositoryService();
	DeploymentBuilder deploymentBuilder=repositoryService.createDeployment();//建立一個部署物件
	deploymentBuilder.name("helloWorld入門程式");//新增部署的名稱
	deploymentBuilder.addZipInputStream(zipInputStream);
	Deployment deployment=deploymentBuilder.deploy();//完成部署
	
	//列印我們的流程資訊
	System.out.println("部署Id:"+deployment.getId());
	System.out.println("部署名稱Name:"+deployment.getName());
}

3.檢視流程定義
查詢流程定義的資訊
/**檢視流程定義
 * 	id:(key):(version):(隨機值)
 * 	name:對應流程檔案process節點的name屬性
 *  key:對應流程檔案process節點的id屬性
 *  version:釋出時自動生成的。如果是第一次釋出的流程,version預設從1開始;
 *  如果當前流程引擎中已存在相同的流程,則找到當前key對應的最高版本號,在最高版本號上加1*/
@Test
public void queryProcessDefinition() throws Exception{
	//獲取倉庫服務物件,使用版本的升級排列,查詢列表
	List<ProcessDefinition> pdList=processEngine.getRepositoryService()
								.createProcessDefinitionQuery()
								//新增查詢條件
								//.processDefinitionId(processDefinitionId)
								//.processDefinitionKey(processDefinitionKey)
								//.processDefinitionName(processDefinitionName)
								//排序(可以按照id/key/name/version/Cagetory排序)
								.orderByProcessDefinitionVersion().asc()
								//.count()
								//.listPage(firstResult, maxResults)
								//.singleResult()
								.list();//總的結果集數量
	//便利集合,檢視內容
	for (ProcessDefinition pd:pdList) {
		System.out.println("id:"+pd.getId());
		System.out.println("name:"+pd.getName());
		System.out.println("key:"+pd.getKey());
		System.out.println("version:"+pd.getVersion());
		System.out.println("resourceName:"+pd.getDiagramResourceName());
		System.out.println("###########################################");
	}
}
結果:

我們再次部署一次HelloWorld流程(用剛剛的Zip):

那麼查詢流程定義的資訊的執行結果為:

可以看到流程定義的key值相同的情況下,版本是從1開始逐次升級的
流程定義的Id是【key:版本:生成ID】
說明:
1)流程定義和部署物件相關的Service都是RepositoryService。

2)建立流程定義查詢物件,可以在ProcessDefinitionQuery上設定查詢的相關引數

3)呼叫ProcessDefinitionQuery物件的list方法,執行查詢,獲得符合條件的流程定義列表

4)由執行結果可以看出:
Key和Name的值為:bpmn檔案process節點的id和name的屬性值


5)key屬性被用來區別不同的流程定義。

6)帶有特定key的流程定義第一次部署時,version為1。之後每次部署都會在當前最高版本號上加1

7)Id的值的生成規則為:{processDefinitionKey}:{processDefinitionVersion}:{generated-id}, 這裡的generated-id是一個自動生成的唯一的數字

8)重複部署一次,deploymentId的值以一定的形式變化
   規則act_ge_property表生成


4.刪除流程定義
刪除部署到activiti中的流程定義。
/**刪除流程*/
@Test
public void deleteDeployment(){
	//刪除釋出資訊
	String deploymentId="1";
	//獲取倉庫服務物件
	RepositoryService repositoryService=processEngine.getRepositoryService();
	//普通刪除,如果當前規則下有正在執行的流程,則拋異常
	//repositoryService.deleteDeployment(deploymentId);
	//級聯刪除,會刪除和當前規則相關的所有資訊,正在執行的資訊,也包括歷史資訊
	repositoryService.deleteDeployment(deploymentId, true);
	
}
說明:
1)因為刪除的是流程定義,而流程定義的部署是屬於倉庫服務的,所以應該先得到RepositoryService

2)如果該流程定義下沒有正在執行的流程,則可以用普通刪除。如果是有關聯的資訊,用級聯刪除。專案開發中使用級聯刪除的情況比較多,刪除操作一般只開放給超級管理員使用。


5.獲取流程定義文件的資源(檢視流程圖附件)
查詢出流程定義文件。主要查的是圖片,用於顯示流程用。
/**檢視流程附件(檢視流程圖片)*/
@Test
public void viewImage() throws Exception{
	//從倉庫中找需要展示的檔案
	String deploymentId="1";
	List<String> names=processEngine.getRepositoryService()
					   			    .getDeploymentResourceNames(deploymentId);
	String imageName=null;
	for(String name:names){
		System.out.println("name:"+name);
		if(name.indexOf(".png")>0){
			imageName=name;
			break;
		}
	}
	System.out.println("imageName:"+imageName);
	if(imageName!=null){
		File f=new File("e:/"+imageName);
		//通過部署ID和檔名稱得到檔案的輸入流
		InputStream in = processEngine.getRepositoryService()
				                      .getResourceAsStream(deploymentId, imageName);
		FileUtils.copyInputStreamToFile(in, f);
	}
}
執行結果:



說明:
1)deploymentId為流程部署ID
2)resourceName為act_ge_bytearray表中NAME_列的值
圖7.9.jpg
3)使用repositoryService的getDeploymentResourceNames方法可以獲取指定部署下得所有檔案的名稱
圖7.10.jpg
4)使用repositoryService的getResourceAsStream方法傳入部署ID和資源圖片名稱可以獲取部署下指定名稱檔案的輸入流
5)最後的有關IO流的操作,使用FileUtils工具的copyInputStreamToFile方法完成流程流程到檔案的拷貝,將資原始檔以流的形式輸出到指定資料夾下。

如果我們的流程需要修改應該怎麼操作呢?請看下一篇