diff --git a/Activiti7Demo/src/main/resources/bpmn/asdf.bpmn20.xml b/Activiti7Demo/src/main/resources/bpmn/asdf.bpmn20.xml
new file mode 100644
index 0000000..2ee0a30
--- /dev/null
+++ b/Activiti7Demo/src/main/resources/bpmn/asdf.bpmn20.xml
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Activiti7Demo/src/main/resources/bpmn/leave.bpmn b/Activiti7Demo/src/main/resources/bpmn/leave.bpmn
new file mode 100644
index 0000000..3007100
--- /dev/null
+++ b/Activiti7Demo/src/main/resources/bpmn/leave.bpmn
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Activiti7Demo/src/main/resources/bpmn/leave.png b/Activiti7Demo/src/main/resources/bpmn/leave.png
new file mode 100644
index 0000000..b975e80
Binary files /dev/null and b/Activiti7Demo/src/main/resources/bpmn/leave.png differ
diff --git a/Activiti7Demo/src/main/resources/bpmn/leave1.bpmn20.xml b/Activiti7Demo/src/main/resources/bpmn/leave1.bpmn20.xml
new file mode 100644
index 0000000..191731b
--- /dev/null
+++ b/Activiti7Demo/src/main/resources/bpmn/leave1.bpmn20.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/Activiti7Demo/src/main/resources/sadasf.bpmn20.xml b/Activiti7Demo/src/main/resources/sadasf.bpmn20.xml
deleted file mode 100644
index 47d2c78..0000000
--- a/Activiti7Demo/src/main/resources/sadasf.bpmn20.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
-
- SequenceFlow_1
-
-
- SequenceFlow_1
- SequenceFlow_2
-
-
- SequenceFlow_2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Activiti7Demo/src/test/java/cn/whai/activiti/activiti7demo/Activiti7DemoApplicationTests.java b/Activiti7Demo/src/test/java/cn/whai/activiti/activiti7demo/Activiti7DemoApplicationTests.java
index 6710353..9143f84 100644
--- a/Activiti7Demo/src/test/java/cn/whai/activiti/activiti7demo/Activiti7DemoApplicationTests.java
+++ b/Activiti7Demo/src/test/java/cn/whai/activiti/activiti7demo/Activiti7DemoApplicationTests.java
@@ -1,24 +1,285 @@
package cn.whai.activiti.activiti7demo;
-import org.activiti.engine.ProcessEngine;
-import org.activiti.engine.ProcessEngineConfiguration;
-import org.activiti.engine.RepositoryService;
+import org.activiti.engine.*;
+import org.activiti.engine.history.HistoricProcessInstance;
+import org.activiti.engine.history.HistoricProcessInstanceQuery;
+import org.activiti.engine.repository.Deployment;
+import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Task;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
+import org.springframework.util.CollectionUtils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
@SpringBootTest
class Activiti7DemoApplicationTests {
+ @Autowired
+ private RepositoryService repositoryService;
@Test
void contextLoads() {
+ //进行部署
+ Deployment deployment = repositoryService.createDeployment()
+ .addClasspathResource("bpmn/leave.bpmn")
+ .addClasspathResource("bpmn/leave.png")
+ .name("请假流程")
+ .deploy();
+ //输出部署的一些信息
+ System.out.println("流程部署ID:"+deployment.getId());
+ System.out.println("流程部署名称:"+deployment.getName());
+ /**
+ * Opening JDBC Connection
+ * ==> Preparing: insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_) values(?, ?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b931f093-a0bf-11ef-a8d1-6ac6acfdceec(String), 请假流程(String), null, null, (String), 2024-11-12 14:31:17.803(Timestamp), null
+ * <== Updates: 1
+ * ==> Preparing: INSERT INTO ACT_GE_BYTEARRAY(ID_, REV_, NAME_, BYTES_, DEPLOYMENT_ID_, GENERATED_) VALUES (?, 1, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?)
+ * ==> Parameters: b931f094-a0bf-11ef-a8d1-6ac6acfdceec(String), bpmn/leave.png(String), java.io.ByteArrayInputStream@3d4ea4cf(ByteArrayInputStream), b931f093-a0bf-11ef-a8d1-6ac6acfdceec(String), false(Boolean), b93217a5-a0bf-11ef-a8d1-6ac6acfdceec(String), bpmn/leave.bpmn(String), java.io.ByteArrayInputStream@655e024(ByteArrayInputStream), b931f093-a0bf-11ef-a8d1-6ac6acfdceec(String), false(Boolean)
+ * <== Updates: 2
+ * Closing JDBC Connection [Transaction-aware proxy for target Connection [HikariProxyConnection@1997102220 wrapping com.mysql.cj.jdbc.ConnectionImpl@4ac2b4c6]]
+ * 流程部署ID:b931f093-a0bf-11ef-a8d1-6ac6acfdceec
+ * 流程部署名称:请假流程
+ */
+
}
+
+ @Test
+ void queryProcessDefinition() {
+
+ List processDefinitions = repositoryService.createProcessDefinitionQuery().list();
+ for (ProcessDefinition processDefinition : processDefinitions) {
+ 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());
+ System.out.println("流程定义资源名称:" + processDefinition.getResourceName());
+ System.out.println("流程定义图片资源名称:" + processDefinition.getDiagramResourceName());
+ System.out.println("流程定义描述:" + processDefinition.getDescription());
+ System.out.println("流程定义分类:" + processDefinition.getCategory());
+ System.out.println("======================================================");
+ }
+ /**
+ * Opening JDBC Connection
+ * ==> Preparing: select distinct RES.* from ACT_RE_PROCDEF RES order by RES.ID_ asc LIMIT ? OFFSET ?
+ * ==> Parameters: 2147483647(Integer), 0(Integer)
+ * <== Columns: ID_, REV_, CATEGORY_, NAME_, KEY_, VERSION_, DEPLOYMENT_ID_, RESOURCE_NAME_, DGRM_RESOURCE_NAME_, DESCRIPTION_, HAS_START_FORM_KEY_, HAS_GRAPHICAL_NOTATION_, SUSPENSION_STATE_, TENANT_ID_, ENGINE_VERSION_
+ * <== Row: Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec, 1, http://www.activiti.org/processdef, Part1_Deployment, Part1_Deployment, 1, 0c82b70d-a0c1-11ef-9820-6ac6acfdceec, bpmn/leave.bpmn, bpmn/leave.png, null, 0, 1, 1, , null
+ * <== Total: 1
+ * Closing JDBC Connection [Transaction-aware proxy for target Connection [HikariProxyConnection@1566233058 wrapping com.mysql.cj.jdbc.ConnectionImpl@17796f47]]
+ * 流程定义ID:Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec
+ * 流程定义名称:Part1_Deployment
+ * 流程定义key:Part1_Deployment
+ * 流程定义版本:1
+ * 流程部署ID:0c82b70d-a0c1-11ef-9820-6ac6acfdceec
+ * 流程定义资源名称:bpmn/leave.bpmn
+ * 流程定义图片资源名称:bpmn/leave.png
+ * 流程定义描述:null
+ * 流程定义分类:http://www.activiti.org/processdef
+ * ======================================================
+ */
+ }
+ // 流程实例
+ // 流程定义(ProcessDefinition)与流程实例(ProcessInstance)是一对多关系(salvio修改)
+ @Autowired
+ private RuntimeService runtimeService;
+ /**
+ * 初始化流程实例
+ */
+ @Test
+ public void initProcessInstance() {
+ // 流程定义KEY
+ String processDefinitionKey = "Part1_Deployment";
+ // 业务表KEY(用于把业务数据与Activiti7流程数据相关联)
+ String businessKey = "4208169753200945";
+ // 参数
+ Map variables = new HashMap<>(16);
+ ProcessInstance processInstance = this.runtimeService
+ .startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
+ System.out.println("流程实例ID:" + processInstance.getProcessInstanceId());
+ /**
+ * Opening JDBC Connection
+ * ==> Preparing: select * from ACT_RE_PROCDEF where KEY_ = ? and (TENANT_ID_ = '' or TENANT_ID_ is null) and VERSION_ = (select max(VERSION_) from ACT_RE_PROCDEF where KEY_ = ? and (TENANT_ID_ = '' or TENANT_ID_ is null))
+ * ==> Parameters: Part1_Deployment(String), Part1_Deployment(String)
+ * <== Columns: ID_, REV_, CATEGORY_, NAME_, KEY_, VERSION_, DEPLOYMENT_ID_, RESOURCE_NAME_, DGRM_RESOURCE_NAME_, DESCRIPTION_, HAS_START_FORM_KEY_, HAS_GRAPHICAL_NOTATION_, SUSPENSION_STATE_, TENANT_ID_, ENGINE_VERSION_
+ * <== Row: Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec, 1, http://www.activiti.org/processdef, Part1_Deployment, Part1_Deployment, 1, 0c82b70d-a0c1-11ef-9820-6ac6acfdceec, bpmn/leave.bpmn, bpmn/leave.png, null, 0, 1, 1, , null
+ * <== Total: 1
+ * ==> Preparing: select * from ACT_RU_VARIABLE where TASK_ID_ = ?
+ * ==> Parameters: b25c87dd-a0c3-11ef-8ba8-68c6acfdcef0(String)
+ * <== Total: 0
+ * ==> Preparing: insert into ACT_HI_TASKINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, OWNER_, ASSIGNEE_, START_TIME_, CLAIM_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TASK_DEF_KEY_, FORM_KEY_, PRIORITY_, DUE_DATE_, CATEGORY_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
+ * ==> Parameters: b25c87dd-a0c3-11ef-8ba8-68c6acfdcef0(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), UserTask(String), null, null, null, admin(String), 2024-11-12 14:59:44.325(Timestamp), null, null, null, null, sid-192966db-031d-4a50-886d-379935dd9bc1(String), null, 50(Integer), null, null, (String)
+ * <== Updates: 1
+ * ==> Preparing: insert into ACT_HI_PROCINST ( ID_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, START_TIME_, END_TIME_, DURATION_, START_USER_ID_, START_ACT_ID_, END_ACT_ID_, SUPER_PROCESS_INSTANCE_ID_, DELETE_REASON_, TENANT_ID_, NAME_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
+ * ==> Parameters: b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 4208169753200945(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), 2024-11-12 14:59:44.311(Timestamp), null, null, null, sid-26d6e725-878e-411d-b23d-6df4ae3cbd24(String), null, null, null, (String), null
+ * <== Updates: 1
+ * ==> Preparing: insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TENANT_ID_ ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b25ada2b-a0c3-11ef-8ba8-68c6acfdcef0(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), sid-26d6e725-878e-411d-b23d-6df4ae3cbd24(String), null, null, null, startEvent(String), null, 2024-11-12 14:59:44.314(Timestamp), 2024-11-12 14:59:44.316(Timestamp), 2(Long), null, (String), b25b4f5c-a0c3-11ef-8ba8-68c6acfdcef0(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), sid-192966db-031d-4a50-886d-379935dd9bc1(String), b25c87dd-a0c3-11ef-8ba8-68c6acfdcef0(String), null, UserTask(String), userTask(String), admin(String), 2024-11-12 14:59:44.317(Timestamp), null, null, null, (String)
+ * <== Updates: 2
+ * ==> Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b25cd5fe-a0c3-11ef-8ba8-68c6acfdcef0(String), participant(String), admin(String), null, null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String)
+ * <== Updates: 1
+ * ==> Preparing: insert into ACT_RU_EXECUTION (ID_, REV_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, IS_SCOPE_,IS_EVENT_SCOPE_, IS_MI_ROOT_, PARENT_ID_, SUPER_EXEC_, ROOT_PROC_INST_ID_, SUSPENSION_STATE_, TENANT_ID_, NAME_, START_TIME_, START_USER_ID_, IS_COUNT_ENABLED_, EVT_SUBSCR_COUNT_, TASK_COUNT_, JOB_COUNT_, TIMER_JOB_COUNT_, SUSP_JOB_COUNT_, DEADLETTER_JOB_COUNT_, VAR_COUNT_, ID_LINK_COUNT_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 4208169753200945(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), null, true(Boolean), false(Boolean), true(Boolean), false(Boolean), false(Boolean), null, null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 1(Integer), (String), null, 2024-11-12 14:59:44.311(Timestamp), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), null, Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), sid-192966db-031d-4a50-886d-379935dd9bc1(String), true(Boolean), false(Boolean), false(Boolean), false(Boolean), false(Boolean), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 1(Integer), (String), null, 2024-11-12 14:59:44.313(Timestamp), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer)
+ * <== Updates: 2
+ * ==> Preparing: insert into ACT_RU_TASK (ID_, REV_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, TASK_DEF_KEY_, DUE_DATE_, CATEGORY_, SUSPENSION_STATE_, TENANT_ID_, FORM_KEY_, CLAIM_TIME_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
+ * ==> Parameters: b25c87dd-a0c3-11ef-8ba8-68c6acfdcef0(String), UserTask(String), null, null, 50(Integer), 2024-11-12 14:59:44.317(Timestamp), null, admin(String), null, b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), sid-192966db-031d-4a50-886d-379935dd9bc1(String), null, null, 1(Integer), (String), null, null
+ * <== Updates: 1
+ * ==> Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b25cd5fe-a0c3-11ef-8ba8-68c6acfdcef0(String), participant(String), admin(String), null, null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), null
+ * <== Updates: 1
+ * Closing JDBC Connection [Transaction-aware proxy for target Connection [HikariProxyConnection@621103114 wrapping com.mysql.cj.jdbc.ConnectionImpl@4ac2b4c6]]
+ * 流程实例ID:b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0
+ */
+ }
+
+ /**
+ * 查询流程实例
+ */
+ @Test
+ public void getProcessInstance() {
+ String processInstanceId = "b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0";
+ ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery()
+ .processInstanceId(processInstanceId)
+ .singleResult();
+ System.out.println("ProcessInstanceId:" + processInstance.getProcessInstanceId());
+ System.out.println("ProcessDefinitionId:" + processInstance.getProcessDefinitionId());
+ System.out.println("isEnded:" + processInstance.isEnded());
+ System.out.println("isSuspended:" + processInstance.isSuspended());
+ /**
+ * Opening JDBC Connection
+ * ==> Preparing: select distinct RES.* , P.KEY_ as ProcessDefinitionKey, P.ID_ as ProcessDefinitionId, P.NAME_ as ProcessDefinitionName, P.VERSION_ as ProcessDefinitionVersion, P.DEPLOYMENT_ID_ as DeploymentId, S.PROC_INST_ID_ AS PARENT_PROC_INST_ID_ from ACT_RU_EXECUTION RES inner join ACT_RE_PROCDEF P on RES.PROC_DEF_ID_ = P.ID_ left outer join ACT_RU_EXECUTION S on RES.SUPER_EXEC_ = S.ID_ WHERE RES.PARENT_ID_ is null and RES.ID_ = ? and RES.PROC_INST_ID_ = ? order by RES.ID_ asc LIMIT ? OFFSET ?
+ * ==> Parameters: b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 2147483647(Integer), 0(Integer)
+ * <== Columns: ID_, REV_, PROC_INST_ID_, BUSINESS_KEY_, PARENT_ID_, PROC_DEF_ID_, SUPER_EXEC_, ROOT_PROC_INST_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, IS_SCOPE_, IS_EVENT_SCOPE_, IS_MI_ROOT_, SUSPENSION_STATE_, CACHED_ENT_STATE_, TENANT_ID_, NAME_, START_TIME_, START_USER_ID_, LOCK_TIME_, IS_COUNT_ENABLED_, EVT_SUBSCR_COUNT_, TASK_COUNT_, JOB_COUNT_, TIMER_JOB_COUNT_, SUSP_JOB_COUNT_, DEADLETTER_JOB_COUNT_, VAR_COUNT_, ID_LINK_COUNT_, ProcessDefinitionKey, ProcessDefinitionId, ProcessDefinitionName, ProcessDefinitionVersion, DeploymentId, PARENT_PROC_INST_ID_
+ * <== Row: b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0, 1, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0, 4208169753200945, null, Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec, null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0, null, 1, 0, 1, 0, 0, 1, null, , null, 2024-11-12 14:59:44.311, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, Part1_Deployment, Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec, Part1_Deployment, 1, 0c82b70d-a0c1-11ef-9820-6ac6acfdceec, null
+ * <== Total: 1
+ * Closing JDBC Connection [Transaction-aware proxy for target Connection [HikariProxyConnection@1118158255 wrapping com.mysql.cj.jdbc.ConnectionImpl@77eb0e47]]
+ * ProcessInstanceId:b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0
+ * ProcessDefinitionId:Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec
+ * isEnded:false
+ * isSuspended:false
+ */
+
+ // 查询流程实例列表
+ List processInstanceList = this.runtimeService.createProcessInstanceQuery().list();
+ if (!CollectionUtils.isEmpty(processInstanceList)) {
+ processInstanceList.forEach(pi -> {
+ System.out.println("ProcessInstanceId:" + pi.getProcessInstanceId());
+ System.out.println("ProcessDefinitionId:" + pi.getProcessDefinitionId());
+ System.out.println("isEnded:" + pi.isEnded());
+ System.out.println("isSuspended:" + pi.isSuspended());
+ });
+ }
+ // 挂起流程实例
+ this.runtimeService.suspendProcessInstanceById(processInstanceId);
+ // 激活流程实例
+ this.runtimeService.activateProcessInstanceById(processInstanceId);
+ // 删除流程实例
+ this.runtimeService.deleteProcessInstance(processInstanceId, "测试删除流程实例");
+ }
+
+ /**
+ * 任务管理
+ */
+ @Autowired
+ private TaskService taskService;
+
+ /**
+ * 查询任务列表
+ */
+ @Test
+ public void listTasks() {
+ List taskList = this.taskService.createTaskQuery().list();
+ if (!CollectionUtils.isEmpty(taskList)) {
+ taskList.forEach(task -> {
+ System.out.println("Id:" + task.getId());
+ System.out.println("Name:" + task.getName());
+ System.out.println("Assignee:" + task.getAssignee());
+ });
+ }
+ }
+
+
+ @Test
+ public void listTasksByAssignee() {
+ /**
+ * 查询Admin的代办任务
+ */
+ String assignee = "admin";
+ List taskList = this.taskService.createTaskQuery()
+ .taskAssignee(assignee)
+ .list();
+ if (!CollectionUtils.isEmpty(taskList)) {
+ taskList.forEach(task -> {
+ System.out.println("Id:" + task.getId());
+ System.out.println("Name:" + task.getName());
+ System.out.println("Assignee:" + task.getAssignee());
+ });
+ }
+
+
+ // 完成任务
+ String taskId = "354b9d90-477f-11ed-abfa-e4a8dfd43d4a";
+ Map variables = new HashMap<>(16);
+ this.taskService.complete(taskId, variables);
+
+
+ // 给定用户成为任务的受理人。
+ String userId = "jason";
+ taskService.claim(taskId, userId);
+
+ // 归还任务,分配的任务回收,撤回
+ taskService.unclaim(taskId);
+
+ // 将给定任务的被分派人更改为给定的 userId。不检查身份组件是否知道该用户。
+ taskService.setAssignee(taskId, userId);
+ }
+
+ @Autowired
+ private HistoryService historyService;
+
+ // 历史记录
+ @Test
+ public void history() {
+ // 查询历史流程实例
+ HistoricProcessInstanceQuery historicProcessInstanceQuery =
+ this.historyService
+ .createHistoricProcessInstanceQuery()
+ .orderByProcessInstanceEndTime();
+ List list = historicProcessInstanceQuery.list();
+
+ list.forEach(historicProcessInstance -> {
+ System.out.println("ProcessInstanceId:" + historicProcessInstance.getId());
+ System.out.println("ProcessDefinitionId:" + historicProcessInstance.getProcessDefinitionId());
+ });
+
+
+
+ // 根据流程实例ID查询历史
+ String processInstanceId = "0f8a9b00-479e-11ed-af85-e4a8dfd43d4a";
+ List historicProcessInstances =
+ this.historyService
+ .createHistoricProcessInstanceQuery()
+ .processInstanceId(processInstanceId)
+ .list();
+ historicProcessInstances.forEach(historicProcessInstance -> {
+ System.out.println("ProcessInstanceId:" + historicProcessInstance.getId());
+ System.out.println("ProcessDefinitionId:" + historicProcessInstance.getProcessDefinitionId());
+ });
+ }
+
+
+
}
diff --git a/Activiti7Demo/workflow.md b/Activiti7Demo/workflow.md
index 42b2621..4d61c6c 100644
--- a/Activiti7Demo/workflow.md
+++ b/Activiti7Demo/workflow.md
@@ -55,3 +55,225 @@ BPMN(Business Process Model And Notation),业务流程模型和符号,
- mysql
- 在Navicat工具中创建`activiti`的数据库,用于后续的实验.
+
+
+
+### Activiti使用步骤
+
+> 2.4.1 整合Activiti
+> Activiti是一个工作流引擎,业务系统使用Activiti来对系统的业务流程进行自动化管理,为了方便业务系统访问(操作)Activiti的接口或功能,通常将Activiti和业务系统的环境集成在一起。
+> 2.4.2 业务流程建模
+> 使用Activiti流程建模工具(Activity-designer)定义业务流程(.bpmn文件)。
+> .bpmn文件就是业务流程定义文件,通过xml定义业务流程。
+> 如果使用其他公司开发的工作引擎一般都提供了可视化的建模工具(Process Designer)用于生成流程定义文件,建模工具操作直观,一般都支持图形化拖拽方式、多窗口的用户界面、丰富的过程图形元素、过程元素拷贝、粘贴、删除等功能。
+> 2.4.3 部署业务流程
+> 向Activiti部署业务流程定义(.bpmn文件)。
+> 使用Activiti提供的API向Activiti中部署.bpmn文件(一般情况下还需要一起部署业务流程的图片.png)。
+> 2.4.4 启动流程实例
+> 启动一个流程实例表示开始一次业务流程的运行,比如员工请假流程部署完成,如果张三要请假就可以启动一个流程实例,如果李四要请假也需要启动一个流程实例,两个流程的执行互不影响,就好比定义一个Java类,实例化两个Java对象一样,部署的流程就好比Java类,启动一个流程实例就好比new一个Java对象。
+> 2.4.5 查询待办任务
+> 因为现在系统的业务流程已经交给Activiti管理,通过Activiti就可以查询当前流程执行到哪里了,当前用户需要办理什么任务了,这些Activiti帮我们管理了,而不像传统方式中需要我们在SQL语句中的WHERE条件中指定当前查询的状态值是多少。
+> 2.4.6 处理待办任务
+> 用户查询待办任务后,就可以办理某个任务,如果这任务办理完成还需要其他用户办理,比如采购单创建后由部门经理审核,这个过程也是由Activiti帮我们完成了,不需要我们在代码中硬编码指定下一个任务办理人了
+> 2.4.7 结束流程
+> 当任务办理完成没有下一个任务/结点了,这个流程实例就完成了。
+
+### Service总览
+
+![img](http://42.192.130.83:9000/picgo/imgs/v2-c33ee3444141b1a2c3b45ef88db771df_1440w.jpg_repeat_1731401329594__239673.png)
+
+- RepositoryService Activiti的资源管理接口:管理和控制流程发布包和流程定义的操作
+- RuntimeService Activiti的流程运行管理接口:流程执行相关的信息
+- TaskService Activiti的任务管理接口:
+- HistoryService Activiti的历史管理接口
+- ManagementService Activiti的引擎管理接口,管理和维护功能
+
+#### 数据表解读
+
+Activiti 使用到的表都是 ACT_ 开头的,表名的第二部分表示用途。
+
+##### ACT_GE_ (GE) 表示 general 全局通用数据及设置,各种情况都使用的数据。
+
+> #### 全局通用数据(ACT_GE_*)
+>
+> | ACT_GE_BYTEARRAY | 二进制数据表,存储通用的流程定义和流程资源。 |
+> | ---------------- | ---------------------------------------------------- |
+> | ACT_GE_PROPERTY | 系统相关属性,属性数据表存储整个流程引擎级别的数据。 |
+
+##### ACT_HI_ (HI) 表示 history 历史数据表,包含着程执行的历史相关数据。
+
+##### ACT_RE_ (RE) 表示 repository 存储,包含的是静态信息。
+
+##### ACT_RU_ (RU) 表示 runtime 运行时,运行时的流程变量,用户任务,变量,职责(job)等运行时数据。Activiti 只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录 (salvio修
+
+
+
+
+
+## 流程定义 ProcessDefinition
+
+```java
+@Autowired
+private RepositoryService repositoryService;
+@Test
+void queryProcessDe() {
+ List processDefinitions = repositoryService.createProcessDefinitionQuery().list();
+ for (ProcessDefinition processDefinition : processDefinitions) {
+ 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());
+ System.out.println("流程定义资源名称:" + processDefinition.getResourceName());
+ System.out.println("流程定义图片资源名称:" + processDefinition.getDiagramResourceName());
+ System.out.println("流程定义描述:" + processDefinition.getDescription());
+ System.out.println("流程定义分类:" + processDefinition.getCategory());
+ System.out.println("======================================================");
+ }
+ /**
+ * Opening JDBC Connection
+ * ==> Preparing: select distinct RES.* from ACT_RE_PROCDEF RES order by RES.ID_ asc LIMIT ? OFFSET ?
+ * ==> Parameters: 2147483647(Integer), 0(Integer)
+ * <== Columns: ID_, REV_, CATEGORY_, NAME_, KEY_, VERSION_, DEPLOYMENT_ID_, RESOURCE_NAME_, DGRM_RESOURCE_NAME_, DESCRIPTION_, HAS_START_FORM_KEY_, HAS_GRAPHICAL_NOTATION_, SUSPENSION_STATE_, TENANT_ID_, ENGINE_VERSION_
+ * <== Row: Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec, 1, http://www.activiti.org/processdef, Part1_Deployment, Part1_Deployment, 1, 0c82b70d-a0c1-11ef-9820-6ac6acfdceec, bpmn/leave.bpmn, bpmn/leave.png, null, 0, 1, 1, , null
+ * <== Total: 1
+ * Closing JDBC Connection [Transaction-aware proxy for target Connection [HikariProxyConnection@1566233058 wrapping com.mysql.cj.jdbc.ConnectionImpl@17796f47]]
+ * 流程定义ID:Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec
+ * 流程定义名称:Part1_Deployment
+ * 流程定义key:Part1_Deployment
+ * 流程定义版本:1
+ * 流程部署ID:0c82b70d-a0c1-11ef-9820-6ac6acfdceec
+ * 流程定义资源名称:bpmn/leave.bpmn
+ * 流程定义图片资源名称:bpmn/leave.png
+ * 流程定义描述:null
+ * 流程定义分类:http://www.activiti.org/processdef
+ * ======================================================
+ */
+}
+```
+
+
+
+## 流程实例 ProcessInstance
+
+
+
+```java
+/**
+ * 初始化流程实例
+ */
+@Test
+public void initProcessInstance() {
+ // 流程定义KEY
+ String processDefinitionKey = "Part1_Deployment";
+ // 业务表KEY(用于把业务数据与Activiti7流程数据相关联)
+ String businessKey = "4208169753200945";
+ // 参数
+ Map variables = new HashMap<>(16);
+ ProcessInstance processInstance = this.runtimeService
+ .startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
+ System.out.println("流程实例ID:" + processInstance.getProcessInstanceId());
+ /**
+ * Opening JDBC Connection
+ * ==> Preparing: select * from ACT_RE_PROCDEF where KEY_ = ? and (TENANT_ID_ = '' or TENANT_ID_ is null) and VERSION_ = (select max(VERSION_) from ACT_RE_PROCDEF where KEY_ = ? and (TENANT_ID_ = '' or TENANT_ID_ is null))
+ * ==> Parameters: Part1_Deployment(String), Part1_Deployment(String)
+ * <== Columns: ID_, REV_, CATEGORY_, NAME_, KEY_, VERSION_, DEPLOYMENT_ID_, RESOURCE_NAME_, DGRM_RESOURCE_NAME_, DESCRIPTION_, HAS_START_FORM_KEY_, HAS_GRAPHICAL_NOTATION_, SUSPENSION_STATE_, TENANT_ID_, ENGINE_VERSION_
+ * <== Row: Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec, 1, http://www.activiti.org/processdef, Part1_Deployment, Part1_Deployment, 1, 0c82b70d-a0c1-11ef-9820-6ac6acfdceec, bpmn/leave.bpmn, bpmn/leave.png, null, 0, 1, 1, , null
+ * <== Total: 1
+ * ==> Preparing: select * from ACT_RU_VARIABLE where TASK_ID_ = ?
+ * ==> Parameters: b25c87dd-a0c3-11ef-8ba8-68c6acfdcef0(String)
+ * <== Total: 0
+ * ==> Preparing: insert into ACT_HI_TASKINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, OWNER_, ASSIGNEE_, START_TIME_, CLAIM_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TASK_DEF_KEY_, FORM_KEY_, PRIORITY_, DUE_DATE_, CATEGORY_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
+ * ==> Parameters: b25c87dd-a0c3-11ef-8ba8-68c6acfdcef0(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), UserTask(String), null, null, null, admin(String), 2024-11-12 14:59:44.325(Timestamp), null, null, null, null, sid-192966db-031d-4a50-886d-379935dd9bc1(String), null, 50(Integer), null, null, (String)
+ * <== Updates: 1
+ * ==> Preparing: insert into ACT_HI_PROCINST ( ID_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, START_TIME_, END_TIME_, DURATION_, START_USER_ID_, START_ACT_ID_, END_ACT_ID_, SUPER_PROCESS_INSTANCE_ID_, DELETE_REASON_, TENANT_ID_, NAME_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
+ * ==> Parameters: b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 4208169753200945(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), 2024-11-12 14:59:44.311(Timestamp), null, null, null, sid-26d6e725-878e-411d-b23d-6df4ae3cbd24(String), null, null, null, (String), null
+ * <== Updates: 1
+ * ==> Preparing: insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TENANT_ID_ ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b25ada2b-a0c3-11ef-8ba8-68c6acfdcef0(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), sid-26d6e725-878e-411d-b23d-6df4ae3cbd24(String), null, null, null, startEvent(String), null, 2024-11-12 14:59:44.314(Timestamp), 2024-11-12 14:59:44.316(Timestamp), 2(Long), null, (String), b25b4f5c-a0c3-11ef-8ba8-68c6acfdcef0(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), sid-192966db-031d-4a50-886d-379935dd9bc1(String), b25c87dd-a0c3-11ef-8ba8-68c6acfdcef0(String), null, UserTask(String), userTask(String), admin(String), 2024-11-12 14:59:44.317(Timestamp), null, null, null, (String)
+ * <== Updates: 2
+ * ==> Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b25cd5fe-a0c3-11ef-8ba8-68c6acfdcef0(String), participant(String), admin(String), null, null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String)
+ * <== Updates: 1
+ * ==> Preparing: insert into ACT_RU_EXECUTION (ID_, REV_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, IS_SCOPE_,IS_EVENT_SCOPE_, IS_MI_ROOT_, PARENT_ID_, SUPER_EXEC_, ROOT_PROC_INST_ID_, SUSPENSION_STATE_, TENANT_ID_, NAME_, START_TIME_, START_USER_ID_, IS_COUNT_ENABLED_, EVT_SUBSCR_COUNT_, TASK_COUNT_, JOB_COUNT_, TIMER_JOB_COUNT_, SUSP_JOB_COUNT_, DEADLETTER_JOB_COUNT_, VAR_COUNT_, ID_LINK_COUNT_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 4208169753200945(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), null, true(Boolean), false(Boolean), true(Boolean), false(Boolean), false(Boolean), null, null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 1(Integer), (String), null, 2024-11-12 14:59:44.311(Timestamp), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), null, Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), sid-192966db-031d-4a50-886d-379935dd9bc1(String), true(Boolean), false(Boolean), false(Boolean), false(Boolean), false(Boolean), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 1(Integer), (String), null, 2024-11-12 14:59:44.313(Timestamp), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer)
+ * <== Updates: 2
+ * ==> Preparing: insert into ACT_RU_TASK (ID_, REV_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, TASK_DEF_KEY_, DUE_DATE_, CATEGORY_, SUSPENSION_STATE_, TENANT_ID_, FORM_KEY_, CLAIM_TIME_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
+ * ==> Parameters: b25c87dd-a0c3-11ef-8ba8-68c6acfdcef0(String), UserTask(String), null, null, 50(Integer), 2024-11-12 14:59:44.317(Timestamp), null, admin(String), null, b25ab31a-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec(String), sid-192966db-031d-4a50-886d-379935dd9bc1(String), null, null, 1(Integer), (String), null, null
+ * <== Updates: 1
+ * ==> Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?)
+ * ==> Parameters: b25cd5fe-a0c3-11ef-8ba8-68c6acfdcef0(String), participant(String), admin(String), null, null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), null
+ * <== Updates: 1
+ * Closing JDBC Connection [Transaction-aware proxy for target Connection [HikariProxyConnection@621103114 wrapping com.mysql.cj.jdbc.ConnectionImpl@4ac2b4c6]]
+ * 流程实例ID:b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0
+ */
+}
+
+/**
+ * 查询流程实例
+ */
+@Test
+public void getProcessInstance() {
+ String processInstanceId = "b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0";
+ ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery()
+ .processInstanceId(processInstanceId)
+ .singleResult();
+ System.out.println("ProcessInstanceId:" + processInstance.getProcessInstanceId());
+ System.out.println("ProcessDefinitionId:" + processInstance.getProcessDefinitionId());
+ System.out.println("isEnded:" + processInstance.isEnded());
+ System.out.println("isSuspended:" + processInstance.isSuspended());
+ /**
+ * Opening JDBC Connection
+ * ==> Preparing: select distinct RES.* , P.KEY_ as ProcessDefinitionKey, P.ID_ as ProcessDefinitionId, P.NAME_ as ProcessDefinitionName, P.VERSION_ as ProcessDefinitionVersion, P.DEPLOYMENT_ID_ as DeploymentId, S.PROC_INST_ID_ AS PARENT_PROC_INST_ID_ from ACT_RU_EXECUTION RES inner join ACT_RE_PROCDEF P on RES.PROC_DEF_ID_ = P.ID_ left outer join ACT_RU_EXECUTION S on RES.SUPER_EXEC_ = S.ID_ WHERE RES.PARENT_ID_ is null and RES.ID_ = ? and RES.PROC_INST_ID_ = ? order by RES.ID_ asc LIMIT ? OFFSET ?
+ * ==> Parameters: b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0(String), 2147483647(Integer), 0(Integer)
+ * <== Columns: ID_, REV_, PROC_INST_ID_, BUSINESS_KEY_, PARENT_ID_, PROC_DEF_ID_, SUPER_EXEC_, ROOT_PROC_INST_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, IS_SCOPE_, IS_EVENT_SCOPE_, IS_MI_ROOT_, SUSPENSION_STATE_, CACHED_ENT_STATE_, TENANT_ID_, NAME_, START_TIME_, START_USER_ID_, LOCK_TIME_, IS_COUNT_ENABLED_, EVT_SUBSCR_COUNT_, TASK_COUNT_, JOB_COUNT_, TIMER_JOB_COUNT_, SUSP_JOB_COUNT_, DEADLETTER_JOB_COUNT_, VAR_COUNT_, ID_LINK_COUNT_, ProcessDefinitionKey, ProcessDefinitionId, ProcessDefinitionName, ProcessDefinitionVersion, DeploymentId, PARENT_PROC_INST_ID_
+ * <== Row: b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0, 1, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0, 4208169753200945, null, Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec, null, b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0, null, 1, 0, 1, 0, 0, 1, null, , null, 2024-11-12 14:59:44.311, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, Part1_Deployment, Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec, Part1_Deployment, 1, 0c82b70d-a0c1-11ef-9820-6ac6acfdceec, null
+ * <== Total: 1
+ * Closing JDBC Connection [Transaction-aware proxy for target Connection [HikariProxyConnection@1118158255 wrapping com.mysql.cj.jdbc.ConnectionImpl@77eb0e47]]
+ * ProcessInstanceId:b25a64f9-a0c3-11ef-8ba8-68c6acfdcef0
+ * ProcessDefinitionId:Part1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec
+ * isEnded:false
+ * isSuspended:false
+ */
+
+ // 查询流程实例列表
+ List processInstanceList = this.runtimeService.createProcessInstanceQuery().list();
+ if (!CollectionUtils.isEmpty(processInstanceList)) {
+ processInstanceList.forEach(pi -> {
+ System.out.println("ProcessInstanceId:" + pi.getProcessInstanceId());
+ System.out.println("ProcessDefinitionId:" + pi.getProcessDefinitionId());
+ System.out.println("isEnded:" + pi.isEnded());
+ System.out.println("isSuspended:" + pi.isSuspended());
+ });
+ }
+ // 挂起流程实例
+ this.runtimeService.suspendProcessInstanceById(processInstanceId);
+ // 激活流程实例
+ this.runtimeService.activateProcessInstanceById(processInstanceId);
+ // 删除流程实例
+ this.runtimeService.deleteProcessInstance(processInstanceId, "测试删除流程实例");
+}
+```
+
+
+
+## **流程符号**
+
+### 事件 Event
+
+![img](http://42.192.130.83:9000/picgo/imgs/v2-7abf29716c8a87df55a503f537b86230_1440w.jpg_repeat_1731401500483__988588.png)
+
+### **网关 GateWay**
+
+![img](http://42.192.130.83:9000/picgo/imgs/v2-f27e0ae9d25d13b7b0cc90fceaffd732_1440w.jpg_repeat_1731401505552__805264.png)
+
+- 排他网关:只有一条路径会被选择
+- 并行网关:所有路径都会被选择
+- 包容网关:可以在网关上设置条件,**为每个输出设置计算**
+- 事件网关:进入等待状态,**等待事件后转为活动状态**
+
+### 流向 Flow
+
+![img](http://42.192.130.83:9000/picgo/imgs/v2-9f863cc8aa78ed965a8a50349bcd3304_1440w.jpg_repeat_1731401793171__863727.png)
+
+##
diff --git a/ForJdk17/src/main/java/cn/whaifree/interview/ct/P1.java b/ForJdk17/src/main/java/cn/whaifree/interview/ct/P1.java
new file mode 100644
index 0000000..dd64383
--- /dev/null
+++ b/ForJdk17/src/main/java/cn/whaifree/interview/ct/P1.java
@@ -0,0 +1,111 @@
+package cn.whaifree.interview.ct;
+
+import java.util.*;
+
+/**
+ * @version 1.0
+ * @Author whai文海
+ * @Date 2024/11/13 21:18
+ * @注释
+ */
+public class P1 {
+
+ // Method to parse configurations
+ private static void parseConfig(List lines, Set physical, Map> bonds, Map vlans) {
+ for (String line : lines) {
+ String[] parts = line.split(" ");
+ switch (parts[0]) {
+ case "Physical":
+ physical.add(parts[1]);
+ break;
+ case "Bond":
+ String bondName = parts[1];
+ List children = new ArrayList<>(Arrays.asList(parts).subList(3, parts.length));
+ Collections.sort(children);
+ bonds.put(bondName, children);
+ break;
+ case "VLAN":
+ vlans.put(parts[1], parts[2]);
+ break;
+ }
+ }
+ }
+
+ // Method to calculate minimum steps
+ public static int calculateMinSteps(List currentLines, List targetLines) {
+ // Parsing current and target configurations
+ Set currentPhysical = new HashSet<>();
+ Map> currentBonds = new HashMap<>();
+ Map currentVlans = new HashMap<>();
+ parseConfig(currentLines, currentPhysical, currentBonds, currentVlans);
+
+ Set targetPhysical = new HashSet<>();
+ Map> targetBonds = new HashMap<>();
+ Map targetVlans = new HashMap<>();
+ parseConfig(targetLines, targetPhysical, targetBonds, targetVlans);
+
+ int steps = 0;
+
+ // Step 1: Delete extra bonds and vlans in the current configuration
+ for (String bond : new HashSet<>(currentBonds.keySet())) {
+ if (!targetBonds.containsKey(bond)) {
+ currentBonds.remove(bond);
+ steps++;
+ }
+ }
+ for (String vlan : new HashSet<>(currentVlans.keySet())) {
+ if (!targetVlans.containsKey(vlan)) {
+ currentVlans.remove(vlan);
+ steps++;
+ }
+ }
+
+ // Step 2: Add missing bonds and vlans in the current configuration
+ for (Map.Entry> entry : targetBonds.entrySet()) {
+ String bond = entry.getKey();
+ List targetChildren = entry.getValue();
+ if (!currentBonds.containsKey(bond)) {
+ currentBonds.put(bond, targetChildren);
+ steps++;
+ } else if (!currentBonds.get(bond).equals(targetChildren)) {
+ currentBonds.put(bond, targetChildren);
+ steps++;
+ }
+ }
+
+ for (Map.Entry entry : targetVlans.entrySet()) {
+ String vlan = entry.getKey();
+ String targetParent = entry.getValue();
+ if (!currentVlans.containsKey(vlan)) {
+ currentVlans.put(vlan, targetParent);
+ steps++;
+ } else if (!currentVlans.get(vlan).equals(targetParent)) {
+ currentVlans.put(vlan, targetParent);
+ steps++;
+ }
+ }
+
+ return steps;
+ }
+ public static void main(String[] args) {
+ Scanner scanner = new Scanner(System.in);
+
+ int n = Integer.parseInt(scanner.nextLine());
+ List currentLines = new ArrayList<>();
+ for (int i = 0; i < n; i++) {
+ currentLines.add(scanner.nextLine().trim());
+ }
+
+ int m = Integer.parseInt(scanner.nextLine());
+ List targetLines = new ArrayList<>();
+ for (int i = 0; i < m; i++) {
+ targetLines.add(scanner.nextLine().trim());
+ }
+
+ int result = calculateMinSteps(currentLines, targetLines);
+ System.out.println(result);
+
+ scanner.close();
+ }
+
+}
diff --git a/ForJdk17/src/main/java/cn/whaifree/interview/js/P1.java b/ForJdk17/src/main/java/cn/whaifree/interview/js/P1.java
index 48c44ed..b01629d 100644
--- a/ForJdk17/src/main/java/cn/whaifree/interview/js/P1.java
+++ b/ForJdk17/src/main/java/cn/whaifree/interview/js/P1.java
@@ -60,6 +60,8 @@ class p2{
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
+ * 给你一个数组,你可以随意操作任意相邻的元素都+1,请问需要多少次可以让整个数组变成对称的
+ *
* @param arr int整型一维数组
* @return long长整型
*/
@@ -80,4 +82,44 @@ class p2{
int i = dp[0][n - 1];
return i;
}
+
+ public static class Solution {
+ public int minOperations(int[] arr) {
+ int n = arr.length;
+
+ // 如果数组长度是奇数,中心元素不参与对称操作
+ int operations = 0;
+
+ // 使用双指针,从两端往中间移动
+ for (int i = 0; i < n / 2; i++) {
+ int left = arr[i];
+ int right = arr[n - i - 1];
+
+ // 计算两个元素的差值
+ int diff = Math.abs(left - right);
+
+ // 如果差值是奇数,不能通过 +1 操作得到相等的数
+ if (diff % 2 != 0) {
+ return -1;
+ }
+
+ // 每次需要 diff / 2 次操作来平衡这两个元素
+ operations += diff / 2;
+ }
+
+ return operations;
+ }
+
+ public static void main(String[] args) {
+ Solution solution = new Solution();
+
+ // 示例测试
+ int[] arr1 = {1, 2, 2, 1, 1};
+ System.out.println(solution.minOperations(arr1)); // 输出: 0
+
+ int[] arr2 = {1, 2, 3, 4, 5};
+ System.out.println(solution.minOperations(arr2)); // 输出: -1
+ }
+ }
+
}
diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1648.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1648.java
new file mode 100644
index 0000000..2113dfa
--- /dev/null
+++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1648.java
@@ -0,0 +1,98 @@
+package cn.whaifree.leetCode;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+
+import java.util.*;
+
+/**
+ * @version 1.0
+ * @Author whai文海
+ * @Date 2024/11/12 11:47
+ * @注释
+ */
+public class LeetCode1648 {
+
+// @Test
+// public void test() {
+// int[] inventory = {1000000000};
+// int res = new Solution().maxProfit(inventory, 1000000000);
+// System.out.println(res);
+// }
+//
+// class Solution {
+//
+//
+// /**
+// * 数量最多的同色球的数量 和 球数 == MAX 的颜色的数量。
+// *
+// * @param inventory
+// * @param orders
+// * @return
+// */
+// public int maxProfit(int[] inventory, int orders) {
+//
+// Arrays.sort(inventory);
+//
+// int res = 0;
+// int countOfColor = 1;
+// for (int i = inventory.length - 1; i > 0; i--) {
+// int end = inventory[i];
+// int start = inventory[i - 1];
+// for (int j = end; j > start; j--) {
+// for (int x = 0; x < countOfColor; x++) {
+// res += j;
+// inventory[i]--;
+// orders--;
+// if (orders == 0) {
+// return res;
+// }
+// }
+// }
+// countOfColor++;
+// }
+//
+// // 最后变为 x x x x (x为最小值)
+//
+//
+// for (int j = 0; j < inventory[0]; j++) {
+// int item = inventory[0];
+// if (orders < inventory.length) {
+// return res + orders * item;
+// }else {
+// for (int i = 0; i < item; i++) {
+// res += inventory[0];
+// orders--;
+// if (orders == 0) {
+// return res;
+// }
+// }
+// }
+// }
+//
+// return res;
+//
+//
+// // 5 2 2 1 2 1
+//
+//
+//// int res = 0;
+//// int add = 1;
+////
+//// int right = inventory.length - 1;
+//// for (int i = 0; i < orders; i++) {
+//// int left = right - 1;
+////
+//// int leftV = inventory[left];
+//// int rightV = inventory[right];
+//// for (int j = rightV; j > leftV; j--) {
+////
+//// }
+//// right--;
+//// }
+//// return res;
+//
+// }
+// }
+
+}
diff --git a/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode210_207.java b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode210_207.java
new file mode 100644
index 0000000..c840651
--- /dev/null
+++ b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode210_207.java
@@ -0,0 +1,118 @@
+package cn.whaifree.redo.redo_all_241016;
+
+import org.junit.Test;
+
+import java.util.*;
+
+/**
+ * @version 1.0
+ * @Author whai文海
+ * @Date 2024/11/15 9:56
+ * @注释
+ */
+public class LeetCode210_207 {
+
+ @Test
+ public void test() {
+ int numCourses = 2;
+ int[][] prerequisites = {};
+ Solution solution = new Solution();
+ int[] ints = solution.findOrder(numCourses, prerequisites);
+ System.out.println(Arrays.toString(ints));
+ }
+
+ class Solution {
+ public int[] findOrder(int numCourses, int[][] prerequisites) {
+ // prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi
+
+ Map> map = new HashMap<>();
+ int[] in = new int[numCourses];
+
+ for (int i = 0; i < numCourses; i++) {
+ map.put(i, new ArrayList<>());
+ }
+
+ for (int[] prerequisite : prerequisites) {
+ in[prerequisite[0]]++;
+ map.get(prerequisite[1]).add(prerequisite[0]);
+ }
+
+ Deque deque = new ArrayDeque<>();
+ // 入度炜0的
+ for (int i = 0; i < in.length; i++) {
+ if (in[i] == 0) {
+ deque.push(i);
+ }
+ }
+
+ int[] res = new int[numCourses];
+ int index = 0;
+ while (!deque.isEmpty()) {
+ // 入度为0
+ Integer pop = deque.pop();
+ res[index++] = pop;
+
+ List into = map.get(pop);
+ for (Integer i : into) {
+ in[i]--;
+ if (in[i] == 0) {
+ deque.add(i);
+ }
+ }
+ }
+
+ if (index != numCourses) {
+ return new int[0];
+ }
+ return res;
+ }
+ }
+
+ class Solution1 {
+ public boolean canFinish(int numCourses, int[][] prerequisites) {
+ // prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi
+
+ Map> map = new HashMap<>();
+ int[] in = new int[numCourses];
+
+ for (int i = 0; i < numCourses; i++) {
+ map.put(i, new ArrayList<>());
+ }
+
+ for (int[] prerequisite : prerequisites) {
+ in[prerequisite[0]]++;
+ map.get(prerequisite[1]).add(prerequisite[0]);
+ }
+
+ Deque deque = new ArrayDeque<>();
+ // 入度炜0的
+ for (int i = 0; i < in.length; i++) {
+ if (in[i] == 0) {
+ deque.push(i);
+ }
+ }
+
+ int[] res = new int[numCourses];
+ int index = 0;
+ while (!deque.isEmpty()) {
+ // 入度为0
+ Integer pop = deque.pop();
+ res[index++] = pop;
+
+ List into = map.get(pop);
+ for (Integer i : into) {
+ in[i]--;
+ if (in[i] == 0) {
+ deque.add(i);
+ }
+ }
+ }
+
+ if (index != numCourses) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+}
diff --git a/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode2602.java b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode2602.java
new file mode 100644
index 0000000..b897c27
--- /dev/null
+++ b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode2602.java
@@ -0,0 +1,59 @@
+package cn.whaifree.redo.redo_all_241016;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @version 1.0
+ * @Author whai文海
+ * @Date 2024/11/16 17:01
+ * @注释
+ */
+public class LeetCode2602 {
+
+ @Test
+ public void test() {
+ int[] nums = {3,1,6,8};
+ int[] queries = {1,5};
+ Solution solution = new Solution();
+ System.out.println(solution.minOperations(nums, queries));
+ }
+
+ class Solution {
+ public List minOperations(int[] nums, int[] queries) {
+ // 1 3 6 8
+ // 1 4 10 18
+ Arrays.sort(nums);
+ // 前缀和
+ long[] preSum = new long[nums.length + 1];
+ for (int i = 1; i <= nums.length; i++) {
+ preSum[i] = preSum[i - 1] + nums[i - 1];
+ }
+ List list = new ArrayList<>();
+ for (int i = 0; i < queries.length; i++) {
+ long l = minOpr(preSum, nums, queries[i]);
+ list.add(l);
+ }
+ return list;
+ }
+
+
+ public long minOpr(long[] preSum, int[] nums, int queries) {
+ int index = Arrays.binarySearch(nums, queries);
+ if (index < 0) {
+ index = -index - 1;
+ }
+
+ // 前面的次数
+ long preSize = preSum[index];
+ long before = (long) index * queries - preSize;
+ long afterSize = preSum[nums.length] - preSize;
+ long after = afterSize - (long) (nums.length - index) * queries;
+
+ return (before + after);
+ }
+ }
+}
diff --git a/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode469_1.java b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode469_1.java
new file mode 100644
index 0000000..962175a
--- /dev/null
+++ b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode469_1.java
@@ -0,0 +1,68 @@
+package cn.whaifree.redo.redo_all_241016;
+
+import org.junit.Test;
+
+/**
+ * @version 1.0
+ * @Author whai文海
+ * @Date 2024/11/14 17:17
+ * @注释
+ */
+public class LeetCode469_1 {
+
+ @Test
+ public void test() {
+ String s = "2001:0db8:85a3:0:0:8A2E:0370:7334";
+ System.out.println(new Solution().validIPAddress(s));
+ }
+
+ class Solution {
+ public String validIPAddress(String queryIP) {
+ if (queryIP.contains(":") && isIpv6(queryIP.split(":", -1))) {
+ return "IPv6";
+ } else if (queryIP.contains(".") && isIpv4(queryIP.split("\\.", -1))) {
+ return "IPv4";
+ }
+ return "Neither";
+ }
+
+ public boolean isIpv6(String[] ips) {
+ if (ips.length != 8) {
+ return false;
+ }
+ try {
+ for (String ip : ips) {
+ if (ip.isEmpty() || ip.length() > 4) {
+ return false;
+ }
+ int i = Integer.parseInt(ip, 16);
+ }
+ }catch (Exception e){
+ return false;
+ }
+ return true;
+ }
+
+ public boolean isIpv4(String[] ip) {
+ if (ip.length != 4) {
+ return false;
+ }
+ for (int i = 0; i < ip.length; i++) {
+ String s = ip[i];
+ try {
+ if (s.length() > 1 && s.startsWith("0")) {
+ return false;
+ }
+ Integer num = Integer.valueOf(s);
+ if (num < 0 || num > 255) {
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+ }
+}
diff --git a/ForJdk17/src/main/java/cn/whaifree/tech/GRRXReference.java b/ForJdk17/src/main/java/cn/whaifree/tech/GRRXReference.java
new file mode 100644
index 0000000..6bbfcbc
--- /dev/null
+++ b/ForJdk17/src/main/java/cn/whaifree/tech/GRRXReference.java
@@ -0,0 +1,103 @@
+package cn.whaifree.tech;
+
+import org.junit.Test;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+
+/**
+ * @version 1.0
+ * @Author whai文海
+ * @Date 2024/11/15 21:22
+ * @注释
+ */
+public class GRRXReference {
+
+ @Test
+ public void soft() {
+ Object obj = new Object();
+ SoftReference