JoyLau's Blog

JoyLau 的技术学习与思考

语法

XML 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<definitions xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="definitions_a563b995-6727-44a6-b7c9-613f54d9145c" targetNamespace="1" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">
<process id="process_SBJY" isExecutable="true" name="设备借用">
<documentation id="documentation_6f4c7594-bfd9-4b51-8477-a8165c33ca19">{"setting":{"name":"设备借用","categoryId":1,"desc":"","repeatType":0,"autoPass":true,"enableUndo":true,"enableTransfer":true,"enableAuth":true,"id":"process_SBJY:24:c5e034aa-253a-11ee-b160-1aa02d19e831"},"form":[{"title":"单行输入框","type":"单行输入框","name":"TextInput","icon":"icon-danhangwenben","value":"","valueType":"String","props":{"placeholder":"请输入","required":false,"mobileShow":false,"pcShow":true},"id":"field3251030156446","err":false},{"title":"视频","type":"视频","name":"VideoUpload","icon":"icon-shipin","value":[],"valueType":"Array","props":{"required":false,"hiddenMobileShow":true,"maxSize":200,"maxNumber":1,"enableZip":true},"id":"field5186540608388","isInTable":false,"err":false},{"title":"数字","type":"数字","name":"NumberInput","icon":"icon-shuzi","value":null,"valueType":"Number","props":{"placeholder":"请输入","required":true,"mobileShow":true,"pcShow":true},"id":"field2918600070275","isInTable":false,"err":false},{"title":"人员","type":"人员","name":"UserPicker","icon":"icon-renyuan","value":[],"valueType":"User","props":{"placeholder":"请选择人员","required":true,"mobileShow":true,"pcShow":true,"multiple":true},"id":"field2758549148097","isInTable":false,"err":false},{"title":"部门","type":"部门","name":"DeptPicker","icon":"icon-bumen","value":[],"valueType":"Dept","props":{"placeholder":"请选择部门","required":true,"mobileShow":false,"pcShow":true},"id":"field3836364467190","isInTable":false,"err":false}],"process":{"id":"root","parentId":null,"type":"ROOT","name":"发起人","desc":"任何人","props":{"assignedUser":[],"formPerms":[]},"children":{"id":"node_616935911517","parentId":"root","props":{"assignedType":["ASSIGN_USER"],"mode":"AND","sign":false,"nobody":{"handler":"TO_PASS","assignedUser":[]},"assignedUser":[{"id":"1585090515499008001","name":"蜀山分局","orgName":null,"type":2,"number":2,"photo":null},{"id":"1585090627415621634","name":"蜀山分局2","orgName":null,"type":2,"number":5,"photo":null},{"id":"1585109286318030850","name":"地方监狱-ch","orgName":null,"type":2,"number":3,"photo":null},{"id":"1602586682327564289","name":"11112342","orgName":null,"type":2,"number":3,"photo":null},{"id":"1635892057621479425","name":"狱政科","orgName":null,"type":2,"number":4,"photo":null},{"id":"1578658896143728642","name":"科室1","orgName":null,"type":2,"number":8,"photo":null},{"id":"1625451599632105474","name":"分分分","orgName":null,"type":2,"number":2,"photo":null},{"id":"1572024105919086593","name":"001","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1574934048770945026","name":"ch","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1579683243000184834","name":"90","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1580726129128992770","name":"186-超级管理员","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582182526693732354","name":"测试1","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582267287462277121","name":"李聪","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582268293298319361","name":"张爱婷","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582268293659029506","name":"李聪","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582268294598553601","name":"李聪婷","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582268295139618817","name":"张婷聪","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582268295470968833","name":"张婷","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582268295823290369","name":"张爱聪","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582268296012034050","name":"任婷","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582268296188194818","name":"张婷聪","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1582938632181313538","name":"李婷","orgName":"省局","type":1,"number":null,"photo":""}],"roleOrg":{"role":[],"roleOrgType":"","org":[]}},"type":"CC","name":"抄送人","children":{"id":"node_926398936983","parentId":"node_616935911517","props":{"assignedType":["ASSIGN_USER"],"mode":"NEXT","sign":false,"nobody":{"handler":"TO_EXCEPTIONAL","assignedUser":[]},"assignedUser":[{"id":"1580726129128992770","name":"186-超级管理员","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1659398930563702785","name":"刘法手机","orgName":"科室1","type":1,"number":null,"photo":"168673478113543988cbfefe15f74157569bb3107d652"},{"id":"1585094725347098626","name":"11111","orgName":null,"type":2,"number":0,"photo":null}],"roleOrg":{"role":[],"roleOrgType":"ALL","org":[]}},"type":"APPROVAL","name":"审批人","children":{"id":"node_839328175114","parentId":"node_926398936983","props":{"assignedType":["ASSIGN_USER"],"mode":"OR","sign":false,"nobody":{"handler":"TO_PASS","assignedUser":[]},"assignedUser":[{"id":"1580726129128992770","name":"186-超级管理员","orgName":"省局","type":1,"number":null,"photo":""},{"id":"1659398930563702785","name":"刘法手机","orgName":"科室1","type":1,"number":null,"photo":""},{"id":"1572769134128214018","name":"张柱11","orgName":"科室1","type":1,"number":null,"photo":"1684823575798a655866a187cf9c8d995b8dae79fb77a"},{"id":"1613445750961299458","name":"洪小霞","orgName":"科室1","type":1,"number":null,"photo":""}],"roleOrg":{"role":[],"roleOrgType":"","org":[]}},"type":"APPROVAL","name":"审批人","children":{}}}}}}</documentation>
<extensionElements>
<camunda:properties>
<camunda:property name="createBy" value="1580726129128992770"/>
<camunda:property name="createAt" value="2023-07-19T17:56:37.413"/>
</camunda:properties>
</extensionElements>
<startEvent id="root" name="发起人">
<documentation id="documentation_3c5043d1-e67d-45df-bfe3-89abc6b1f1ba">{"assignedUser":[],"formPerms":[]}</documentation>
<extensionElements>
<camunda:executionListener class="com.hfky.workflow.server.module.camunda.listener.start.StartEventStartListener" event="start"/>
<camunda:executionListener class="com.hfky.workflow.server.module.camunda.listener.start.StartEventEndListener" event="end"/>
</extensionElements>
<outgoing>sequenceFlow_76b564f1-d4ad-4d53-900e-947df8979783</outgoing>
</startEvent>
<sendTask camunda:class="com.hfky.workflow.server.module.camunda.delegate.CCTaskDelegate" id="node_616935911517" name="抄送人">
<documentation id="documentation_bf70d26d-f7fe-4547-b27b-142ab7c9b613">{"assignedType":["ASSIGN_USER"],"assignedUser":[{"id":"1585090515499008001","name":"蜀山分局","type":2},{"id":"1585090627415621634","name":"蜀山分局2","type":2},{"id":"1585109286318030850","name":"地方监狱-ch","type":2},{"id":"1602586682327564289","name":"11112342","type":2},{"id":"1635892057621479425","name":"狱政科","type":2},{"id":"1578658896143728642","name":"科室1","type":2},{"id":"1625451599632105474","name":"分分分","type":2},{"id":"1572024105919086593","name":"001","type":1},{"id":"1574934048770945026","name":"ch","type":1},{"id":"1579683243000184834","name":"90","type":1},{"id":"1580726129128992770","name":"186-超级管理员","type":1},{"id":"1582182526693732354","name":"测试1","type":1},{"id":"1582267287462277121","name":"李聪","type":1},{"id":"1582268293298319361","name":"张爱婷","type":1},{"id":"1582268293659029506","name":"李聪","type":1},{"id":"1582268294598553601","name":"李聪婷","type":1},{"id":"1582268295139618817","name":"张婷聪","type":1},{"id":"1582268295470968833","name":"张婷","type":1},{"id":"1582268295823290369","name":"张爱聪","type":1},{"id":"1582268296012034050","name":"任婷","type":1},{"id":"1582268296188194818","name":"张婷聪","type":1},{"id":"1582938632181313538","name":"李婷","type":1}],"roleOrg":{"role":[],"roleOrgType":"UNKNOWN","org":[]},"selfSelect":null,"formUser":null}</documentation>
<extensionElements>
<camunda:executionListener class="com.hfky.workflow.server.module.camunda.listener.task.sendtask.start.SendTaskStartListener" event="start"/>
<camunda:executionListener class="com.hfky.workflow.server.module.camunda.listener.task.sendtask.end.SendTaskEndListener" event="end"/>
</extensionElements>
<incoming>sequenceFlow_76b564f1-d4ad-4d53-900e-947df8979783</incoming>
<outgoing>node_926398936983_sequence</outgoing>
</sendTask>
<sequenceFlow id="sequenceFlow_76b564f1-d4ad-4d53-900e-947df8979783" sourceRef="root" targetRef="node_616935911517"/>
<sequenceFlow id="node_926398936983_sequence" sourceRef="node_616935911517" targetRef="node_926398936983">
<extensionElements>
<camunda:executionListener class="com.hfky.workflow.server.module.camunda.listener.sequence.UserTaskIncomingListener" event="take"/>
</extensionElements>
</sequenceFlow>
<userTask camunda:assignee="${user}" id="node_926398936983" name="审批人">
<documentation id="documentation_dc99fedc-fc7b-4985-b80a-bea805b02699">{"assignedType":["ASSIGN_USER"],"mode":"NEXT","sign":false,"formPerms":null,"nobody":{"handler":"TO_EXCEPTIONAL","assignedUser":[]},"timeLimit":null,"assignedUser":[{"id":"1580726129128992770","name":"186-超级管理员","type":1},{"id":"1659398930563702785","name":"刘法手机","type":1},{"id":"1585094725347098626","name":"11111","type":2}],"selfSelect":null,"leaderTop":null,"leader":null,"roleOrg":{"role":[],"roleOrgType":"ALL","org":[]},"refuse":null,"formUser":null}</documentation>
<extensionElements>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.create.UserTaskCreateListener" event="create"/>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.complete.UserTaskCompleteListener" event="complete"/>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.delete.UserTaskDeleteListener" event="delete"/>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.assignment.UserTaskAssignmentListener" event="assignment"/>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.update.UserTaskUpdateListener" event="update"/>
<camunda:inputOutput>
<camunda:inputParameter name="approvalMode">NEXT</camunda:inputParameter>
<camunda:inputParameter name="userTaskType">APPROVAL</camunda:inputParameter>
<camunda:inputParameter name="nobodyHandler">TO_EXCEPTIONAL</camunda:inputParameter>
</camunda:inputOutput>
</extensionElements>
<incoming>node_926398936983_sequence</incoming>
<outgoing>node_839328175114_sequence</outgoing>
<multiInstanceLoopCharacteristics camunda:collection="${users}" camunda:elementVariable="user" id="multiInstanceLoopCharacteristics_55826d3e-2ded-467b-a8ea-3be1ae6e102e" isSequential="true">
<completionCondition id="completionCondition_08ebe6ea-749f-4dc8-bd8b-55b0428db83b">${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<sequenceFlow id="node_839328175114_sequence" sourceRef="node_926398936983" targetRef="node_839328175114">
<extensionElements>
<camunda:executionListener class="com.hfky.workflow.server.module.camunda.listener.sequence.UserTaskIncomingListener" event="take"/>
</extensionElements>
</sequenceFlow>
<userTask camunda:assignee="${user}" id="node_839328175114" name="审批人">
<documentation id="documentation_621470e6-df17-4fb1-8fad-86011e0b344c">{"assignedType":["ASSIGN_USER"],"mode":"OR","sign":false,"formPerms":null,"nobody":{"handler":"TO_PASS","assignedUser":[]},"timeLimit":null,"assignedUser":[{"id":"1580726129128992770","name":"186-超级管理员","type":1},{"id":"1659398930563702785","name":"刘法手机","type":1},{"id":"1572769134128214018","name":"张柱11","type":1},{"id":"1613445750961299458","name":"洪小霞","type":1}],"selfSelect":null,"leaderTop":null,"leader":null,"roleOrg":{"role":[],"roleOrgType":"UNKNOWN","org":[]},"refuse":null,"formUser":null}</documentation>
<extensionElements>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.create.UserTaskCreateListener" event="create"/>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.complete.UserTaskCompleteListener" event="complete"/>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.delete.UserTaskDeleteListener" event="delete"/>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.assignment.UserTaskAssignmentListener" event="assignment"/>
<camunda:taskListener class="com.hfky.workflow.server.module.camunda.listener.task.usertask.update.UserTaskUpdateListener" event="update"/>
<camunda:inputOutput>
<camunda:inputParameter name="approvalMode">OR</camunda:inputParameter>
<camunda:inputParameter name="userTaskType">APPROVAL</camunda:inputParameter>
<camunda:inputParameter name="nobodyHandler">TO_PASS</camunda:inputParameter>
</camunda:inputOutput>
</extensionElements>
<incoming>node_839328175114_sequence</incoming>
<outgoing>sequenceFlow_39966a65-6409-4301-bd22-566da3f0abc5</outgoing>
<multiInstanceLoopCharacteristics camunda:collection="${users}" camunda:elementVariable="user" id="multiInstanceLoopCharacteristics_2ee36c6f-a743-44e8-96f1-5a9153434859" isSequential="false">
<completionCondition id="completionCondition_4c099868-903c-4c86-b1b3-7e60f78c96e6">${nrOfCompletedInstances == 1}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<endEvent id="end" name="结束">
<extensionElements>
<camunda:executionListener class="com.hfky.workflow.server.module.camunda.listener.end.EndEventEndListener" event="end"/>
</extensionElements>
<incoming>sequenceFlow_39966a65-6409-4301-bd22-566da3f0abc5</incoming>
</endEvent>
<sequenceFlow id="sequenceFlow_39966a65-6409-4301-bd22-566da3f0abc5" sourceRef="node_839328175114" targetRef="end"/>
<textAnnotation id="textAnnotation_e2d2a588-caf6-466e-8b93-29cdb683f4fd">
<text>审批节点/顺序依次审批/流程异常</text>
</textAnnotation>
<association id="association_6f8c3357-dce9-4d5a-9596-720975abad36" sourceRef="node_926398936983" targetRef="textAnnotation_e2d2a588-caf6-466e-8b93-29cdb683f4fd"/>
<textAnnotation id="textAnnotation_84c4a034-2871-4275-affd-4111c89f2f48">
<text>审批节点/或签/直接通过</text>
</textAnnotation>
<association id="association_6138d9c4-bf25-4f0d-b7ea-eadf4b06233a" sourceRef="node_839328175114" targetRef="textAnnotation_84c4a034-2871-4275-affd-4111c89f2f48"/>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_18a5de55-9957-40e6-b43e-5ebde913cdf5">
<bpmndi:BPMNPlane bpmnElement="process_SBJY" id="BPMNPlane_4328db3b-a050-4677-b4d6-22f5148b8739">
<bpmndi:BPMNShape bpmnElement="root" id="BPMNShape_df1df4ed-7fcc-4d16-95e2-996bdab5097e">
<dc:Bounds height="36.0" width="36.0" x="100.0" y="100.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="node_616935911517" id="BPMNShape_20d93b31-b628-4844-b9e6-f95aaa374d26">
<dc:Bounds height="80.0" width="100.0" x="186.0" y="78.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_76b564f1-d4ad-4d53-900e-947df8979783" id="BPMNEdge_7ce6d515-d414-470c-a10d-4faf4e827a9f">
<di:waypoint x="136.0" y="118.0"/>
<di:waypoint x="186.0" y="118.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape bpmnElement="node_926398936983" id="BPMNShape_9a09848e-47b5-4cf9-ba4d-202fca0076eb">
<dc:Bounds height="80.0" width="100.0" x="336.0" y="78.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="node_926398936983_sequence" id="BPMNEdge_6c227e09-8505-411f-b218-cccf6c7f6b62">
<di:waypoint x="286.0" y="118.0"/>
<di:waypoint x="336.0" y="118.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape bpmnElement="textAnnotation_e2d2a588-caf6-466e-8b93-29cdb683f4fd" id="BPMNShape_9778beb2-f56e-4525-adeb-55521420d4ae">
<dc:Bounds height="30.0" width="150.0" x="436.0" y="178.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="association_6f8c3357-dce9-4d5a-9596-720975abad36" id="BPMNEdge_9cf34fdc-3cda-4465-8bae-461a4b97d085">
<di:waypoint x="386.0" y="158.0"/>
<di:waypoint x="436.0" y="193.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape bpmnElement="node_839328175114" id="BPMNShape_2adea32c-7b35-4ed9-93dd-5d4d9b5c42e4">
<dc:Bounds height="80.0" width="100.0" x="486.0" y="78.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="node_839328175114_sequence" id="BPMNEdge_cb1c6de5-6bf5-496e-bf67-577bee2c033c">
<di:waypoint x="436.0" y="118.0"/>
<di:waypoint x="486.0" y="118.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape bpmnElement="textAnnotation_84c4a034-2871-4275-affd-4111c89f2f48" id="BPMNShape_ad901588-3b14-4870-9b4a-8061053332e5">
<dc:Bounds height="30.0" width="150.0" x="586.0" y="178.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="association_6138d9c4-bf25-4f0d-b7ea-eadf4b06233a" id="BPMNEdge_5da81668-e368-42a5-90b7-7751795cd44e">
<di:waypoint x="536.0" y="158.0"/>
<di:waypoint x="586.0" y="193.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_6f6c1e50-adde-4c61-8f9b-6f043ebda337">
<dc:Bounds height="36.0" width="36.0" x="636.0" y="100.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_39966a65-6409-4301-bd22-566da3f0abc5" id="BPMNEdge_41edea4e-b4c5-42db-9787-e5a2faf04c20">
<di:waypoint x="586.0" y="118.0"/>
<di:waypoint x="636.0" y="118.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

例如有上面的示例 XML
现在想获取 id 为 node_839328175114 的 userTask 的 documentation 的值
使用

1
select extractvalue(@xml, '/definitions/process/userTask[@id="node_839328175114"]/documentation');

这里我的场景是官方文档没有提到的, 做个简记
官方文档: https://dev.mysql.com/doc/refman/8.0/en/xml-functions.html

背景

有时我们想在同一个流程实例中查看流程从上到下的流转顺序, 效果像这样

Camunda-1

这时会到 ACT_HI_ACTINST 表里去查流程实例的节点信息

但是我们根据流程是 ID 去查数据的时候发现, 并没有很好的根据时间顺序进行排列,就比如上面的数据,在数据库反应的情况如下:

Camunda-2

可以看到 发起人和抄送人是几乎同时进行的,因为发起人发起后,第一个是抄送人任务, sendTask 的操作很快,创建时间 START_TIME 都是 2023-07-20 09:11:21
于是同一流程实例根据创建时间 START_TIME 排序就会出现问题,上面的数据就是抄送人跑到发起人前面去了

于是想着用没用其他的方法,来根据其他字段进行排序

解决方案

被我找到一个方案, 就是表里的主键 UUID

Camunda 默认主键策略是 UUID 这个配置可以在配置文件中修改

1
2
3
camunda:
bpm:
id-generator: strong

可以修改为 simplestrongprefixed, 默认是 strong

strong 策略的实现是 StrongUuidGenerator, 源码位置在 org.camunda.bpm.engine.impl.persistence.StrongUuidGenerator

其中生成 ID 的 getNextId 方法是使用的 fasterxmlTimeBasedGenerator, 源码位置在 com.fasterxml.uuid.impl.TimeBasedGenerator

从名字可以看出是基于时间生成的,实际上生成的是 UUID 的 version 1 版本

于是就是可以根据时间来排序了

具体操作

继续翻源码, 我们来到 java-uuid-generator-3.2.0.jar 这个依赖包, 其中 2 个类引起了我的注意
UUIDUtilUUIDComparator

那么排序就很简单了, 如下代码就可轻松排序:

1
2
3
4
5
6
7
8
9
public class UUIDTimeOrderTest {
public static void main(String[] args) {
String[] demos = ("c0767f45-0367-11ee-9698-8edff34f00ff,c07aec28-0367-11ee-9698-8edff34f00ff,c167211a-0367-11ee-9698-8edff34f00ff,c1687fb5-0367-11ee-9698-8edff34f00ff,c169b840-0367-11ee-9698-8edff34f00ff,c16b8d0b-0367-11ee-9698-8edff34f00ff").split(",");
Arrays.stream(demos)
.sorted((s1, s2) -> UUIDComparator.staticCompare(UUIDUtil.uuid(s1), UUIDUtil.uuid(s2)))
.forEach(s -> System.out.println(s));
}

}

背景

特斯拉开了将近 2 年了, 没有进行任何保养过, 最近想去保养下, 发下没有什么值得保养的

就我目前收集的信息, 目前可以保养的有

  1. 空调滤芯, 官方建议每年更换一次
  2. 空调管道支架,很早之前有发召回的公告,需要加装支架
  3. 前支臂,原地方向盘打满的时候, 前轮会发出哒哒哒的异响,不是刹车片摩擦的声音,我查询了下,应该通病

其实前 2 个问题, 并没有什么安全隐患,也并不是强制性的, 然后我就看了下空调滤芯的事情, 发现如果到官方的售后去更换的话, 材料费加上人工工时费,大概在 340
我在京东买个 2 个前置的曼牌空调滤芯, 打算自己动手更换

准备工具

  1. T20 螺丝刀
  2. 撬棒,家里没有,我拿了个金属勺子代替

步骤

  1. 将副驾驶的座位移到最后面
  2. 拿掉副驾驶脚垫
  3. 使用 T20 螺丝刀拧下副驾驶下方右侧的螺丝, 左侧的没有螺丝, 是个塑料的膨胀螺丝, 拿东西撬一下就行
  4. 沿着手套箱下面的边缝撬起,去下下方的塑料壳盖板,注意有 2 根排线相连,取得时候用力不能过大,否则会扯断排线
  5. 我这里为了顺利拆掉侧方的挡板, 我拔掉了喇叭的排线,这样能够把整个塑料壳放到傍边,也可以把氛围灯的排线一并拆掉,这样可以整体拿下来
  6. 使用撬棒沿着侧边挡板的缝隙慢慢撬起, 随后用手沿着挡板把整个挡板拽下来,要用点力气, 这里注意拔下来的挡板白色卡扣,有时候不会被一起带出来,需要手动去下来,再装回卡勾上, 不然还原装回去的时候容易掉下去,导致车里异响

挡板

  1. 拆下挡板后可以看到最里面的滤芯槽盖板, 上方有一个 T20 的螺丝, 拆下他, 可以去除盖板

滤芯槽盖板
滤芯槽盖板2

  1. 取出 2 片空调滤芯,再放入新买的

新旧对比1
新旧对比2

对比了下新旧, 发现我之前旧的滤芯并不是很脏,但是有点潮湿了,还有异味

  1. 还原

我的 Tesla

Spring Cloud Gateway 配合 Sentinel 实现限流
在 sentinel dashboard 配置贵州后,重启服务会失效

本篇介绍如何持久化

引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

配置服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
spring:
cloud:
sentinel:
filter:
enabled: false
scg:
# 请求被 ban 的响应
fallback:
response-status: 429
response-body: 操作频繁,您已被限流,请稍后重试
mode: "response"
content-type: "text/plain; charset=utf-8"
datasource:
# 接口分组配置
gw-api-group:
nacos:
server-addr: ${nacos.server-addr}
username: ${spring.cloud.nacos.username}
password: ${spring.cloud.nacos.password}
namespace: sentinel
group-id: DEFAULT_GROUP
data-id: gw-api-group-rules
rule-type: gw-api-group
# 接口限流配置
gw-rule:
nacos:
server-addr: ${nacos.server-addr}
username: ${spring.cloud.nacos.username}
password: ${spring.cloud.nacos.password}
namespace: sentinel
group-id: DEFAULT_GROUP
data-id: gw_flow-rules
rule-type: gw_flow
eager: true

创建配置文件

在 Nacos 上新建命名空间 sentinel,
再分别新建配置文件 gw-api-group-rulesgw_flow-rules

分别配置如下:

gw-api-group-rules:

1
2
3
4
5
6
7
8
9
10
11
[
{
"apiName": "cipher_group",
"predicateItems": [
{
"pattern": "/im-wildfirechat/support/cipher",
"matchStrategy": 0
}
]
}
]

gw_flow-rules:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[
{
"resource": "cipher_group",
"resourceMode": 1,
"grade": 1,
"count": 2,
"intervalSec": 60,
"controlBehavior": 0,
"burst": 0,
"maxQueueingTimeoutMs": 500,
"paramItem": {
"parseStrategy": 1,
"fieldName": null,
"pattern": null,
"matchStrategy": 0
}
}
]

保存

配置文件的配置项参考官方文档: https://sentinelguard.io/zh-cn/docs/api-gateway-flow-control.html

或者参考 代码类 com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRulecom.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition

具有源码可查看 com.alibaba.cloud.sentinel.datasource.RuleType

验证

启动服务

  1. 查看 sentinel dashboard 的配置
  2. 调用接口,看是否返回被 ban 信息

api-group
aip=rule

ssh 配置开启隧道的 tcp 转发

有时我们开启 本地端口转发或者远程端口转发想在内网的其他服务器上使用该端口,修改修改 /etc/ssh/sshd_config 配置文件来开启转发

  1. 打开配置项 AllowTcpForwarding yes
  2. 打开配置项 GatewayPorts yes
  3. 如果长时间保持连接,那么还需要开启 TCPKeepAlive yes

配置场景:
有时我们有多个前缀需要反向代理到同一个后端服务,
比如 /s1, /s2, /s3-xxx, 都代理到同一个后端服务
最普通的写法可以写多个 location 来匹配, 这里介绍使用一个 location 完成匹配

1
2
3
4
5
6
7
8
9
10
11
12
location ~* ^/(s1|s2|s3-*)/ {
proxy_pass http://GATEWAY;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
}

上面还配置了支持升级http协议支持了https

0%