test(activiti): 添加 Activiti 7 流程引擎测试用例

- 新增流程部署、查询、实例初始化和任务管理等测试方法
- 添加历史记录查询功能
- 更新 NIO 服务器示例代码
- 新增枚举类型和自定义类型处理器- 调整 Spring Cloud服务配置
- 添加新的 BPMN 文件

Changes
Activiti7DemoApplicationTests.java
AioServer.java
AmountBig.java
AmountTypeHandler.java
application.yaml
application.yaml
asdf.bpmn20.xml
ASPIServiceImpl.java
bootstrap.yml
BProviderController.java
BService.java
BSPIServiceImpl.java
cn.whaifree.tech.SPI.SPIService
ConfigController.java
FanxinTest.java
FunctionInterfaceDemo.java
GRRXReference.java
leave.bpmn
leave.png
leave1.bpmn20.xml
LeetCode210_207.java
LeetCode469_1.java
LeetCode1648.java
LeetCode2602.java
P1.java
P1.java
pom.xml
pom.xml
pom.xml
RestConfig.java
sadasf.bpmn20.xml
ScheduledThreadPoolTest.java
ServiceBApplication.java
SPIService.java
TestController.java
ThreadDemo1.java
TransactionConfig.java
workflow.md
Unversioned Files
C:\Users\wenhai\project\javaProject\LeetCode\SpringCloud\GateWay\src\main\resources\application.properties
C:\Users\wenhai\project\javaProject\LeetCode\SpringCloud\GateWay\src\main\java\com\whai\springcloud\gateway\GateWayApplication.java
C:\Users\wenhai\project\javaProject\LeetCode\SpringCloud\GateWay\src\test\java\com\whai\springcloud\gateway\GateWayApplicationTests.java
C:\Users\wenhai\project\javaProject\LeetCode\SpringCloud\GateWay\pom.xml
This commit is contained in:
whai 2024-11-16 20:43:40 +08:00
parent ea493390a6
commit 93ae3a0720
42 changed files with 1807 additions and 73 deletions

View File

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
<!-- 流程定义 -->
<process id="parallelApprovalProcess" name="Parallel Approval Process" isExecutable="true">
<!-- 开始事件 -->
<startEvent id="startEvent" name="Start"/>
<!-- 并行网关(分支) -->
<parallelGateway id="forkGateway" />
<!-- 财务审批任务 -->
<userTask id="financialApproval" name="Financial Approval" flowable:assignee="financeUser" />
<!-- 人力资源审批任务 -->
<userTask id="hrApproval" name="HR Approval" flowable:assignee="hrUser" />
<!-- 技术审批任务 -->
<userTask id="techApproval" name="Tech Approval" flowable:assignee="techUser" />
<!-- 并行网关(汇合) -->
<parallelGateway id="joinGateway" />
<!-- 结束事件 -->
<endEvent id="endEvent" name="End"/>
<!-- 连线 -->
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="forkGateway"/>
<sequenceFlow id="flow2" sourceRef="forkGateway" targetRef="financialApproval"/>
<sequenceFlow id="flow3" sourceRef="forkGateway" targetRef="hrApproval"/>
<sequenceFlow id="flow4" sourceRef="forkGateway" targetRef="techApproval"/>
<sequenceFlow id="flow5" sourceRef="financialApproval" targetRef="joinGateway"/>
<sequenceFlow id="flow6" sourceRef="hrApproval" targetRef="joinGateway"/>
<sequenceFlow id="flow7" sourceRef="techApproval" targetRef="joinGateway"/>
<sequenceFlow id="flow8" sourceRef="joinGateway" targetRef="endEvent"/>
</process>
<!-- 图形表示部分 -->
<bpmndi:BPMNDiagram id="BPMNDiagram_parallelApprovalProcess">
<bpmndi:BPMNPlane id="BPMNPlane_parallelApprovalProcess" bpmnElement="parallelApprovalProcess">
<!-- 开始事件图形 -->
<bpmndi:BPMNShape id="startEventShape" bpmnElement="startEvent">
<omgdc:Bounds x="100" y="100" width="36" height="36"/>
</bpmndi:BPMNShape>
<!-- 并行网关(分支)图形 -->
<bpmndi:BPMNShape id="forkGatewayShape" bpmnElement="forkGateway">
<omgdc:Bounds x="200" y="100" width="50" height="50"/>
</bpmndi:BPMNShape>
<!-- 财务审批任务图形 -->
<bpmndi:BPMNShape id="financialApprovalShape" bpmnElement="financialApproval">
<omgdc:Bounds x="300" y="40" width="80" height="100"/>
</bpmndi:BPMNShape>
<!-- 人力资源审批任务图形 -->
<bpmndi:BPMNShape id="hrApprovalShape" bpmnElement="hrApproval">
<omgdc:Bounds x="300" y="150" width="80" height="100"/>
</bpmndi:BPMNShape>
<!-- 技术审批任务图形 -->
<bpmndi:BPMNShape id="techApprovalShape" bpmnElement="techApproval">
<omgdc:Bounds x="300" y="260" width="80" height="100"/>
</bpmndi:BPMNShape>
<!-- 并行网关(汇合)图形 -->
<bpmndi:BPMNShape id="joinGatewayShape" bpmnElement="joinGateway">
<omgdc:Bounds x="420" y="150" width="50" height="50"/>
</bpmndi:BPMNShape>
<!-- 结束事件图形 -->
<bpmndi:BPMNShape id="endEventShape" bpmnElement="endEvent">
<omgdc:Bounds x="550" y="160" width="36" height="36"/>
</bpmndi:BPMNShape>
<!-- 连线图形 -->
<bpmndi:BPMNEdge id="flow1Edge" bpmnElement="flow1">
<omgdi:waypoint x="136" y="118"/>
<omgdi:waypoint x="200" y="125"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="flow2Edge" bpmnElement="flow2">
<omgdi:waypoint x="250" y="125"/>
<omgdi:waypoint x="300" y="90"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="flow3Edge" bpmnElement="flow3">
<omgdi:waypoint x="250" y="125"/>
<omgdi:waypoint x="300" y="200"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="flow4Edge" bpmnElement="flow4">
<omgdi:waypoint x="250" y="125"/>
<omgdi:waypoint x="300" y="310"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="flow5Edge" bpmnElement="flow5">
<omgdi:waypoint x="380" y="90"/>
<omgdi:waypoint x="420" y="175"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="flow6Edge" bpmnElement="flow6">
<omgdi:waypoint x="380" y="200"/>
<omgdi:waypoint x="420" y="175"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="flow7Edge" bpmnElement="flow7">
<omgdi:waypoint x="380" y="310"/>
<omgdi:waypoint x="420" y="175"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="flow8Edge" bpmnElement="flow8">
<omgdi:waypoint x="470" y="175"/>
<omgdi:waypoint x="550" y="178"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
<process id="Part1_Deployment" name="Part1_Deployment" isExecutable="true">
<startEvent id="sid-26d6e725-878e-411d-b23d-6df4ae3cbd24"/>
<endEvent id="sid-03d64ced-963c-4506-a5b3-21b8a9dc4279"/>
<sequenceFlow id="sid-560ce1e7-a0f9-4a99-8a64-d2920292cd37" sourceRef="sid-26d6e725-878e-411d-b23d-6df4ae3cbd24" targetRef="sid-86ada704-a4d8-4a01-bddc-b2cd677f091d"/>
<sequenceFlow id="sid-da2d1cc1-7544-40f6-81ab-1d0c32c0064a" sourceRef="sid-8af65ca8-f037-4716-95c5-373eda92d456" targetRef="sid-03d64ced-963c-4506-a5b3-21b8a9dc4279"/>
<parallelGateway id="sid-8af65ca8-f037-4716-95c5-373eda92d456"/>
<userTask id="sid-86ada704-a4d8-4a01-bddc-b2cd677f091d"/>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_Part1_Deployment">
<bpmndi:BPMNPlane bpmnElement="Part1_Deployment" id="BPMNPlane_Part1_Deployment">
<bpmndi:BPMNShape id="shape-6b3bc939-03fe-47d7-b1fb-44a959045633" bpmnElement="sid-26d6e725-878e-411d-b23d-6df4ae3cbd24">
<omgdc:Bounds x="-20.0" y="-85.0" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-8137d303-1a5b-4a34-b8d7-995a29ae534a" bpmnElement="sid-03d64ced-963c-4506-a5b3-21b8a9dc4279">
<omgdc:Bounds x="-20.0" y="105.00001" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-05926a76-90de-4b3f-8fd5-d27d06dd6d6e" bpmnElement="sid-560ce1e7-a0f9-4a99-8a64-d2920292cd37">
<omgdi:waypoint x="-5.0" y="-55.0"/>
<omgdi:waypoint x="-95.0" y="-35.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="edge-6b52ec5d-0f90-4972-a304-022f03ccf3cf" bpmnElement="sid-da2d1cc1-7544-40f6-81ab-1d0c32c0064a">
<omgdi:waypoint x="-5.0" y="45.0"/>
<omgdi:waypoint x="-5.0" y="105.00001"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="shape-d7a9725f-5a80-4154-a46e-229cbb12a853" bpmnElement="sid-8af65ca8-f037-4716-95c5-373eda92d456">
<omgdc:Bounds x="-25.0" y="4.999999" width="40.0" height="40.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-03887bc6-8b53-480f-bd78-662dc1005441" bpmnElement="sid-86ada704-a4d8-4a01-bddc-b2cd677f091d">
<omgdc:Bounds x="-195.0" y="-55.0" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:flowable="http://flowable.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="http://www.flowable.org/processdef">
</definitions>

View File

@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
id="Definitions_1"
targetNamespace="http://bpmn.io/schema/bpmn"
exporter="bpmn-js (https://bpmn.io)"
exporterVersion="10.3.0">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:userTask id="UserTask_1" name="任务">
<bpmn:incoming>SequenceFlow_1</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_2</bpmn:outgoing>
</bpmn:userTask>
<bpmn:endEvent id="EndEvent_1">
<bpmn:incoming>SequenceFlow_2</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SequenceFlow_1" sourceRef="StartEvent_1" targetRef="UserTask_1" />
<bpmn:sequenceFlow id="SequenceFlow_2" sourceRef="UserTask_1" targetRef="EndEvent_1" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
<dc:Bounds x="173" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="UserTask_1_di" bpmnElement="UserTask_1">
<dc:Bounds x="263" y="90" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_1_di" bpmnElement="EndEvent_1">
<dc:Bounds x="423" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1_di" bpmnElement="SequenceFlow_1">
<di:waypoint x="209" y="120" />
<di:waypoint x="263" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_2_di" bpmnElement="SequenceFlow_2">
<di:waypoint x="363" y="120" />
<di:waypoint x="423" y="120" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -1,24 +1,285 @@
package cn.whai.activiti.activiti7demo; package cn.whai.activiti.activiti7demo;
import org.activiti.engine.ProcessEngine; import org.activiti.engine.*;
import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.RepositoryService; 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.activiti.spring.SpringProcessEngineConfiguration;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest @SpringBootTest
class Activiti7DemoApplicationTests { class Activiti7DemoApplicationTests {
@Autowired
private RepositoryService repositoryService;
@Test @Test
void contextLoads() { 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<ProcessDefinition> 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<String, Object> 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]]
* 流程实例IDb25a64f9-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]]
* ProcessInstanceIdb25a64f9-a0c3-11ef-8ba8-68c6acfdcef0
* ProcessDefinitionIdPart1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec
* isEndedfalse
* isSuspendedfalse
*/
// 查询流程实例列表
List<ProcessInstance> 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<Task> 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<Task> 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<String, Object> 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<HistoricProcessInstance> 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<HistoricProcessInstance> historicProcessInstances =
this.historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.list();
historicProcessInstances.forEach(historicProcessInstance -> {
System.out.println("ProcessInstanceId" + historicProcessInstance.getId());
System.out.println("ProcessDefinitionId" + historicProcessInstance.getProcessDefinitionId());
});
}
} }

View File

@ -55,3 +55,225 @@ BPMNBusiness Process Model And Notation业务流程模型和符号
- mysql - mysql
- 在Navicat工具中创建`activiti`的数据库,用于后续的实验. - 在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<ProcessDefinition> 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<String, Object> 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]]
* 流程实例IDb25a64f9-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]]
* ProcessInstanceIdb25a64f9-a0c3-11ef-8ba8-68c6acfdcef0
* ProcessDefinitionIdPart1_Deployment:1:0c957bc0-a0c1-11ef-9820-6ac6acfdceec
* isEndedfalse
* isSuspendedfalse
*/
// 查询流程实例列表
List<ProcessInstance> 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)
##

View File

@ -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<String> lines, Set<String> physical, Map<String, List<String>> bonds, Map<String, String> 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<String> 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<String> currentLines, List<String> targetLines) {
// Parsing current and target configurations
Set<String> currentPhysical = new HashSet<>();
Map<String, List<String>> currentBonds = new HashMap<>();
Map<String, String> currentVlans = new HashMap<>();
parseConfig(currentLines, currentPhysical, currentBonds, currentVlans);
Set<String> targetPhysical = new HashSet<>();
Map<String, List<String>> targetBonds = new HashMap<>();
Map<String, String> 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<String, List<String>> entry : targetBonds.entrySet()) {
String bond = entry.getKey();
List<String> 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<String, String> 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<String> currentLines = new ArrayList<>();
for (int i = 0; i < n; i++) {
currentLines.add(scanner.nextLine().trim());
}
int m = Integer.parseInt(scanner.nextLine());
List<String> 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();
}
}

View File

@ -60,6 +60,8 @@ class p2{
* 代码中的类名方法名参数名已经指定请勿修改直接返回方法规定的值即可 * 代码中的类名方法名参数名已经指定请勿修改直接返回方法规定的值即可
* *
* *
* 给你一个数组你可以随意操作任意相邻的元素都+1请问需要多少次可以让整个数组变成对称的
*
* @param arr int整型一维数组 * @param arr int整型一维数组
* @return long长整型 * @return long长整型
*/ */
@ -80,4 +82,44 @@ class p2{
int i = dp[0][n - 1]; int i = dp[0][n - 1];
return i; 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
}
}
} }

View File

@ -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;
//
// }
// }
}

View File

@ -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<Integer, List<Integer>> 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<Integer> 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<Integer> 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<Integer, List<Integer>> 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<Integer> 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<Integer> into = map.get(pop);
for (Integer i : into) {
in[i]--;
if (in[i] == 0) {
deque.add(i);
}
}
}
if (index != numCourses) {
return false;
}
return true;
}
}
}

View File

@ -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<Long> 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<Long> 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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<Object> softRef = new SoftReference<>(obj); // 创建软引用
// 手动触发垃圾回收
System.gc();
// 尝试获取软引用指向的对象
Object retrievedObject = softRef.get();
if (retrievedObject != null) {
System.out.println("对象还在内存中: " + retrievedObject);
} else {
System.out.println("对象已经被垃圾回收");
}
// 使 obj 可被回收
obj = null;
// 再次尝试获取软引用指向的对象
System.gc(); // 强烈建议调用 GC 来验证软引用回收
retrievedObject = softRef.get();
if (retrievedObject != null) {
System.out.println("对象还在内存中: " + retrievedObject);
} else {
System.out.println("对象已经被垃圾回收");
}
}
@Test
public void weak() {
Object obj = new Object();
WeakReference<Object> weakRef = new WeakReference<>(obj); // 创建弱引用
// 手动触发垃圾回收
System.gc();
// 尝试获取软引用指向的对象
Object retrievedObject = weakRef.get();
if (retrievedObject != null) {
System.out.println("对象还在内存中: " + retrievedObject);
} else {
System.out.println("对象已经被垃圾回收");
}
// 使 obj 可被回收
obj = null;
// 再次尝试获取软引用指向的对象
System.gc(); // 强烈建议调用 GC 来验证软引用回收
retrievedObject = weakRef.get();
if (retrievedObject != null) {
System.out.println("对象还在内存中: " + retrievedObject);
} else {
System.out.println("对象已经被垃圾回收");
}
}
@Test
public void phantom() {
// 创建一个引用队列
ReferenceQueue<Object> queue = new ReferenceQueue<>();
// 创建一个对象和它的虚引用
Object obj = new Object();
PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);
System.out.println("虚引用创建完毕obj 是:" + phantomRef.get());
// 使 obj 可被回收
obj = null;
// 手动触发垃圾回收
System.gc();
// 检查引用队列中是否有虚引用指向的对象
try {
// 只有在对象被回收后才会从引用队列中取得虚引用
PhantomReference<?> refFromQueue = (PhantomReference<?>) queue.remove();
System.out.println("虚引用指向的对象已经被回收:" + refFromQueue);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,14 @@
package cn.whaifree.tech.SPI;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/15 21:31
* @注释
*/
public class ASPIServiceImpl implements SPIService {
@Override
public void sayHello() {
System.out.println("Hello, I am ASPIServiceImpl");
}
}

View File

@ -0,0 +1,14 @@
package cn.whaifree.tech.SPI;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/15 21:31
* @注释
*/
public class BSPIServiceImpl implements SPIService {
@Override
public void sayHello() {
System.out.println("BSPIServiceImpl sayHello");
}
}

View File

@ -0,0 +1,28 @@
package cn.whaifree.tech.SPI;
import java.security.Provider;
import java.util.Iterator;
import java.util.ServiceLoader;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/15 21:31
* @注释
*/
public interface SPIService {
void sayHello();
static void main(String[] args) {
ServiceLoader<SPIService> load = ServiceLoader.load(SPIService.class);
Iterator<SPIService> iterator = load.iterator();
while (iterator.hasNext()) {
SPIService next = iterator.next();
next.sayHello();
}
}
}

View File

@ -1,6 +1,7 @@
package cn.whaifree.test; package cn.whaifree.test;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -18,6 +19,14 @@ public class FanxinTest {
new LinkedBlockingQueue<>() new LinkedBlockingQueue<>()
); );
// 异步
threadPoolExecutor.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
return null;
}
});
} }

View File

@ -53,6 +53,7 @@ public class ThreadDemo1 {
public static void main(String[] args) throws InterruptedException { public static void main(String[] args) throws InterruptedException {
AtomicInteger num = new AtomicInteger(9); AtomicInteger num = new AtomicInteger(9);
num.decrementAndGet();
CountDownLatch countDownLatch = new CountDownLatch(num.get()); CountDownLatch countDownLatch = new CountDownLatch(num.get());
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {

View File

@ -142,6 +142,9 @@ class BioServer {
class NioServer { class NioServer {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
// 打开一个选择器 // 打开一个选择器
Selector selector = Selector.open(); Selector selector = Selector.open();
// 打开一个服务器套接字通道 // 打开一个服务器套接字通道

View File

@ -14,6 +14,24 @@ import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolTest { public class ScheduledThreadPoolTest {
volatile static Integer i = 0; volatile static Integer i = 0;
/**
* 提交任务时消费任务的时候检查 ScheduledFutureTask 时间
*
* 任务提交当用户提交一个定时任务时ScheduledThreadPool 会将任务封装成 ScheduledFutureTask 对象并将其放入延迟队列中
*
* 任务调度线程池中的线程会从延迟队列中取出任务并执行如果任务设置了延迟执行时间线程会等待相应的时间后再执行任务
*
* 任务执行线程执行任务时会调用 ScheduledFutureTask run 方法run 方法会首先检查任务的取消状态如果任务被取消则直接返回否则会执行任务的 run 方法
*
* 周期性任务对于周期性任务ScheduledFutureTask 会根据任务的执行周期重新计算下一次执行的时间并将其重新放入延迟队列中这样周期性任务会按照指定的周期重复执行
*
* 异常处理如果任务在执行过程中抛出异常ScheduledFutureTask 会捕获这个异常并调用 setException 方法将异常设置到 Future 对象中
*
* 任务完成当任务执行完成后ScheduledFutureTask 会从延迟队列中移除并更新 Future 对象的状态
*
* 线程回收ScheduledThreadPool 中的线程会根据任务的执行情况进行回收如果线程池中的线程在一段时间内没有任务可执行它们会被回收以减少资源消耗
* @param args
*/
public static void main(String[] args) { public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);

View File

@ -0,0 +1,2 @@
cn.whaifree.tech.SPI.ASPIServiceImpl
cn.whaifree.tech.SPI.BSPIServiceImpl

View File

@ -17,7 +17,9 @@ public class FunctionInterfaceDemo {
public static void main(String[] args) throws InterruptedException { public static void main(String[] args) throws InterruptedException {
HashMap<Object, Object> map = new HashMap<>(); ConcurrentHashMap<Object, Object> map = new ConcurrentHashMap<>();
map.put(null, null);
// HashMap<Object, Object> map = new HashMap<>();
// map.put(null, null); // map.put(null, null);
System.out.println(map.get(null)); System.out.println(map.get(null));

171
SpringCloud/GateWay/pom.xml Normal file
View File

@ -0,0 +1,171 @@
<?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>3.3.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.whai.springcloud</groupId>
<artifactId>GateWay</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>GateWay</name>
<description>GateWay</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
<swagger.fox.version>3.0.0</swagger.fox.version>
</properties>
<dependencies>
<!-- SpringCloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel Gateway -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!-- Sentinel Datasource Nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- Sentinel 实时监控 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- SpringCloud Loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!--验证码 -->
<dependency>
<groupId>pro.fessional</groupId>
<artifactId>kaptcha</artifactId>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<!-- 为防止打包docker部署读取不到配置文件问题资源文件 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>

View File

@ -0,0 +1,13 @@
package com.whai.springcloud.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GateWayApplication {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication.class, args);
}
}

View File

@ -0,0 +1 @@
spring.application.name=GateWay

View File

@ -0,0 +1,48 @@
# Tomcat
server:
port: 6880
# Spring
spring:
application:
# 应用名称
name: whai-gateway
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 192.168.50.248:8848
username: nacos
password: nacos
config:
# 配置中心地址
server-addr: 192.168.50.248:8848
username: nacos
password: nacos
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# sentinel:
# # 取消控制台懒加载
# eager: true
# transport:
# # 配置控制台服务地址
# dashboard: 127.0.0.1:8080
# # 默认 8719 端口,假如被占用会自动从 8719 开始依次 +1 扫描,直至找到未被占用的端口
# port: 8719
# # nacos配置持久化
# datasource:
# ds1:
# nacos:
# server-addr: 127.0.0.1:8848
# dataId: sentinel-pmhub-gateway
# groupId: DEFAULT_GROUP
# data-type: json
# rule-type: gw-flow
# 实时log配置可在http://localhost:6888/ 监控中心查看实时日志
logging:
file:
name: logs/${spring.application.name}/info.log

View File

@ -0,0 +1,13 @@
package com.whai.springcloud.gateway;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class GateWayApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -30,6 +30,7 @@
<java.version>17</java.version> <java.version>17</java.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <artifactId>spring-boot-starter</artifactId>

View File

@ -16,7 +16,7 @@ import org.springframework.web.client.RestTemplate;
public class RestConfig { public class RestConfig {
@Bean @Bean
@LoadBalanced @LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { public RestTemplate restTemplate() {
return restTemplateBuilder.build(); return new RestTemplateBuilder().build();
} }
} }

View File

@ -18,6 +18,4 @@ public interface BService {
@GetMapping("/getB") @GetMapping("/getB")
String getB(@RequestParam("msg") String msg); String getB(@RequestParam("msg") String msg);
} }

View File

@ -1,5 +1,6 @@
server: server:
port: 12120 port: 12123
spring: spring:
application: application:
name: ServiceA name: ServiceA
@ -8,12 +9,12 @@ spring:
username: nacos username: nacos
password: nacos password: nacos
discovery: discovery:
namespace: 97ff159f-6177-4aab-b735-bd75458949d4 namespace: public
group: DEFAULT_GROUP group: DEFAULT_GROUP
server-addr: localhost:8848 server-addr: 192.168.50.248:8848
config: config:
# 配置所属命名空间的id我们配置名称为dev的id在命名空间列表查看id的值 # 配置所属命名空间的id我们配置名称为dev的id在命名空间列表查看id的值
namespace: 97ff159f-6177-4aab-b735-bd75458949d4 namespace: public
# 文件名,如果没有配置则默认为 ${spring.application.name} # 文件名,如果没有配置则默认为 ${spring.application.name}
# prefix: springboot3-nacos # prefix: springboot3-nacos
# 配置所属分组 # 配置所属分组
@ -21,7 +22,7 @@ spring:
# 后缀名,只支持 properties 和 yaml 类型 # 后缀名,只支持 properties 和 yaml 类型
file-extension: yaml file-extension: yaml
# nacos服务器地址 # nacos服务器地址
server-addr: localhost:8848 server-addr: ${spring.cloud.nacos.discovery.server-addr}
# 配置自动刷新 # 配置自动刷新
refresh-enabled: true refresh-enabled: true
config: config:
@ -33,5 +34,3 @@ logging:
level: level:
com.hexadecimal: debug com.hexadecimal: debug
hexadecimal:
name: whai

View File

@ -30,6 +30,8 @@
<java.version>17</java.version> <java.version>17</java.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <artifactId>spring-boot-starter</artifactId>

View File

@ -5,7 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication @SpringBootApplication(scanBasePackages = {"com.whai.springcloud.serviceb"})
@EnableDiscoveryClient @EnableDiscoveryClient
@EnableFeignClients @EnableFeignClients
public class ServiceBApplication { public class ServiceBApplication {

View File

@ -57,7 +57,7 @@ public class BProviderController {
} }
} }
@Value("${cvm.reset.ratelimit}") @Value("${cvm.reset.ratelimit:0}")
private int rateLimitCount; private int rateLimitCount;
private void initRateLimiter() { private void initRateLimiter() {
if (rateLimitCount <= 0) { if (rateLimitCount <= 0) {
@ -72,6 +72,11 @@ public class BProviderController {
return StrUtil.format("BProviderController.getB, msg: {}, port: {}", msg, environment.getProperty("server.port")); return StrUtil.format("BProviderController.getB, msg: {}, port: {}", msg, environment.getProperty("server.port"));
} }
@RequestMapping("/getProper")
public int getProper() {
return environment.getProperty("cvm.reset.ratelimit", Integer.class);
}
@PostMapping("/CVM/reset") @PostMapping("/CVM/reset")

View File

@ -0,0 +1,27 @@
package com.whai.springcloud.serviceb.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/16 14:24
* @注释
*/
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/get")
public boolean get() {
return useLocalCache;
}
}

View File

@ -1,4 +1,6 @@
server:
port: 12121
spring: spring:
application: application:
name: ServiceB name: ServiceB
@ -7,12 +9,12 @@ spring:
username: nacos username: nacos
password: nacos password: nacos
discovery: discovery:
namespace: 97ff159f-6177-4aab-b735-bd75458949d4 namespace: public
group: DEFAULT_GROUP group: DEFAULT_GROUP
server-addr: localhost:8848 server-addr: 192.168.50.248:8848
config: config:
# 配置所属命名空间的id我们配置名称为dev的id在命名空间列表查看id的值 # 配置所属命名空间的id我们配置名称为dev的id在命名空间列表查看id的值
namespace: 97ff159f-6177-4aab-b735-bd75458949d4 namespace: public
# 文件名,如果没有配置则默认为 ${spring.application.name} # 文件名,如果没有配置则默认为 ${spring.application.name}
# prefix: springboot3-nacos # prefix: springboot3-nacos
# 配置所属分组 # 配置所属分组
@ -20,7 +22,7 @@ spring:
# 后缀名,只支持 properties 和 yaml 类型 # 后缀名,只支持 properties 和 yaml 类型
file-extension: yaml file-extension: yaml
# nacos服务器地址 # nacos服务器地址
server-addr: localhost:8848 server-addr: ${spring.cloud.nacos.discovery.server-addr}
# 配置自动刷新 # 配置自动刷新
refresh-enabled: true refresh-enabled: true
config: config:
@ -32,5 +34,3 @@ logging:
level: level:
com.hexadecimal: debug com.hexadecimal: debug
hexadecimal:
name: whai

View File

@ -32,6 +32,9 @@
<spring-cloud.version>2023.0.3</spring-cloud.version> <spring-cloud.version>2023.0.3</spring-cloud.version>
</properties> </properties>
<dependencies> <dependencies>
<!-- Lombok --> <!-- Lombok -->
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>

View File

@ -0,0 +1,97 @@
package cn.whaifree.springdemo.config;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import javax.sql.DataSource;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/15 16:37
* @注释
*/
@Configuration
@Slf4j
public class TransactionConfig implements TransactionManagementConfigurer {
@Autowired
private TransactionTemplate transactionTemplate;
//配置事务管理器
@Bean
public TransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
// 打印参数
log.info("transactionManager: {}", transactionManager);
log.info("dataSource: {}", dataSource);
return transactionManager;
}
@Resource(name="txManager1")
private PlatformTransactionManager txManager1;
// 创建事务管理器1
@Bean(name = "txManager1")
public PlatformTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Override
public TransactionManager annotationDrivenTransactionManager() {
return txManager1;
}
@Transactional(value="txManager1")
public void addUser() {
}
public void addUser2() {
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
TransactionStatus transaction = txManager1.getTransaction(transactionDefinition);
try {
txManager1.commit(transaction);
} catch (Exception e) {
txManager1.rollback(transaction);
}
}
/**
* 编程事务
* TransactionTemplate
* PlatformTransactionManager
* DataSourceTransactionManager
*/
public void adduser3() {
Object execute = transactionTemplate.execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
return null;
}
});
}
}
class Tran{
}

View File

@ -64,7 +64,7 @@ public class TestController {
} }
@Override @Override
public Object call() throws Exception { public Object call(){
return null; return null;
} }

View File

@ -0,0 +1,52 @@
package cn.whaifree.springdemo.mybatis;
import cn.whaifree.springdemo.mybatis.domain.AmountBig;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/15 10:52
* @注释
*/
public class AmountTypeHandler extends BaseTypeHandler<AmountBig> {
/**
* 该方法用于将 AmountBig 枚举类型的值设置到 PreparedStatement
* @param ps
* @param i
* @param parameter
* @param jdbcType
* @throws SQLException
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, AmountBig parameter, JdbcType jdbcType) throws SQLException {
if (parameter.equals(AmountBig.BIG)) {
ps.setDouble(i, 1000000000D);
}else {
ps.setDouble(i, 0D);
}
}
@Override
public AmountBig getNullableResult(ResultSet rs, String columnName) throws SQLException {
double aDouble = rs.getDouble(columnName);
if (aDouble == 1000000000D) {
return AmountBig.BIG;
}
return AmountBig.SMALL;
}
@Override
public AmountBig getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return null;
}
@Override
public AmountBig getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return null;
}
}

View File

@ -0,0 +1,12 @@
package cn.whaifree.springdemo.mybatis.domain;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/15 10:50
* @注释
*/
public enum AmountBig {
BIG,
SMALL
}