1. 程式人生 > >【Activiti】從入門到放棄——專案實戰之流程定義管理

【Activiti】從入門到放棄——專案實戰之流程定義管理

步驟分析:
要想在實現一個能夠完成流程定義的crud的功能,也就是在專案中能夠對各種流程(客戶報備,報銷,請假等)進行crud,那就是一個完整的模組,應該單獨獨立一個選單。並且完成這個選單的模組管理。
1)選單-跳轉到管理介面
2)選單模組管理
i.部署新流程-沒有資料
ii.列表/重新整理流程
iii.刪除/掛起/啟用流程
iv.查詢流程圖
流程定義選單實現:
1 建立選單
在流程管理下面建立一個流程定義管理的二級選單 就有url
2 建立一個WorkFlowController要有一個跳轉到流程定義管理介面的方法
該方法的對映地址就是選單裡面的url
3 建立流程管理介面
拷貝其他頁面修改為流程管理頁面
新增流程:


1、先讓後臺能夠接受來自前臺的資料(/workflow/newDeploy)
2、編寫IWorkFlowService完成專案的部署

注意1:
直接在控制器中注入工作流相關服務完成流程部署,還是自己寫一個服務進行封裝,這樣在Controller裡面就呼叫一句就搞定。
注意2:
編寫部署方法時,不要傳入頁面層的API,
MutilpartFile而要傳入InputStream 流.
注意3:
通過資料庫資訊檢視是否部署成功。

//跳轉到流程定義管理頁面
	@RequestMapping("/processDefinition/index")
	public String processDefiniton() {
		
		//流程定義管理介面路徑,預設加上字首和字尾
		return "workFlow/processDefinition";
	}


/**
	 * 引數:
	 *    name:部署名稱
	 *    processFile:型別是MultipartFile,是SPringmvc用於檔案上傳接收的專用類
	 * 返回值:
	 *    AJaxResult轉換結果
	 * @return
	 */
	@RequestMapping("/newDeploy")
	@ResponseBody
	public AjaxResult newDeploy(String name,MultipartFile processFile) {
		System.out.println(name);
		System.out.println(processFile);
		//1 不要直接注入RepositoryService來完成部署,應該交給對應Service去做
		//2 MultipartFile就是web層api,如果我們直接傳入,Service層就強依賴於web層API.也就是咱們這個Service必須在web才能執行,不能強依賴.
		try {
			workFlowService.newDeploy(name,processFile.getInputStream());
			return new AjaxResult();
		} catch (IOException e) {
			e.printStackTrace();
			return new AjaxResult("部署失敗!"+e.getMessage(),-1);
		}
	}

@Override
	public void newDeploy(String name, InputStream inputStream) {
		//完成真正部署
		//1獲取引擎物件
		//2獲取服務
		//3做事情
		ZipInputStream zis = null;
		try {
			zis = new ZipInputStream(inputStream);
			//建立配置物件
			DeploymentBuilder builder = repositoryService.createDeployment();
			//進行配置
			builder.name(name)//部署名稱
			       .addZipInputStream(zis);  //bpmn和png
			//部署
			builder.deploy();
		} catch (Exception e) {
			e.printStackTrace();
			
		}
		finally{
			if (zis != null) {
				try {
					zis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

列表流程:
前臺:
修改datagrid的地址為/workFlow/listProcessDefinition
後臺:
在WorkFlowController中新增一個返回Json資料的listProcessDefinition方法,
並完成對應地址“/workFlow/listProcessDefinition”的對映,並完成邏輯。

注意1:不能直接返回List
1、轉換Json失敗,原因時報延遲載入錯誤,事物在Service,但是在Controller中還需要資料庫延遲載入,所以有問題。
2、ProcessDefinition有太多不需要的屬性,需傳遞到前臺。浪費網路資源。
需要返回一個List< Map<String,Object>>,具體map裡面有那些key呢,需要
根據前臺展示來。檢視ProcessDefinition裡面的屬性,可以把重要的都展示出來。
注意2:所有的列沒有佔全整個寬度
在這裡插入圖片描述


注意3:把物件拷貝到map中使用工具類進行拷貝
在這裡插入圖片描述

//返回值:流程定義的list json格式
	@RequestMapping("/listProcessDefinitions")
	@ResponseBody
	public List<Map<String, Object>> listProcessDefinitions() {
		
		return workFlowService.listProcessDefinitions();
	}


@Override
	public List<Map<String, Object>> listProcessDefinitions() {
		//建立查詢物件
		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
		//設定查詢條件
		query.orderByProcessDefinitionKey().desc();//相同的流程不同的版本放到一起
		query.orderByProcessDefinitionVersion().desc();//版本安倒序排
		//做查詢
		List<ProcessDefinition> list = query.list();
		
		//申明要返回的型別
		List<Map<String, Object>>  result = new ArrayList<>();
		//進行轉換
		for (ProcessDefinition processDefinition : list) {
			//把一個processDefinition轉換為一個Map
			result.add(processDefinition2map(processDefinition));
		}
		//返回
		return result;
	}

	private Map<String, Object> processDefinition2map(ProcessDefinition processDefinition) {
		//申明要返回的型別
//		Map<String, Object> result = new HashMap<>();
		//進行轉換
//		result.put("id", processDefinition.getId());
		//返回
//		return result;
          return CommUtil.obj2map(processDefinition, new String[]{
        		 "id","name","key",
        		 "version","deploymentId","resourceName",
        		 "diagramResourceName","description"
          });
	}

刪除操作:

@Override
	public void deleteDeployment(String deploymentId) {
		repositoryService.deleteDeployment(deploymentId);
	}

查詢流程圖:
一 點選"檢視流程圖"按鈕,開啟一個查詢流程圖對話方塊
裡面需要展示流程圖,先寫死路徑:/1.png

二 動態發請求到Controller獲取流程圖

三 deploymentId和resoruceName要動態獲取

@RequestMapping("/viewProcessDefinitionPng")
	public void viewProcessDefinitionPng(String deploymentId,String resourceName,HttpServletRequest request,HttpServletResponse response) throws IOException{
		System.out.println("00000");
		InputStream inputStream=null;
		ServletOutputStream outputStream = null;
		try {
			System.out.println(resourceName);//MyProcess.myProcess.png
			inputStream=definitionService.viewProcessDefinitionPng(deploymentId,resourceName);
			outputStream=response.getOutputStream();
			IOUtils.copy(inputStream, outputStream);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

@Override
	public InputStream viewProcessDefinitionPng(String deploymentId, String resourceName) {
		return repositoryService.getResourceAsStream(deploymentId, resourceName);
	}


view:function(){
					///workFlow/viewDiagram?deploymentId=1&diagarmResoruceName=test.png
					//開啟之前需要動態設定流程圖的src地址
					// 獲取行選中資料
					var rowData = processDefinitionGrid.datagrid("getSelected");
					// 判斷
					if(!rowData){
						$.messager.alert("溫馨提示","請選中一行!!","info");
						return;
					}
					var deploymentId = rowData.deploymentId;
					var diagramResourceName = rowData.diagramResourceName;
					var src = "/workFlow/viewDiagram?deploymentId="+deploymentId+"&diagarmResoruceName="
							+diagramResourceName;
					//動態設定src地址
					$("#img").attr("src",src);
					//開啟流程圖對話方塊
					viewProcessDiagramDlg.dialog("open");
				}
<!-- 2. 檢視流程圖對話方塊-->
	<div id="viewProcessDiagramDlg" >
<!-- 		第一步:寫死路徑
<img src="/1.png" alt="xxxxx">
 -->
 <!-- 2 通過Controller來響應 -->
	<img id="img" src=""/>
	</div>