Aciviti工作流

1. springBoot和activiti整合

  • pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.14</version><relativePath/></parent><groupId>com.activiti7</groupId><artifactId>activiti7</artifactId><version>0.0.1-SNAPSHOT</version><name>activiti7</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Mysql驅動包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency><!-- activiti --><dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter</artifactId><version>7.1.0.M6</version></dependency><!-- 注意:activiti需要引入springSecurity包 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  • 數據庫的Config文件
@Configuration
public class DruidConfig {@Value("${spring.datasource.url}")private String url;@Value("${spring.datasource.username}")private String username;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.driver-class-name}")private String driverClassName;@Beanpublic DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);dataSource.setDriverClassName(driverClassName);// 其他 Druid 相關配置,如最大連接數、初始連接數等return dataSource;}@Beanpublic PlatformTransactionManager transactionManager() {return new DataSourceTransactionManager(dataSource());}
}
  • activiti的config配置類
@Configuration
public class ActivitiConfiguration {@Autowiredprivate DataSource dataSource;@Autowiredprivate PlatformTransactionManager platformTransactionManager;public ActivitiConfiguration() {}//通過@Bean注解將SpringProcessEngineConfiguration實例聲明為Spring Bean,使其可供其他組件注入和使用@Beanpublic SpringProcessEngineConfiguration springProcessEngineConfiguration() {SpringProcessEngineConfiguration spec = new SpringProcessEngineConfiguration();//設置數據源,將注入的數據源設置到SpringProcessEngineConfiguration實例中spec.setDataSource(this.dataSource);//設置事務管理器將注入的事務管理器設置到SpringProcessEngineConfiguration實例中spec.setTransactionManager(this.platformTransactionManager);//設置數據庫模式更新策略 true表示在啟動時自動創建或更新Activiti引擎所需的數據庫表結構spec.setDatabaseSchemaUpdate("true");//				這里我在部署項目的時候自己加載了bpmn文件,所以把這的掃面關掉了。
//                Resource[] resources = null;
//                //配置流程部署資源
//                //使用PathMatchingResourcePatternResolver從classpath中的bpmn目錄下加載所有以.bpmn為擴展名的文件作為流程定義資源,
//                // 并將它們設置到SpringProcessEngineConfiguration實例中。
//                try {
//                        resources = (new PathMatchingResourcePatternResolver()).getResources("classpath*:bpmn/*.bpmn");
//                } catch (IOException var4) {
//                        var4.printStackTrace();
//                }
//                spec.setDeploymentResources(resources);return spec;}
}
  • yaml文件
spring:datasource:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://123.57.27.43:3306/activiti?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=trueusername: rootpassword: newpwd

注意:啟動項目前需要提前創建好需要用到的數據庫

配置完成后啟動項目,啟動完成后activiti數據庫會自動創建25張activiti相關的表

2. activiti基礎

@SpringBootTest
class Activiti7Base {/*部署流程1.只提供了一種類目錄加載的方式,還有流、zip等方式。2.act_re_deployment表和act_re_procdef表3.注意:act_re_deployment表有一個系統自帶的流程每次啟動項目都會升級版本(暫時沒研究)*/@Testvoid contextLoads() {// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到repositoryService實例RepositoryService repositoryService = processEngine.getRepositoryService();// 使用repositoryService進行部署Deployment deployment = repositoryService.createDeployment().addClasspathResource("bpmn/diagram6.bpmn").addClasspathResource("bpmn/diagram6.svg").name("請假申請流程-10").deploy();System.out.println("流程部署id:"+deployment.getId());System.out.println("流程部署名稱:"+deployment.getName());}/*啟動流程*/@Testvoid startProcess(){// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 獲取runtimeService實例RuntimeService runtimeService = processEngine.getRuntimeService();// 根據流程定義Id啟動流程ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("java110_752023081032120386");System.out.println("流程定義Id:"+processInstance.getProcessDefinitionId());System.out.println("流程實例Id:"+processInstance.getId());System.out.println("當前活動Id:"+processInstance.getActivityId());}/*查詢用戶任務1.act_ru_task表*/@Testvoid queryUserTask(){// 負責人
//                String assignee = "mps1";
//                String assignee = "mps2";// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 創建taskServiceTaskService taskService = processEngine.getTaskService();// 根據流程key 和 任務負責人 查詢任務List<Task> list = taskService.createTaskQuery().processDefinitionKey("java110_752023081032120386")
//                        .taskAssignee(assignee).list();for(Task task : list){System.out.println("-------------------------");System.out.println("流程實例id:"+task.getProcessInstanceId());System.out.println("任務id:"+task.getId());System.out.println("任務負責人:"+task.getAssignee());System.out.println("任務名稱:"+task.getName());}}/*用戶完成任務*/@Testvoid finishTask(){// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 創建taskServiceTaskService taskService = processEngine.getTaskService();// 根據流程key 和 任務負責人 查詢任務Task task = taskService.createTaskQuery().processDefinitionKey("java110_752023081032120386").processInstanceId("2502") //流程實例id.taskAssignee("mps8").singleResult(); //singleResult()只返回一個任務,如果查詢結果有零個或多個任務會拋異常// 完成任務, 參數任務idtaskService.complete(task.getId());}/*查詢流程定義*/@Testvoid queryProcess(){// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 獲取repositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();// 獲取processDefinitionQuery對象ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();// 查詢當前所有的流程定義List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey("java110_752023081032120386").orderByProcessDefinitionVersion().desc().list();for(ProcessDefinition processDefinition : definitionList){System.out.println("流程定義 id="+processDefinition.getId());System.out.println("流程定義 name="+processDefinition.getName());System.out.println("流程定義 key="+processDefinition.getKey());System.out.println("流程定義 Version="+processDefinition.getVersion());System.out.println("流程部署ID="+processDefinition.getDeploymentId());}}/*查詢當前流程實例*/@Testvoid queryProcessInstance(){// 流程定義keyString processDefinitionKey = "java110_752023081032120386";// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 獲取runtimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey).list();for(ProcessInstance processInstance : list){System.out.println("---------------------------");System.out.println("流程實例id:"+processInstance.getProcessInstanceId());System.out.println("所屬流程定義id:"+processInstance.getProcessDefinitionId());System.out.println("是否執行完成:"+processInstance.isEnded());System.out.println("是否暫停:"+processInstance.isSuspended());System.out.println("當前活動標識:"+processInstance.getActivityId());System.out.println("業務關鍵字:"+processInstance.getBusinessKey());}}/*下載流程bpmn 和 圖片*/@Testvoid download() throws IOException {// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 獲取repositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();// 得到processDefinition,設置查詢條件,得到想要的流程定義ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("java110_752023081032120386").singleResult();// 通過流程定義信息,得到部署IDString deploymentId = processDefinition.getDeploymentId();// 讀取圖片和bpmnInputStream pngInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getResourceName());// 構造流File file_png = new File("D:/idea/work/activiti7/src/main/resources/download/aaa.svg");File file_bpmn = new File("D:/idea/work/activiti7/src/main/resources/download/aaa.bpmn");FileOutputStream bpmnOut = new FileOutputStream(file_bpmn);FileOutputStream pngOut = new FileOutputStream(file_png);// 輸出IOUtils.copy(pngInput,pngOut);IOUtils.copy(bpmnInput,bpmnOut);// 關閉流pngOut.close();bpmnOut.close();pngInput.close();bpmnInput.close();}/*查詢歷史記錄1.act_hi_actinst表*/@Testvoid queryHistoryInfo(){// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 獲取historyServiceHistoryService historyService = processEngine.getHistoryService();// 獲取act_hi_actinst表的查詢對象HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();// 設置條件instanceQuery.processInstanceId("5002");// 根據開始時間升序instanceQuery.orderByHistoricActivityInstanceStartTime().asc();// 查詢所有內容List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();for(HistoricActivityInstance hi : activityInstanceList){System.out.println(hi.getActivityId());System.out.println(hi.getActivityName());System.out.println(hi.getProcessDefinitionId());System.out.println(hi.getProcessInstanceId());System.out.println("<================================>");}}/*流程定義與流程實例1.流程定義ProcessDefinition和流程實例ProcessInstance是Activti中非常重要的兩個概念。他們的關系其實類似于JAVA中類和對象的概念。2.流程定義ProcessDefinition是以BPMN文件定義的一個工作流程,是一組工作規范。例如我們之前定義的請假流程。流程實例ProcessInstance則是指一個具體的業務流程。例如某個員工發起-一次請假,就會實例化一一個請假的流程實例,并且每個不同的流程實例之間是互不影響的。3.在后臺的表結構中,有很多張表都包含了流程定義ProcessDefinetion和流程實例rocsslnstance的字段。流程定義的字段通常是PROC_DEF_ID,而流程實例的字段通常是PROC_INST_ID。ProcessEngine對象1.processEngine.getRepositoryService() 	//流程定義對象2.processEngine.getRuntimeService() 	//運行時的對象(實例對象)3.processEngine.getHistoryService() 	//歷史記錄對象4.processEngine.getTaskService() 		//任務對象*/
}

3. activiti進階

@SpringBootTest
public class Activiti7Progress {/*啟動任務時,添加業務key*/@Testvoid addBusinessKey(){// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 獲取runtimeService實例RuntimeService runtimeService = processEngine.getRuntimeService();// 根據流程定義Id啟動流程ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("java110_752023081032120386","1001");System.out.println("businessKey:"+processInstance.getBusinessKey());}/*整個流程的掛起和激活 ,掛起就是讓改流程停止服務*/@Testvoid suspendAllProcessInstance(){// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 獲取repositoryServiceRepositoryService repositoryService = processEngine.getRepositoryService();// 得到processDefinition,設置查詢條件,得到想要的流程定義ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("java110_752023081032120386").singleResult();// 獲取當前流程是否是掛起狀態boolean suspended = processDefinition.isSuspended();// 獲取流程定義的idString definitionId = processDefinition.getId();// 如果是掛起狀態,改為激活狀態 否在掛起if(suspended){repositoryService.activateProcessDefinitionById(definitionId,true,null);System.out.println("流程定義id:"+definitionId+",已激活");}else {repositoryService.suspendProcessDefinitionById(definitionId,true,null);System.out.println("流程定義id:"+definitionId+",已掛起");}}/*掛起單個流程實例*/@Testvoid suspendSingleProcessInstance(){// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 獲取runtimeServiceRuntimeService runtimeService = processEngine.getRuntimeService();// 得到runtimeService,設置查詢條件,得到想要的流程定義ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId("30002").singleResult();// 獲取當前流程是否是掛起狀態boolean suspended = instance.isSuspended();// 獲取流程定義的idString definitionId = instance.getId();// 如果是掛起狀態,改為激活狀態 否在掛起if(suspended){runtimeService.activateProcessInstanceById(definitionId);System.out.println("流程定義id:"+definitionId+",已激活");}else {runtimeService.suspendProcessInstanceById(definitionId);System.out.println("流程定義id:"+definitionId+",已掛起");}}/*啟動流程,帶流程map變量1.涉及到的bpmn文件和網關圖片放在下面*/@Testvoid startProcessM(){// 創建ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 流程定義的keyString key = "java110_752023081032120386";// 流程變量mapHashMap<String, Object> variables = new HashMap<>();// 設置流程變量Evection evection = new Evection();// 設置請假日期evection.setNum(4d);// 把流程變量放入mapvariables.put("evection",evection);// 設置任務負責人
//                variables.put("assignee0","李四1");
//                variables.put("assignee1","王經理1");
//                variables.put("assignee2","楊總經理1");
//                variables.put("assignee3","張財務1");// 獲取runtimeService實例RuntimeService runtimeService = processEngine.getRuntimeService();// 根據流程定義Id啟動流程ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key,variables);System.out.println("流程定義Id:"+processInstance.getProcessDefinitionId());System.out.println("流程實例Id:"+processInstance.getId());System.out.println("當前活動Id:"+processInstance.getActivityId());}/*查詢候選用戶*/@Testvoid queryUsers(){//得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//得到TaskService對象TaskService taskService = processEngine.getTaskService();//設置一些參數,流程定義的key,候選用戶String key = "java110_752023081032120386";String candidateUsers = "mps8";//4.執行查詢List<Task> list = taskService.createTaskQuery().processDefinitionKey(key).taskCandidateUser(candidateUsers)//設置候選用戶.list();for (Task task : list) {System.out.println(task.getProcessInstanceId());System.out.println(task.getId());System.out.println(task.getName());System.out.println(task.getAssignee());//為null,說明當前的mps7只是一個候選人,并不是任務的執行人(需要拾取任務)}}/*查詢候選用戶組*/@Testvoid queryGroup(){// 得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到TaskService對象TaskService taskService = processEngine.getTaskService();// 設置一些參數,流程定義的key,候選用戶String key = "java110_752023081032120386";String candidateUsers = "mps8";List<Task> list = taskService.createTaskQuery().processDefinitionKey(key).taskCandidateGroup(candidateUsers)// 設置候選用戶.list();for (Task task : list) {System.out.println(task.getProcessInstanceId());System.out.println(task.getId());System.out.println(task.getName());System.out.println(task.getAssignee());//為null,說明當前的mps7只是一個候選人,并不是任務的執行人(需要拾取任務)}}/*候選用戶拾取任務*/@Testvoid claimTask(){// 得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到TaskService對象TaskService taskService = processEngine.getTaskService();// 設置一些參數,流程定義的key,候選用戶String key = "java110_752023081032120386";String candidateUsers = "mps8";Task task = taskService.createTaskQuery().processDefinitionKey(key)
//                        .taskCandidateUser(candidateUsers)// 設置候選用戶(候選用戶方式).taskCandidateGroup(candidateUsers)// 設置候選用戶(候選用戶組方式).singleResult();if (task != null) {taskService.claim(task.getId(), candidateUsers);// 第一個參數任務ID,第二個參數為具體的候選用戶名   此處可以try catch下,如果該任務已經被其他人拾取,會報異常,此時可以給前端展示任務已被拾取System.out.println("任務拾取完畢!"); // 拾取完之后就可以正常的進行辦理了}}/*任務的退還 和 交接*/@Testvoid connectTask(){// 得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到TaskService對象TaskService taskService = processEngine.getTaskService();// 設置一些參數,流程定義的key,用戶String key = "java110_752023081032120386";String assignee = "mps7";// 執行查詢Task task = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee)  // 設置任務的負責人.singleResult();// 判斷是否有這個任務if (task != null) {// 退還 如果設置為null,歸還組任務,該任務沒有負責人taskService.setAssignee(task.getId(), null);// 交接 交接任務為mps8  ,交接任務就是一個候選人拾取用戶的過程 // 注意:activiti沒有幫我們限制一定是候選組里面的人,可以交接給任意人
//                        taskService.setAssignee(task.getId(), "lisi");
//                        System.out.println("交接任務完成~!");}}/*任務委派*/@Testvoid delegateTask(){String key = "java110_752023081032120386";String assignee = "mps3";// 得到ProcessEngine對象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 得到TaskService對象TaskService taskService = processEngine.getTaskService();// 執行查詢Task task = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee)  // 設置任務的負責人.singleResult();// 判斷是否有這個任務if (task != null) {taskService.delegateTask(task.getId(),"mps2");}}/*1.claim() 和 setAssignee() 區別taskService.claim(String taskId,String userId);taskService.setAssignee(String taskId, String userId);都可以實現對任務的認領。兩個方法的區別在于執行 claim 方法時會檢查該任務是否已被簽收,如果已被簽收,則會拋出 ActivitiTaskAlreadyClaimedException 異常,其他方面兩個方法效果一致。2. 委派在act_ru_task表中OWNER_(委托人),ASSIGNEE_(辦理人)兩個字段。任務委托一定是任務的代理人assignee如mps3將自己的任務委托給用戶mps2原來表中:ASSIGNEE_=mps3    OWNER_=null委托后:ASSIGNEE_=mps2    OWNER_=mps3務必理解:OWNER_是委托前的辦理人3. 候選用戶 和 候選組候選用戶和候選組都需要先拾取任何,然后在辦理任務。沒有用戶拾取任務時代辦人(Assignee)為空。候選組有更加規范的使用方式,參考:https://blog.csdn.net/qq_41466440/article/details/130592801。*/
}

候選用戶,候選用戶組,代辦人

        /*查詢用候選用戶,候選用戶組*/@Testvoid queryUsersTask(){List<IdentityLink> forTask = taskService.getIdentityLinksForTask(task.getId());for(IdentityLink identityLink : forTask){System.out.println("<------------------候選組用戶>");System.out.println("GroupId:"+identityLink.getGroupId());System.out.println("ProcessDefinitionId:"+identityLink.getProcessDefinitionId());System.out.println("TaskId:"+identityLink.getTaskId());System.out.println("UserId:"+identityLink.getUserId());System.out.println("Type:"+identityLink.getType());System.out.println("ProcessInstanceId:"+identityLink.getProcessInstanceId());}}

查詢候選用戶結果:

<------------------候dai選組用戶>
GroupId:null
ProcessDefinitionId:null
TaskId:12503
UserId:mps7
Type:candidate
ProcessInstanceId:null
<------------------候選組用戶>
GroupId:null
ProcessDefinitionId:null
TaskId:12503
UserId:mps8
Type:candidate
ProcessInstanceId:null

查詢代辦用戶結果:

GroupId:null
ProcessDefinitionId:null
TaskId:20003
UserId:mps8
Type:assignee
ProcessInstanceId:null

查詢候選用戶組的結果:

<------------------候選組用戶>
GroupId:mps7
ProcessDefinitionId:null
TaskId:20003
UserId:null
Type:candidate
ProcessInstanceId:null
<------------------候選組用戶>
GroupId:mps8
ProcessDefinitionId:null
TaskId:20003
UserId:null
Type:candidate
ProcessInstanceId:null

注意:

  1. 返回結果的Type來區分:candidate候選用戶,assignee代辦用戶
  2. 候選組用戶這樣查詢,正常使用。
  3. 候選組有更加規范的使用方式,參考:https://blog.csdn.net/qq_41466440/article/details/130592801
  • 流程變量

流程變量的作用域

  • 全局流程變量:在整個流程執行期間,這個流程變量都是有效的。
  • 本地流程變量:這個只針對流程中某一個具體的 Task(任務)有效,這個任務執行完畢后,這個流程變量就失效了。
  • 臨時流程變量:顧名思義就是臨時的,這個不會存入到數據庫中(略)。

全局變量

  1. 啟動流程時設置變量
@Test
void test01() {Map<String, Object> variables = new HashMap<>();variables.put("days", 10);variables.put("reason", "休息一下");variables.put("startTime", new Date());ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01", variables);
}

儲存在ACT_RU_VARIABLE表和ACT_HI_VARINST表里面,每一個流程變量都有對應的流程實例 ID,這就說明這些流程變量是屬于某一個流程實例的。

@Test
void test01() {List<Execution> list = runtimeService.createExecutionQuery().list();for (Execution execution : list) {Object reason = runtimeService.getVariable(execution.getId(), "reason");}
}
/* sql
: ==> select * from ACT_RU_VARIABLE WHERE EXECUTION_ID_ = ? AND TASK_ID_ is null AND NAME_ = ?
: ==> 6fdd2007-4c3a-11ed-aa7e-acde48001122(String), reason(String)
: <== Total: 1
*/

查詢某一個流程的所有變量

@Test
void test02() {List<Execution> list = runtimeService.createExecutionQuery().list();for (Execution execution : list) {Map<String,Object> variables = runtimeService.getVariables(execution.getId());}
}
/* sql
: ==>  select * from ACT_RU_VARIABLE WHERE EXECUTION_ID_ = ? AND TASK_ID_ is null: ==> 6fdd2007-4c3a-11ed-aa7e-acde48001122(String): <== Total: 3*/
  1. 通過 Task 設置
@Test
void test03() {Task task = taskService.createTaskQuery().singleResult();taskService.setVariable(task.getId(), "days", 10); // 逐個設置Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());taskService.setVariables(task.getId(),variables); // 直接設置一個 Map
}
  1. 完成任務時設置
@Test
void test04() {Task task = taskService.createTaskQuery().singleResult();Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());variables.put("days", 10);taskService.complete(task.getId(),variables);
}
  1. 通過流程設置
@Test
void test05() {Execution execution = runtimeService.createExecutionQuery().singleResult();runtimeService.setVariable(execution.getId(), "days", 10); // 逐個設置Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());runtimeService.setVariables(execution.getId(), variables); // 直接設置一個 Map
}

本地變量

  1. 通過 Task 設置
@Test
void test03() {Task task = taskService.createTaskQuery().singleResult();taskService.setVariableLocal(task.getId(), "days", 10); // 逐個設置Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());taskService.setVariableLocal(task.getId(),variables); // 直接設置一個 Map
}

ACT_RU_VARIABLE 表的里的TASK_ID_ 有值字段就要值了。

通過taskService.complete(task.getId());執行完任務后就在ACT_RU_VARIABLE表里面查不到該變量了,需要在歷史表里面查詢。

@Test
void test07() {ProcessInstance pi = runtimeService.createProcessInstanceQuery().singleResult();List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(pi.getId()).list();for (HistoricVariableInstance hvi : list) {logger.info("name:{},type:{},value:{}", hvi.getVariableName(), hvi.getVariableTypeName(), hvi.getValue());}
}
  1. 完成任務時設置
@Test
void test04() {Task task = taskService.createTaskQuery().singleResult();Map<String, Object> variables = new HashMap<>();variables.put("reason", "休息一下");variables.put("startTime", new Date());variables.put("days", 10);taskService.complete(task.getId(),variables,true);
}
/*
complete(java.lang.String, java.util.Map<java.lang.String,java.lang.Object>, boolean):在完成一個 Task 的時候,如果傳遞了變量,則可以通過第三個參數來控制這個變量是全局的還是本地的,true 表示這個變量是本地的。
*/

后續加的設置變量的方法

  • 設置方法變量
  • ${da.e(qingjiakaishishijian)>da.e(‘2023-08-21’)} 需要這樣的e()方法來轉換字符串
// 定義一個類
public class Da implements Serializable {public long e(String date) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");try {return format.parse(date).getTime();} catch (ParseException e) {e.printStackTrace();}return 1;}
}// 設置變量HashMap<String, Object> variables = new HashMap<>();Da da = new Da();variables.put("qingjiakaishishijian","2023-08-22");variables.put("da",da);
// 設置到流程當中(也可以用其它方式設置,本例只寫啟動時設置)ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key,variables);

啟動流程,帶流程map變量時用到的文件

  • bpmn文件(文件局部內容)
  <bpmn2:process id="java110_752023081032120386" name="請假流程-10" isExecutable="true"><bpmn2:startEvent id="StartEvent_1" name="開始"><bpmn2:outgoing>Flow_0gx4dj0</bpmn2:outgoing></bpmn2:startEvent><bpmn2:sequenceFlow id="Flow_0gx4dj0" sourceRef="StartEvent_1" targetRef="Activity_1jdu4q4" /><bpmn2:sequenceFlow id="Flow_01hxak9" sourceRef="Activity_1jdu4q4" targetRef="Activity_0uxetgk" /><bpmn2:sequenceFlow id="Flow_0196722" name="大于等于3天" sourceRef="Activity_0uxetgk" targetRef="Activity_0wbgvlh"><bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">${evection.num&gt;=3}</bpmn2:conditionExpression></bpmn2:sequenceFlow><bpmn2:userTask id="Activity_1jdu4q4" name="提交者" activiti:assignee="${assignee0}"><bpmn2:incoming>Flow_0gx4dj0</bpmn2:incoming><bpmn2:outgoing>Flow_01hxak9</bpmn2:outgoing></bpmn2:userTask><bpmn2:userTask id="Activity_0uxetgk" name="部門經理" activiti:assignee="${assignee1}"><bpmn2:incoming>Flow_01hxak9</bpmn2:incoming><bpmn2:outgoing>Flow_0196722</bpmn2:outgoing><bpmn2:outgoing>Flow_05s60lc</bpmn2:outgoing></bpmn2:userTask><bpmn2:userTask id="Activity_0wbgvlh" name="總經理" activiti:assignee="${assignee2}"><bpmn2:incoming>Flow_0196722</bpmn2:incoming><bpmn2:outgoing>Flow_142455r</bpmn2:outgoing></bpmn2:userTask><bpmn2:sequenceFlow id="Flow_142455r" sourceRef="Activity_0wbgvlh" targetRef="Activity_0su91aq" /><bpmn2:userTask id="Activity_0su91aq" name="財務" activiti:assignee="${assignee3}"><bpmn2:incoming>Flow_142455r</bpmn2:incoming><bpmn2:incoming>Flow_05s60lc</bpmn2:incoming><bpmn2:outgoing>Flow_075zn6w</bpmn2:outgoing></bpmn2:userTask><bpmn2:sequenceFlow id="Flow_05s60lc" name="小于3天" sourceRef="Activity_0uxetgk" targetRef="Activity_0su91aq"><bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">${evection.num&lt;3}</bpmn2:conditionExpression></bpmn2:sequenceFlow><bpmn2:endEvent id="Event_0zvcra4"><bpmn2:incoming>Flow_075zn6w</bpmn2:incoming></bpmn2:endEvent><bpmn2:sequenceFlow id="Flow_075zn6w" sourceRef="Activity_0su91aq" targetRef="Event_0zvcra4" /></bpmn2:process>
  • 圖片

在這里插入圖片描述

候選用戶和候選組的bpmn文件

  • 候選組bpmn(文件局部內容)
<bpmn2:userTask id="Activity_1js1e5x" name="總經理" activiti:candidateGroups="mps7,mps8"><bpmn2:incoming>Flow_0o5ixaf</bpmn2:incoming><bpmn2:outgoing>Flow_192t89v</bpmn2:outgoing>
</bpmn2:userTask>
  • 候選用戶bpmn(文件局部內容)
<bpmn2:userTask id="Activity_1js1e5x" name="總經理" activiti:candidateUsers="mps7,mps8"><bpmn2:incoming>Flow_0o5ixaf</bpmn2:incoming><bpmn2:outgoing>Flow_192t89v</bpmn2:outgoing>
</bpmn2:userTask>

排他網關

  1. 設置天數就用帶流程map變量的啟動流程就行
  2. 也可以在流程當中設置流程變量(參考Global和Local)
  • 圖片

在這里插入圖片描述

并行網關

  1. 設置天數就用帶流程map變量的啟動流程就行
  2. 也可以在流程當中設置流程變量(參考Global和Local)
  3. 并行網關的條件不會執行
  4. 并行網關一般都是兩個一個分開一個聚合,并行網關兩個或多個都執行完成才合并然后往下走

在這里插入圖片描述

包含網關

  1. 設置天數就用帶流程map變量的啟動流程就行
  2. 也可以在流程當中設置流程變量(參考Global和Local)
  3. 包含網關相當于并行和排他的結合體,符合條件的都執行完才會合并然后往下走

在這里插入圖片描述

  • 設置天數用到的javaBean類(注意:一定到實現序列化接口)
public class Evection implements Serializable {private double num;public double getNum() {return num;}public void setNum(double num) {this.num = num;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906764.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906764.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906764.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

golang 對象池sync.Pool的實現

Go語言中sync.Pool通過多級緩存機制實現高效對象復用&#xff0c;其核心設計結合了GMP調度模型特性。以下是實現要點分析&#xff1a; P o o l ∑ p 0 G O M A X P R O C S ( l o c a l P o o l p ) v i c t i m C a c h e Pool \sum_{p0}^{GOMAXPROCS}(localPool_p) vict…

Docker run命令-p參數詳解

端口映射基礎語法 docker run -p <宿主機端口>:<容器端口> 操作示例 docker run -d --restartalways --namespug -p 5000:80 registry.aliyuncs.com/openspug/spug參數解析 -d&#xff1a;后臺運行容器--restartalways&#xff1a;設置容器自動重啟--namespug&…

《2.1.4 C語言中的整數類型及類型轉換|精講篇》

后面作者會在2025.5.25 00:00前整理出筆記和思維導圖大家放心&#xff0c;主頁還有其他文章 請先移步歡迎參考 收藏文章 關注博主 高效學習 好了&#xff0c;這小節我們要探討一個相對來說簡單的問題&#xff0c;就是C語言里邊的那些定點整數是如何進行強制類型轉換的。好來看這…

采用多維計算策略(分子動力學模擬+機器學習),顯著提升 α-半乳糖苷酶熱穩定性

字數 978&#xff0c;閱讀大約需 5 分鐘 在工業應用領域&#xff0c;α-半乳糖苷酶在食品加工、動物營養及醫療等方面發揮著重要作用。然而&#xff0c;微生物來源的該酶往往存在熱穩定性不足的問題&#xff0c;限制了其在工業場景中的高效應用。近日&#xff0c;來自江南大學的…

Jetpack Compose預覽調試技巧

Jetpack Compose 預覽(Preview)不顯示是一個常見問題,可能由多種原因導致。以下是系統的調試技巧和解決方案: 1. 檢查基礎配置 Compose 版本兼容性 確保 compose-compiler、compose-ui 等依賴版本一致且與 Kotlin 版本兼容。檢查 build.gradle: android {compileOptions {…

使用 Go 語言實現完整且輕量級高性能的 MQTT Broker

MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一種輕量級的發布/訂閱消息傳輸協議。但是目前雖然mqtt的客戶端很多&#xff0c;但是服務端著實不多&#xff0c;常見的服務端如mosquitto或emqx。但是golang語言的實現幾乎找不到。golang的輕量級部署和高并…

uv sync --frozen卡住不動

今天受邀幫同事調試uv卡住不動的問題&#xff0c;同樣的代碼已經在別的服務器跑起來了&#xff0c;換了一臺服務器之后&#xff0c;執行uv sync --frozen沒有按預期創建虛擬環境和安裝依賴。 1. 鏡像源是已經配置好的&#xff0c;pip install也能很快安裝包。 2. 查看了uv.lo…

Spring Boot中如何對密碼等敏感信息進行脫敏處理

以下是常見的脫敏方法及實現步驟&#xff0c;涵蓋配置、日志和API響應等多個層面&#xff1a; ?1. 配置文件敏感信息脫敏? (1) 使用加密庫&#xff08;如Jasypt&#xff09; ?步驟?&#xff1a; 添加依賴&#xff1a; <dependency><groupId>com.github.ulise…

springboot中redis的事務的研究

redis的事務類似于隊列操作&#xff0c;執行過程分為三步&#xff1a; 開啟事務入隊操作執行事務 使用到的幾個命令如下&#xff1a; 命令說明multi開啟一個事務exec事務提交discard事務回滾watch監聽key(s)&#xff1a;當監聽一個key(s)時&#xff0c;如果在本次事務提交之…

python打卡day35@浙大疏錦行

知識點回顧&#xff1a; 三種不同的模型可視化方法&#xff1a;推薦torchinfo打印summary權重分布可視化進度條功能&#xff1a;手動和自動寫法&#xff0c;讓打印結果更加美觀推理的寫法&#xff1a;評估模式 作業&#xff1a;調整模型定義時的超參數&#xff0c;對比下效果。…

Python爬蟲實戰:研究Crawley 框架相關技術

1. Crawley 框架相關定義 1.1 網絡爬蟲定義 網絡爬蟲是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本。它通過 HTTP 協議與 Web 服務器進行交互,獲取網頁內容并進行解析處理,是數據采集和信息檢索的重要工具。 1.2 Crawley 框架定義 Crawley 是一個基于 Pytho…

tvalid寄存器的理解

if(!out_axis_tvalid_reg || m_axis_tready ) beginend m_axis_tready 是上拍下一級給的ready信號 out_axis_tvalid_reg是上一拍&#xff0c;本級給下級的valid信號 一共有四種組合&#xff0c;然后可以通過這個if語句&#xff0c;在接下來的begin ... end中&#xff0c;用來…

【AI實戰】從“苦AI”到“爽AI”:Magentic-UI 把“人類-多智能體協作”玩明白了!

Hello&#xff0c;親愛的小伙伴們&#xff01;你是否曾經在深夜里&#xff0c;為了自動化點外賣、篩機票、抓網頁數據焦頭爛額&#xff1f;有沒有幻想過哪天能出個“貼心AI管家”&#xff0c;一鍵點菜、搞定事務、自動操作網頁&#xff0c;比你還懂你&#xff1f;更關鍵——還讓…

【東楓科技】usrp rfnoc 開發環境搭建

作者 太原市東楓電子科技有限公司 &#xff0c;代理銷售 USRP&#xff0c;Nvidia&#xff0c;等產品與技術支持&#xff0c;培訓服務。 環境 Ubuntu 20.04 依賴包 sudo apt-get updatesudo apt-get install autoconf automake build-essential ccache cmake cpufrequtils …

Ntfs!ReadIndexBuffer函數分析之根目錄讀取索引緩沖區的一個例子

Ntfs!ReadIndexBuffer函數分析之根目錄讀取索引緩沖區的一個例子 第一部分&#xff1a; 0: kd> p Ntfs!ReadIndexBuffer0xdc: f7173962 e829f60300 call Ntfs!NtfsCheckIndexBuffer (f71b2f90) 0: kd> t Ntfs!NtfsCheckIndexBuffer: f71b2f90 55 p…

LumaDot (亮度可調的屏幕圓點)

應用名稱 LumaDot &#xff08;源自 “Luminance”&#xff08;亮度&#xff09; “Dot”&#xff08;圓點&#xff09;&#xff0c;強調其核心功能&#xff1a;亮度可調的屏幕圓點&#xff09; 應用說明 LumaDot 是一款輕量級 Windows 桌面工具&#xff0c;專為需要屏幕標記…

HarmonyOS 鴻蒙應用開發基礎:EventHub,優雅解決跨組件通信難題

EventHub是鴻蒙開發中用于線程內通信的事件中心模塊&#xff0c;基于發布訂閱模式實現組件間的高效通信。它完美解決了傳統回調方式在多層嵌套場景下的痛點&#xff0c;使得組件間的通信更加靈活和易于管理。 核心特性 事件中心機制&#xff1a;通過事件名進行通信&#xff0c…

前端框架token相關bug,前后端本地聯調

今天我搭建框架的時候&#xff0c;我想請求我自己的本地&#xff01;然后我自己想鏈接我自己的本地后端&#xff0c;我之前用的前端項目&#xff0c;都是鏈別人的后端&#xff0c;基本上很少情況會鏈接自己的后端&#xff01;所以我當時想的是&#xff0c;我前后端接口一樣&…

【數據結構初階】順序表專題

文章目錄 順序表1.數據結構相關概念1、什么是數據結構2、為什么需要數據結構&#xff1f; 2.順序表1、順序表的概念及結構2、順序表分類3、動態順序表的實現1.定義一個動態順序表2.順序表的初始化3.順序表的銷毀4.順序表達的尾插5.順序表的頭插6.空間大小檢查函數7.順序表的尾刪…

從神經生物學到社會心理學:游戲沉迷機制的深度解構

你是否曾在深夜放下手機時驚覺&#xff1a;"明明只想玩10分鐘&#xff0c;怎么天都亮了&#xff1f;"這不是意志力薄弱的表現&#xff0c;而是價值數十億美元的游戲產業用神經科學精心設計的認知陷阱。 當《王者榮耀》的Victory音效讓你心跳加速&#xff0c;當《原神…