Activiti工作流之实现一个简单的流程审批
該代碼在上一篇博客的基礎上開發。
Activiti工作流入門
1.繪制bpmn流程圖
在resources目錄下新建一個diagram文件夾來存放我們繪制的bpmn流程圖
由于我的IDEA中已經安裝了actiBPM插件,所以我們可以直接創建
?
然后利用IDEA中提供的組件來繪制流程圖
?
為了方便測試,對應的3個流程處理的人員分別為zhangsan,lisi,wangwu。
我們可以點擊對應的流程,在Assignee中指定任務負責人。
?
2.將bpmn轉為png圖片
在IDEA中將bpmn格式的后綴改為.xml
?
?
導出png圖片,最終效果如下:
?
3.部署流程定義
部署流程定義就是要將上邊繪制的圖形即流程定義(.bpmn)部署在工作流程引擎 activiti 中,方法 如下:
/*** 流程定義的部署* 背后影響的表:* ? ? act_re_deployment: 部署信息* ? ? act_re_procdef: 流程定義* ? ? act_ge_bytearray: 流程定義的bpmn文件和png文件*/ public class ActivitiDeployment {public static void main(String[] args) {//1.創建ProcessEngineer對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//2.獲取repositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();//3.部署對象Deployment deploy = repositoryService.createDeployment()//添加bpmn資源.addClasspathResource("diagram/holiday.bpmn")//添加圖片文件資源.addClasspathResource("diagram/holiday.png").name("請假申請流程").deploy();//4.輸出部署的一些信息System.out.println(deploy.getId());System.out.println(deploy.getName());} }我們還可以用zip壓縮包部署
@Test public void deployProcessByZip() {//1.創建ProcessEngineer對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//2.獲取repositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();//3.定義zip輸入流InputStream inputStream = this.getClass() .getClassLoader() .getResourceAsStream(" diagram/holiday.zip");//4.部署對象ZipInputStream zipInputStream = new ZipInputStream(inputStream);Deployment deploy = repositoryService.createDeployment().addZipInputStream(zipInputStream)//5.輸出部署的一些信息System.out.println(deploy.getId());System.out.println(deploy.getName()); }4.啟動一個流程實例
流程定義部署在 activiti 后就可以通過工作流管理業務流程了,也就是說上邊部署的請假申請流程可以使用了。
針對該流程,啟動一個流程表示發起一個新的請假申請單,這就相當于 java 類與 java 對象的關 系,類定義好后需要 new 創建一個對象使用,當然可以 new 多個對象。對于請假申請流程,張三發起一個請假申請單需要啟動一個流程實例。
/*** 啟動流程實例(前提是完成了流程定義的部署工作)** 背后影響的表:* ? ? act_hi_actinst: 已完成的活動信息* ? ? act_hi_identitylink: 參與者信息* ? ? act_hi_procinst: 流程實例* ? ? act_hi_taskinst: 任務實例* ? ? act_ru_execution: 執行表* ? ? act_ru_identitylink: 參與者信息* ? ? act_ru_task: 任務*/ public class ActivitiStartInstance {public static void main(String[] args) {//1.創建ProcessEngineer對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//2.獲取runtimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();//3.創建流程實例ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday");//4.輸出實例的相關信息System.out.println("流程部署id:" + processInstance.getDeploymentId());//nullSystem.out.println("流程定義id:" + processInstance.getProcessDefinitionId());//holiday:1:4System.out.println("流程實例id:" + processInstance.getId());//2501System.out.println("流程活動id:" + processInstance.getActivityId());//null} }5.任務查詢
流程啟動后,各任務的負責人就可以查詢自己當前需要處理的任務,查詢出來的任務都是該用戶的待辦任務。
/*** 查詢當前用戶的任務列表*/ public class ActivitiTaskQuery { ?//wangwu完成自己任務列表的查詢public static void main(String[] args) {//1.得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); ?//2.得到TaskService對象TaskService taskService = processEngine.getTaskService(); ?//3.根據流程定義的key,負責人assignee來實現當前用戶的任務列表查詢Task task = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee("zhangsan").singleResult(); ?//4.任務列表的展示System.out.println("流程實例ID:" + task.getProcessInstanceId());//2501System.out.println("任務ID:" + task.getId()); ?//2505System.out.println("任務負責人:" + task.getAssignee());//zhangsanSystem.out.println("任務名稱:" + task.getName());//填寫請假申請單 ?}6.任務處理
任務負責人查詢待辦任務,選擇任務進行處理,完成任務。
/*** 處理當前用戶的任務* 背后操作的表:* ? act_hi_actinstact_hi_identitylinkact_hi_taskinstact_ru_identitylinkact_ru_task*/ public class ActivitiCompleteTask { ?//查詢當前用戶wangwu的任務并處理掉public static void main(String[] args) {//1.得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); ?//2.得到TaskService對象TaskService taskService = processEngine.getTaskService(); ?//3.查詢當前用戶的任務Task task = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee("zhangsan").singleResult(); ?//4.處理任務,結合當前用戶任務列表的查詢操作的話,任務ID:task.getId()taskService.complete(task.getId()); ?//5.輸出任務的idSystem.out.println(task.getId());} }在處理過程中可以實時觀察代碼中標明的表的變化,下面列出了一些表的數據變化:
比如在zhangsan填寫完請假申請單后act_hi_actinst表的變化
流程到了部門經理審批這一步,由于部門經理還沒有處理,end_time為null
?
全部完成后的效果:
?
act_ru_task表,可以發現每處理一步,都會將處理完的數據刪除掉,然后當前的數據為待處理的。等lisi和wangwu都處理完,沒有任務后,該表的數據會為空。
?
全部完成后的效果:
?
7.流程定義查詢
/*** 查詢流程定義信息*/ public class QueryProcessDefinition { ? ?public static void main(String[] args) {//1.得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); ?//2.創建RepositoryService對象RepositoryService repositoryService = processEngine.getRepositoryService(); ?//3.得到ProcessDefinitionQuery對象,可以認為它就是一個查詢器ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); ?//4.設置條件,并查詢出當前的所有流程定義 ? 查詢條件:流程定義的key=holiday//orderByProcessDefinitionVersion() 設置排序方式,根據流程定義的版本號進行排序List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("holiday").orderByProcessDefinitionVersion().desc().list(); ?//5.輸出流程定義信息for(ProcessDefinition processDefinition :list){System.out.println("流程定義ID:"+processDefinition.getId());System.out.println("流程定義名稱:"+processDefinition.getName());System.out.println("流程定義的Key:"+processDefinition.getKey());System.out.println("流程定義的版本號:"+processDefinition.getVersion());System.out.println("流程部署的ID:"+processDefinition.getDeploymentId()); ?}} }輸出信息如下:
流程定義ID:holiday:1:4 流程定義名稱:請假流程 流程定義的Key:holiday 流程定義的版本號:1 流程部署的ID:18.流程定義刪除
/*** 刪除已經部署的流程定義** 背后影響的表:* ? ? act_re_deployment: 部署信息* ? ? act_re_procdef: 流程定義* ? ? act_ge_bytearray: 流程定義的bpmn文件和png文件*/ public class DeleteProcessDefinition { ?/*** 注意事項:* ? ? 1.當我們正在執行的這一套流程沒有完全審批結束的時候,此時如果要刪除流程定義信息就會失敗* ? ? 2.如果公司層面要強制刪除,可以使用repositoryService.deleteDeployment("1",true);* ? ? //參數true代表級聯刪除,此時就會先刪除沒有完成的流程結點,最后就可以刪除流程定義信息 false的值代表不級聯** @param args*/public static void main(String[] args) {//1.得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); ?//2.創建RepositoryService對象RepositoryService repositoryService = processEngine.getRepositoryService(); ?//3.執行刪除流程定義 參數代表流程部署的idrepositoryService.deleteDeployment("1");} }9.流程定義資源查詢
通過流程定義對象獲取流程定義資源,獲取 bpmn 和 png。
/*** 需求:* 1.從Activiti的act_ge_bytearray表中讀取兩個資源文件* 2.將兩個資源文件保存到路徑: ? /Users/apple/diagram/** 技術方案:* ? ? 1.第一種方式使用actviti的api來實現* ? ? 2.第二種方式:其實就是原理層面,可以使用jdbc的對blob類型,clob類型數據的讀取,并保存* ? ? ? IO流轉換,最好commons-io.jar包可以輕松解決IO操作** 真實應用場景:用戶想查看這個請假流程具體有哪些步驟要走?**/ public class QueryBpmnFile { ?public static void main(String[] args) throws IOException {//1.得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); ?//2.得到RepositoryService對象RepositoryService repositoryService = processEngine.getRepositoryService(); ?//3.得到查詢器:ProcessDefinitionQuery對象ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); ?//4.設置查詢條件processDefinitionQuery.processDefinitionKey("holiday");//參數是流程定義的key ?//5.執行查詢操作,查詢出想要的流程定義ProcessDefinition processDefinition = processDefinitionQuery.singleResult(); ?//6.通過流程定義信息,得到部署IDString deploymentId = processDefinition.getDeploymentId(); ?//7.通過repositoryService的方法,實現讀取圖片信息及bpmn文件信息(輸入流)//getResourceAsStream()方法的參數說明:第一個參數部署id,第二個參數代表資源名稱//processDefinition.getDiagramResourceName() 代表獲取png圖片資源的名稱//processDefinition.getResourceName()代表獲取bpmn文件的名稱InputStream pngIs = repositoryService.getResourceAsStream(deploymentId,processDefinition.getDiagramResourceName());InputStream bpmnIs = repositoryService.getResourceAsStream(deploymentId,processDefinition.getResourceName()); ?//8.構建出OutputStream流OutputStream pngOs =new FileOutputStream("/Users/apple/"+processDefinition.getDiagramResourceName()); ?OutputStream bpmnOs =new FileOutputStream("/Users/apple/"+processDefinition.getResourceName()); ?//9.輸入流,輸出流的轉換 commons-io-xx.jar中的方法IOUtils.copy(pngIs,pngOs);IOUtils.copy(bpmnIs,bpmnOs);//10.關閉流pngOs.close();bpmnOs.close();pngIs.close();bpmnIs.close(); ?} }10.流程歷史信息的查看
即使流程定義已經刪除了,流程執行的歷史信息通過前面的分析,依然保存在 activiti 的 act_hi_*相關的表中。所以我們還是可以查詢流程執行的歷史信息,可以通過 HistoryService 來查看相關的歷史記錄。
/*** 需求:* 歷史數據的查看*/ public class HistoryQuery { ?public static void main(String[] args) throws IOException {//1.得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); ?//2.得到HistoryServiceHistoryService historyService = processEngine.getHistoryService(); ?//3.得到HistoricActivitiInstanceQuery對象HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery(); ?historicActivityInstanceQuery.processInstanceId("2501");//設置流程實例的id ?//4.執行查詢List<HistoricActivityInstance> list = historicActivityInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list();//排序StartTime ?//5.遍歷查詢結果System.out.println("=============================");for (HistoricActivityInstance instance : list) {System.out.println(instance.getActivityId());System.out.println(instance.getActivityName());System.out.println(instance.getProcessDefinitionId());System.out.println(instance.getProcessInstanceId());System.out.println("=============================");}} }輸出信息如下:
============================= _holiday 請假流程 holiday:1:4 2501 ============================= _3 填寫請假申請單 holiday:1:4 2501 ============================= _4 部門經理審批 holiday:1:4 2501 ============================= _5 總經理審批 holiday:1:4 2501 ============================= _6 結束 holiday:1:4 2501 =============================總結
以上是生活随笔為你收集整理的Activiti工作流之实现一个简单的流程审批的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Activiti工作流入门
- 下一篇: 在SpringBoot中使用redis实