關於在IDEA中SpringBoot專案中activiti工作流的使用詳解
記錄一下工作流的在Springboot中的使用,,順便寫個demo,概念,什麼東西的我就不解釋了,如有問題歡迎各位大佬指導一下。
1.建立springboot專案後匯入依賴
<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency>
新增配置之後再springboot啟動類後面加上一行程式碼否則啟動時會報錯
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
新增資料來源以及activiti的配置
spring: activiti: database-schema-update: drop‐create //預設為false,activiti在啟動的時候會對比資料庫中的表中儲存的版本,如果不一樣會丟擲異常 // true activiti會對資料庫中的表進行更新操作,如果表不存在,則自動建立 // create_drop 在activiti啟動的時候建立表,關閉時刪除表,必須手動關閉 // drop-create 在啟動的時候先刪除表後再建立新的表 check-process-definitions: false datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC username: root password: root
2.初始化activiti表
這裡一共有3種方式去建立
第一種
@Test public void initTables() { //建立資料來源 // DriverManagerDataSource dataSource=new DriverManagerDataSource(); // dataSource.setDriverClassName("com.mysql.jdbc.Driver"); // dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test"); // dataSource.setUsername("root"); // dataSource.setPassword("root"); // 建立流程引擎的配置 ProcessEngineConfiguration configuration = ProcessEngineConfiguration .createStandaloneProcessEngineConfiguration(); configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver"); configuration.setJdbcUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&nullCatalogMeansCurrent=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC"); configuration.setJdbcUsername("root"); configuration.setJdbcPassword("root"); // 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); }
第二種配置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.cj.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useUnicode=true%26nullCatalogMeansCurrent=true%26characterEncoding=utf8%26useSSL=false%26serverTimezone=UTC"></property> <property name="jdbcUsername" value="root"></property> <property name="jdbcPassword" value="root"></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.xml"); // 得到流程引擎 ProcessEngine processEngine = configuration.buildProcessEngine(); System.out.println(processEngine); }
第三種方法
@Test public void intiTables3() { //必須建立activiti.cfg.xml 並配置好資料庫的資訊 ProcessEngine processEngine= ProcessEngines.getDefaultProcessEngine(); System.out.println(processEngine); }
3.開啟資料庫檢視
我們開啟資料庫檢視資料庫,會發現activiti已自動幫我們建立了28張表(有的好像也只有24張表,有興趣的可以研究一下)
這裡為大家解釋一下各張表的含義:Activiti的後臺是有資料庫的支援,所有的表都以ACT_開頭。 第二部分是表示表的用途的兩個字母標識。
ACT_RE_*: 'RE'表示repository。 這個字首的表包含了流程定義和流程靜態資源 (圖片,規則,等等)。
ACT_RU_*: 'RU'表示runtime。 這些執行時的表,包含流程例項,任務,變數,非同步任務,等執行中的資料。 Activiti只在流程例項執行過程中儲存這些資料, 在流程結束時就會刪除這些記錄。 這樣執行時表可以一直很小速度很快。
ACT_ID_*: 'ID'表示identity。 這些表包含身份資訊,比如使用者,組等等。
ACT_HI_*: 'HI'表示history。 這些表包含歷史資料,比如歷史流程例項, 變數,任務等等。
ACT_GE_*: 通用資料, 用於不同場景下,如存放資原始檔。
#RepositoryService Select * from act_ge_bytearray; 二進位制資料夾表 Select * from act_re_deployment; 流程部署表 Select * from act_re_procdef; 流程定義表 Select * from act_ge_property; 屬性資料表儲存整個流程引擎級別的資料,初始化表結構時,會預設插入三條記錄 #RuntimeService TaskService 執行時資料庫表 Select * from act_ru_excution; 流程啟動一次只要沒有執行完就會有一條資料 Select * from act_ru_task; 可能有多條資料 Select * from act_ru_variable; 記錄流程執行時的流程變數 Select * from act_ru_identitylink; 存放流程辦理人的資訊 #HistoryService 歷史資料庫表 Select * from act_hi_procinst; 歷史流程例項 Select * from act_hi_taskinst; 歷史任務例項 Select * from act_hi_actinst; 歷史節點表 Select * from act_hi_attachment; 歷史附件表 Select * from act_hicomment; 歷史意見表 Select * from act_hi_identitylink; 歷史流程人員表 Select * from act_hi_detail; 歷史詳情表提供歷史變數查詢 Select * from act_hi_procinst; 歷史流程例項表 Select * from act_hi_taskinst; 歷史任務例項表 Select * from act_hi_varinst; 歷史變量表 #IdentityService 這四張表儘量使用自己的一套,難以滿足需求 Select * from act_id_group; 使用者組資訊表 Select * from act_id_info; 使用者拓展資訊表 Select * from act_id_menbership; 使用者與使用者組對應表 Select * from act_id_user; 使用者資訊表
4.接下來開始畫請假流程圖(需要先安裝外掛),新建一個bpm檔案開始編輯
Assignee相當於辦理人的意思 我這裡是zhang 提出申請,主管yuan 稽核。
5.部署流程流程
// 得到流程引擎 private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); @Test public void deployProcess01() { // 得到流程部署的service RepositoryService repositoryService = this.processEngine.getRepositoryService(); Deployment deploy = repositoryService.createDeployment().name("請假流程").addClasspathResource("activitiTest.bpmn").deploy(); System.out.println("部署成功:流程部署ID:" + deploy.getId()); }
6.啟動流程(這裡的key與第五部第一張途中對應)
/** * 啟動流程 */ @Test public void startProcess() { RuntimeService runtimeService = this.processEngine.getRuntimeService(); // String processDefinitionId="HelloWorld:1:4"; // runtimeService.startProcessInstanceById(processDefinitionId); String processDefinitionKey="mytest"; runtimeService.startProcessInstanceByKey(processDefinitionKey); System.out.println("流程啟動成功"); }
7.根據使用者查詢任務(這裡使用流程圖中的assignee欄位)
@Test public void queryTask() { TaskService taskService = this.processEngine.getTaskService(); String assignee="chen"; 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("################################"); } } }
8.辦理任務(配合步驟8查詢出taskid然後進行辦理任務)
@Test public void completeTask() { TaskService taskService = this.processEngine.getTaskService(); String taskId="5005";//步驟8中查詢出來的taskId taskService.complete(taskId); System.out.println("任務完成"); }
重複7、8兩個步驟,自此一個完整的請假流程就完成了。
那麼肯定會有人問了,如果我想檢視一我們流程定義的資訊,流程圖,刪除流程定義等怎麼辦呢,話不多說直接上程式碼
package com.example; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.junit.jupiter.api.Test; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipInputStream; public class TestProcessProdef { // 得到流程引擎 private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); /** * 部署流程使用classpath */ @Test public void deployProcess01() { // 得到流程部署的service RepositoryService repositoryService = this.processEngine.getRepositoryService(); Deployment deploy = repositoryService.createDeployment().name("請假流程2").addClasspathResource("activiti.bpmn").deploy(); System.out.println("部署成功:流程部署ID:" + deploy.getId()); } /** * 查詢流程部署資訊 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("########################"); } } /** * 查詢流程定義 */ @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("##################"); } } } /** * 啟動流程 */ @Test public void startProcess() { RuntimeService runtimeService = this.processEngine.getRuntimeService(); String processDefinitionKey = "mytest"; runtimeService.startProcessInstanceByKey(processDefinitionKey); System.out.println("流程啟動成功"); } /** * 刪除流程定義 */ @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("刪除成功"); } /** * 查詢流程圖 根據流程定義ID */ @Test public void viewProcessImg() { RepositoryService repositoryService = this.processEngine.getRepositoryService(); String processDefinitionId = "mytest:2:2504"; InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId); File file = new File("d:/mytest.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,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,len); outputStream.flush(); } outputStream.close(); inputStream.close(); System.out.println("查詢成功"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 查詢最新的流程定義 */ @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("##################"); } } /** * 已知key 附加功能:刪除流程定義(刪除key相同的所有不同版本的流程定義) */ public void deleteAllSameVersion() { String processDefinitionKey = "mytest"; 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); } } } }
肯定還有人會問,上面的請假流程是走完了,但是沒有寫請假理由,請假天數,如果是報銷單的話 還需要上傳報銷單據等,那麼這個怎麼解決呢?這個時候就需要activiti提供給我們的流程變量了,那麼什麼是流程變數呢?
流程變數在整個工作流中扮演很重要的作用。例如:請假流程中有請假天數、請假原因等一些引數都為流程變數的範圍。流程變數的作用域範圍是只對應一個流程例項。也就是說各個流程例項的流程變數是不相互影響的。流程例項結束完成以後流程變數還儲存在資料庫中(存放到流程變數的歷史表中)。圖中紅框的資訊就是流程變數。
那麼我們怎麼設定流程變數呢,我們啟動流程的時候就可以設定流程變量了,見程式碼:
/** * 啟動流程 */ @Test public void startProcess() { RuntimeService runtimeService = this.processEngine.getRuntimeService(); String processDefinitionKey = "mytest"; // ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey); //建立流程變數物件 Map<String,Object> variables=new HashMap<>(); variables.put("請假天數",30);//int variables.put("請假原因","結婚"); variables.put("請假時間",new Date()); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,variables); System.out.println("流程啟動成功:" + processInstance.getId() + " " + processInstance.getProcessDefinitionId() + " " + processInstance.getProcessInstanceId()); }
說明:
1)流程變數的作用域就是流程例項,所以只要設定就行了,不用管在哪個階段設定
2)基本型別設定流程變數,在taskService中使用任務ID,定義流程變數的名稱,設定流程變數的值。
3)Javabean型別設定獲取流程變數,除了需要這個javabean實現了Serializable介面外,還要求流程變數物件的屬性不能發生變化,否則丟擲異常。解決方案,固定序列化ID
4)設定流程變數的時候,向act_ru_variable這個表新增資料
RuntimeService物件可以設定流程變數和獲取流程變數TaskService物件可以設定流程變數和獲取流程變數
Map集合的key表示流程變數的名稱 Map集合的value表示流程變數的值
查詢流程變數以及查詢歷史流程變數:
/** * 獲取流程變數 */ @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()); } /** * 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("#####################"); } }
查詢歷史流程例項 、查詢歷史活動 以及查詢歷史任務
public class TestHistoryQuery { private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine(); HistoryService historyService = this.processEngine.getHistoryService(); /* 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,查詢歷史活動 */ @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,查詢歷史任務 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("#######################################"); } } } }
最近我發現上面的程式碼不能完全在開發中應用,比如上面的使用者申請是在畫流程圖的時候寫死的,在實際開發中肯定是根據當前登入的使用者來提出申請,另外還沒有分支的情況,所以我特地修改了一下流程圖。
這個流程圖中 沒有設定使用者,在Condition中傳入引數#{UserId},後面的重要與不重要分支同樣加上Condition條件${message=='重要'}和${message=='不重要'},然後主管稽核和總經理的assignee可以設定成固定的值也可以像使用者一樣根據傳參設定。接下來直接上程式碼
1.啟動流程
/**啟動流程例項*/ @Test public void startProcessInstance(){ String processDefinitionKey = "myProcess_1"; /**啟動流程例項的同時,設定流程變數,使用流程變數用來指定任務的辦理人,對應task.pbmn檔案中#{userID}*/ Map<String,Object> variables = new HashMap<String,Object>(); variables.put("userID","袁志豪"); ProcessInstance pi = processEngine.getRuntimeService()//與正在執行的流程例項和執行物件相關的Service .startProcessInstanceByKey(processDefinitionKey,variables);//使用流程定義的key啟動流程例項,key對應helloworld.bpmn檔案中id的屬性值,使用key值啟動,預設是按照最新版本的流程定義啟動 System.out.println("流程例項ID:"+pi.getId());//流程例項ID 101 System.out.println("流程定義ID:"+pi.getProcessDefinitionId());//流程定義ID }
使用者完成申請提交,主管在流成圖中沒有設定固定值
@Test public void completeTask() { TaskService taskService = this.processEngine.getTaskService(); String taskId = "2508"; // 根據任務ID去完成任務 // taskService.complete(taskId); // 根據任務ID去完成任務並指定流程變數 Map<String,Object > variable =new HashMap<>(); String shenheren ="張三";//實際開發中可在前臺選擇主管傳入後臺 variable.put("zhuguan","張三");//這裡的 zhuguan 和 activiti.bpmn中的#{zhuguan}保持一致,既可以設定下一級稽核主管 taskService.complete(taskId,variables); System.out.println("任務完成"); }
主管稽核
@Test public void complateTask2(){ TaskService taskService = this.processEngine.getTaskService(); String taskId2= "5002"; Map<String,Object > variable =new HashMap<>(); /***這裡的message 是流程圖中分支條件message,根據傳入的引數判斷走那一條線***/ variable.put("message","重要"); // variable.put("message","不重要"); taskService.complete(taskId2,variable); }
經理稽核
@Test public void complateTask3(){ TaskService taskService = this.processEngine.getTaskService(); String taskId2= "7503"; Map<String,Object > variable =new HashMap<>(); variable.put("稽核意見","好好休假注意身體");//領導稽核意見 taskService.complete(taskId2,variable); }
另外我在開發中發現在流程圖畫完之後將bpmn字尾改為xml方式生成圖片之後,再次改為bpmn的時候,發現之前寫的Condition中變成了\n,如圖
我們再次將字尾改為xml之後檢視我們的條件:
解決方式:
將condition前面後面的空格刪掉即可;
到此這篇關於關於在IDEA中SpringBoot專案中activiti工作流的使用詳解的文章就介紹到這了,更多相關IDEA SpringBoot activiti工作流內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!