转载出处来自分享牛http://blog.csdn.net/qq_30739519)

Activiti多实例任务有并行、串行区分。

并行代表同时进行,如把任务分给5个人来处理,这5个人同时会收到任务,并且可以同时处理,不受各自的影响。

串行代表工作或任务由一个人完成后,再由另一个人去处理,直至全部完成,每个任务依赖于前一个任务完成。

我们在使用activiti 工作流引擎的时候,最常用的肯定是任务节点,因为在OA系统、审批系统、办公自动化系统中核心的处理就是流程的运转,在流程运转的时候,可能我们有这样的一个需求,在一个任务节点的时候,我们需要多个人对这个节点进行审批,比如实际中这样一个例子,假如是一个部门的投票,这个部门有5个人,那么当5个人都投票的时候大概分为如下几种:

1.部门所有人都去投票,当所有人都投票完成的时候,这个节点结束,流程运转到下一个节点。(所有的人都需要投票)

2.部门所有人都去投票,只要有任意2/3的人同意,这个节点结束,流程运转到下一个节点。(部分人投票只要满足条件就算完成)。

3.部门中有一个部门经理,只要部门经理投票过了,这个节点结束,流程运转到下一个节点(一票否决权)。

4.部门中根据职位不同,不同的人都不同的权重,当满足条件的时候,这个节点结束,流程运转到下一个节点。比如说所有的人员权重加起来是1,a有0.2的权重,其他的四个人分别是0.1的权重,我们可以配置权重达到0.3就可以走向下一个节点,换言之a的权重是其他人的2倍,那就是a的投票相当于2个人投票。这种需求还是很常见的。

5.部门所有人都去投票,a投票结束到b,b开始投票结束到c,一直如此,串行执行。最终到最后一个人再统计结果,决定流程的运转。

上面的五种情况,我们可以提取出来一些信息,我们的activiti 工作流引擎,必须支持如下功能,才能满足上面的需求:

1.任务节点可以配置自定义满足条件。

2.任务节点必须支持串行、并行。

3.任务节点必须支持可以指定候选人或者候选组。

4.任务节点必须支持可以循环的次数。

5.任务节点必须支持可以自定义权重。

6.任务节点必须支持加签、减签。(就是动态的修改任务节点的处理人)

因为实际上的需求可能比上面的几种情况更加的复杂,上面的6个满足条件,工作流支持前4个,后面的2个条件是不支持的,所以我们必须要扩展activiti 工作流引擎才能使用5、6等的功能。下面我们将详细的介绍前四种条件的使用,在掌握基本使用之后,我们在后面的章节中将详细的介绍,5、6这两种功能以及可能更加复杂的操作。

1.1.2. 串行、并行配置

为了演示如何使用,我们采用由浅入深的使用,结合流程图、流程定义xml、以及代码和数据库的变化来阐释每一个配置的使用以及含义。

流程的详细定义如下图所示:

流程的详细定义xml如下所示:

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <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="daling">

  3. <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">

  4. <startEvent id="startevent1" name="Start"></startEvent>

  5. <userTask id="usertask1" name="多实例任务" activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4">

  6. <multiInstanceLoopCharacteristics isSequential="true">

  7. <loopCardinality>2</loopCardinality>

  8. </multiInstanceLoopCharacteristics>

  9. </userTask>

  10. <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>

  11. <endEvent id="endevent1" name="End"></endEvent>

  12. <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>

  13. </process>

  14. <bpmndi:BPMNDiagram id="BPMNDiagram_daling">

  15. <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">

  16. <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">

  17. <omgdc:Bounds height="35.0" width="35.0" x="180.0" y="150.0"></omgdc:Bounds>

  18. </bpmndi:BPMNShape>

  19. <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">

  20. <omgdc:Bounds height="55.0" width="105.0" x="370.0" y="90.0"></omgdc:Bounds>

  21. </bpmndi:BPMNShape>

  22. <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">

  23. <omgdc:Bounds height="35.0" width="35.0" x="650.0" y="130.0"></omgdc:Bounds>

  24. </bpmndi:BPMNShape>

  25. <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">

  26. <omgdi:waypoint x="215.0" y="167.0"></omgdi:waypoint>

  27. <omgdi:waypoint x="422.0" y="145.0"></omgdi:waypoint>

  28. </bpmndi:BPMNEdge>

  29. <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">

  30. <omgdi:waypoint x="475.0" y="117.0"></omgdi:waypoint>

  31. <omgdi:waypoint x="667.0" y="130.0"></omgdi:waypoint>

  32. </bpmndi:BPMNEdge>

  33. </bpmndi:BPMNPlane>

  34. </bpmndi:BPMNDiagram>

  35. </definitions>

xml配置文件的部分含义如下:

1.activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4" 这个节点可以4个人审核。

2.<loopCardinality>2</loopCardinality> 循环2次结束。

3.<multiInstanceLoopCharacteristics isSequential="true"> 串行并行的配置。

1.1.2.1. 串行的配置

修改<multiInstanceLoopCharacteristics isSequential="true"> 中的isSequential为true是串行,isSequential为false是并行。我们测试串行。下面的代码展示启动流程因为是以一个节点所以部署启动后,直接进入多实例任务。

1.1.2.1.1. 流程的部署

  1. Deployment deploy = repositoryService2.createDeployment()

  2. .category(category).addClasspathResource("demo1.bpmn").deploy();

1.1.2.1.2. 流程的启动

/**

*

@param runtimeService

@param key

*            act_re_procdef表的Id

@param businessKey

*            业务单号

@return

*/

public ProcessInstance startProcessInstanceByKey(

RuntimeService runtimeService, String key, String businessKey) {

ProcessInstance processInstance = runtimeService

.startProcessInstanceByKey(key, businessKey);

return processInstance;

}

我们按照上面的步骤启动一个流程看一下数据库的变化。

ACT_RU_TASK表的数据有了如下图所示:

ACT_RU_IDENTITYLINK表的数据有了如下图所示:

ACT_RU_IDENTITYLINK权限表中,确实把我们设置的人员信息设置进去了,shareniu1,shareniu2,shareniu3,shareniu4现在就有代办信息了。

ACT_RU_VARIABLE表的数据有了如下图所示:

上面重要的变量需要解释一下,要不然还真不好理解,多任务是怎么运转的。

1.nrOfInstances  实例总数。

2.nrOfCompletedInstances  当前还没有完成的实例 nr是number单词缩写 。

3.loopCounter 已经循环的次数。

4.nrOfActiveInstances 已经完成的实例个数。

下面我们结束一个任务看一下,流程走到那个节点了。

1.1.2.1.3. 完成任务

String taskId="45009";

demo.getTaskService().complete(taskId);

接下来看一下数据库表的变化。

ACT_RU_VARIABLE表的数据有了如下图所示:

上面我们仔细的发现,可以看到

nrOfCompletedInstances、loopCounter、nrOfActiveInstances都加1了,确实多任务就是参考这几个值的变化进行判断的。

因为我们设置了循环2次,所以我们看看ACT_RU_IDENTITYLINK还有一个任务,因为我们是并行处理的。

所以我们在结束新的任务看一下流程是不是真的结束了,如果结束了,那么我们循环次数的配置就是正确的。

1.1.2.1.4. 完成任务

String taskId="47502";

demo.getTaskService().complete(taskId);

下面看一下ACT_RU_TASK,里面没有任务信息了,所以侧面证明循环次数的配置就是正确的。

接下来我们测试并行任务。除了isSequential="false",其他的配置是一样的。

1.1.2.2. 并行的配置测试

除了isSequential="false",其他的配置跟上面的串行是一样一样的。

重新部署测试,部署后我们启动一个新的流程测试。

ACT_RU_TASK表如下:

一次性的有2个任务需要处理,因为我们循环的是2次,所以直接就是2个。

ok串行、并行就讲解到这里。

1.1.3. 串行、并行总结

我们配置的是循环2次,看以看到不管是并行还是串行,两个代办任务结束之后,流程直接跳转到下一个状态,但是

我们并没有配置结束条件,所以上面的例子,也可以看出来,如果不配置默认的通过条件,则默认条件是1,后面的源码章节会给大家说明这一点的。

1.1.4. 通过条件的配置

在上面的串行、并行实例中,我们没有设置通过条件,但是程序按照配置的循环的次数,然后跳转到了下一个状态,可以侧面印证,如果不配置通过条件则默认值就是1.

下面的代码详细的介绍通过条件的配置,具体的配置代码如下:

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <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="daling">

  3. <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">

  4. <startEvent id="startevent1" name="Start"></startEvent>

  5. <userTask id="usertask1" name="多实例任务" activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4">

  6. <multiInstanceLoopCharacteristics isSequential="false">

  7. <loopCardinality>4</loopCardinality>

  8. <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition>

  9. </multiInstanceLoopCharacteristics>

  10. </userTask>

  11. <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>

  12. <endEvent id="endevent1" name="End"></endEvent>

  13. <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>

  14. </process>

  15. <bpmndi:BPMNDiagram id="BPMNDiagram_daling">

  16. <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">

  17. <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">

  18. <omgdc:Bounds height="35.0" width="35.0" x="180.0" y="150.0"></omgdc:Bounds>

  19. </bpmndi:BPMNShape>

  20. <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">

  21. <omgdc:Bounds height="55.0" width="105.0" x="371.0" y="140.0"></omgdc:Bounds>

  22. </bpmndi:BPMNShape>

  23. <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">

  24. <omgdc:Bounds height="35.0" width="35.0" x="660.0" y="150.0"></omgdc:Bounds>

  25. </bpmndi:BPMNShape>

  26. <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">

  27. <omgdi:waypoint x="215.0" y="167.0"></omgdi:waypoint>

  28. <omgdi:waypoint x="371.0" y="167.0"></omgdi:waypoint>

  29. </bpmndi:BPMNEdge>

  30. <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">

  31. <omgdi:waypoint x="476.0" y="167.0"></omgdi:waypoint>

  32. <omgdi:waypoint x="660.0" y="167.0"></omgdi:waypoint>

  33. </bpmndi:BPMNEdge>

  34. </bpmndi:BPMNPlane>

  35. </bpmndi:BPMNDiagram>

  36. </definitions>

1.1.4.1. 配置描述

<completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition>

nrOfCompletedInstances、nrOfInstances 变量描述上面已经描述了,我们这里设置的条件是大于1/4的人完成任务,任务就结束了。下面我们代码部署流程,启动流程后进行测试:

ACT_RU_TASK表如下:

我们随便结束一个任务,看一下ACT_RU_TASK表变化。

String taskId="60038";

demo.getTaskService().complete(taskId);

执行上面的代码,我们很神奇的发现,ACT_RU_TASK表中的其他任务没有了,因为我们配置了4个人,通过条件是1/4,所以任意一个人结束了,流程就结束了。这里我们测试的是并行,串行也是一样的,读者可以自行测试验证。

1.1.5. 动态的配置

上面的几种方式,我们定义xml的时候,循环的次数是固定写在xml中的,也就是说我们配置的是循环2次,那么所有的流程实例都是循环2次,这样就不灵活了,程序当然是灵活了比较好,所以在实际开发中,我们可以使用下面的这种方式操作,使程序更加的灵活。

程序的xml配置如下所示:

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <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="daling">

  3. <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">

  4. <startEvent id="startevent1" name="Start"></startEvent>

  5. <userTask id="usertask1" name="多实例任务" activiti:assignee="${assignee}">

  6. <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee">

  7. <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition>

  8. </multiInstanceLoopCharacteristics>

  9. </userTask>

  10. <endEvent id="endevent1" name="End"></endEvent>

  11. <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>

  12. <userTask id="usertask2" name="User Task"></userTask>

  13. <sequenceFlow id="flow3" sourceRef="startevent1" targetRef="usertask2"></sequenceFlow>

  14. <sequenceFlow id="flow4" sourceRef="usertask2" targetRef="usertask1"></sequenceFlow>

  15. </process>

  16. <bpmndi:BPMNDiagram id="BPMNDiagram_daling">

  17. <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">

  18. <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">

  19. <omgdc:Bounds height="35.0" width="35.0" x="180.0" y="150.0"></omgdc:Bounds>

  20. </bpmndi:BPMNShape>

  21. <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">

  22. <omgdc:Bounds height="55.0" width="105.0" x="371.0" y="140.0"></omgdc:Bounds>

  23. </bpmndi:BPMNShape>

  24. <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">

  25. <omgdc:Bounds height="35.0" width="35.0" x="660.0" y="150.0"></omgdc:Bounds>

  26. </bpmndi:BPMNShape>

  27. <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">

  28. <omgdc:Bounds height="55.0" width="105.0" x="330.0" y="50.0"></omgdc:Bounds>

  29. </bpmndi:BPMNShape>

  30. <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">

  31. <omgdi:waypoint x="476.0" y="167.0"></omgdi:waypoint>

  32. <omgdi:waypoint x="660.0" y="167.0"></omgdi:waypoint>

  33. </bpmndi:BPMNEdge>

  34. <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">

  35. <omgdi:waypoint x="197.0" y="150.0"></omgdi:waypoint>

  36. <omgdi:waypoint x="382.0" y="105.0"></omgdi:waypoint>

  37. </bpmndi:BPMNEdge>

  38. <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">

  39. <omgdi:waypoint x="382.0" y="105.0"></omgdi:waypoint>

  40. <omgdi:waypoint x="423.0" y="140.0"></omgdi:waypoint>

  41. </bpmndi:BPMNEdge>

  42. </bpmndi:BPMNPlane>

  43. </bpmndi:BPMNDiagram>

  44. </definitions>

动态配置如下所示:

<userTask id="usertask1" name="多实例任务" activiti:assignee="${assignee}">

<multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee">

<completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition>

</multiInstanceLoopCharacteristics>

</userTask>

参数说明:

activiti:assignee="${assignee}"

activiti:elementVariable="assignee" 多实例任务依赖上面的配置${assignee}

activiti:collection="assigneeList"

三个参数结合决定了,当前节点的处理人来自assigneeList集合,注意这里是集合信息而不是字符串,所以程序的运行时候变量的赋值,如下所示:

String[]v={"shareniu1","shareniu2","shareniu3","shareniu4"};

vars.put("assigneeList",  Arrays.asList(v));

String taskId="97515";

demo.getTaskService().complete(taskId,vars);

ok了,测试一下,确实程序如预期的所示,大功告成。

1.1.6. 总结

参数的使用总结

4.activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4" 这个节点可以4个人审核。

5.<loopCardinality>2</loopCardinality> 循环2次结束。

6.<multiInstanceLoopCharacteristics isSequential="true"> 串行并行的配置。

7.

<completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition> 完成条件的配置。

这里我们还可以得出一个结论:

如果使用串行方式操作nrOfActiveInstances 变量始终是1,因为并行的时候才会去+1操作

Activiti并行网关和串行网关区别相关推荐

  1. 1.4总线:并行总线、串行总线、单工、半双工、全双工、总线宽度、总线带宽、总线的分类、数据总线、地址总线、控制总线

    1.4总线:并行总线.串行总线.单工.半双工.全双工.总线宽度.总线带宽.总线的分类.数据总线.地址总线.控制总线 总线 并行总线.串行总线 单工.半双工.全双工 总线宽度 总线带宽 总线的分类 数据 ...

  2. java8新特性--并行流与串行流

    并行流与串行流 1.概述 2.实例 1.概述 并行流就是把一个内容分成多个数据块,并用不同的线程分 别处理每个数据块的流. Java 8 中将并行进行了优化,我们可以很容易的对数据进行并 行操作.St ...

  3. java8新特性【Lambda、Stream API、Optional、Date Time API 、并行流与串行流】

    文章目录 Lambda 表达式 Lambda 表达式的基础语法 方法引用 Lambda 表达式需要"函数式接口"的支持 Java8 内置的四大核心函数式接口 Stream API ...

  4. 总线的定义, 并行总线和串行总线

    任何一个微处理器都要与一定数量的部件和外围设备连接,但如果将各部件和每一种外围设备都分别用一组线路与CPU直接连接,那么连线将会错综复杂,甚至难以实现.为了简化硬件电路设计.简化系统结构,常用一组线路 ...

  5. 同步和串行的区别_[深度思考]·为什么CNN是同步(并行)而RNN是异步(串行)的呢?...

    为什么CNN是同步(并行)而RNN是异步(串行)的呢? 个人主页--> https://xiaosongshine.github.io/ 1.问题引出 CNN与RNN都是采用parameter ...

  6. “并行程序VS串行程序”——并行程序优化实录

    在多核处理器.超级计算机日益普及的今天,程序员们怎能对并行程序"袖手旁观"呢? 为了练手,我用MPI写了一个并行排序程序, 先介绍下我的第一个版本,大概的思路是: 使用MPI在各个 ...

  7. 同步和串行的区别_谈谈SPI (Serial Peripheral Interface,串行外设接口)

    什么是SPI SPI (Serial Peripheral Interface,串行外设接口)是Motorola 公司推出的一 种同步串行接口技术,是一种高速的,全双工,同步的通信总线: 它以主从方式 ...

  8. java+串行和并行的区别_Java8新特性_并行流与串行流

    1.Java8中forkjoin框架使用更加简单了 1.7中的ForkJoin框架编码复杂且容易出错,而8中的编码则十分简单 JDK1.7时开发者需要自定义计算类,如 package com.atgu ...

  9. 串行并行 同步异步通信

    终端与其他设备(例如其他终端.计算机和外部设备)通过数据传输进行通信.数据传输可以通过两种方式进行:并行通信和串行通信. 1.串行通信 是指使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个 ...

最新文章

  1. mysql 5.6 online ddl_mysql5.6的online ddl功能测试
  2. python100行代码-python代码行数统计 100行
  3. LeetCode 70爬楼梯71简化路径72编辑距离(dp)
  4. php 安全基础 第七章 验证与授权 密码嗅探
  5. java gsoap_gsoap c与java web之间传输字符串中文乱码问题 | 学步园
  6. 【转】细说.NET 中的多线程 (一 概念)
  7. linx vim 文件操作 ubuntu server 软件源
  8. 【kafka】kafka log 存储时间 小于 offset 存储时间 offset存在但是消费不到
  9. 在c语言中large的作用,输入两个数组,调用large函数比较,计数,输出统计结果...
  10. 终端服务器超出最大允许连接数
  11. 通讯录(结尾附全部代码)
  12. python中unicode编码表_python unicode 编码整理
  13. 第一期:一款简单好用的屏幕画笔工具
  14. HTML5期末大作业:绿色特产商城网站设计——绿色特产商城购物网(11页) HTML+CSS+JavaScript 网页设计作业,网页制作作业, 学生网页作业, 网页作业成品, 网页作业模板
  15. 计算机一级考excel基础知识,计算机一级考试模拟题(word、excel、ppt以及基础知识)...
  16. 分布式开源调度框架TBSchedule详解
  17. 以太坊源码分析(37)eth以太坊协议分析
  18. thinkpad如何禁用触摸板(触控板)或指点杆
  19. springboot banner.txt文件
  20. java scan.next_Java使用scanner.nextLine()

热门文章

  1. 短信认证被宣布不安全,将被何种方式取代?
  2. 群辉docker搭建easymock
  3. 网络地址转换(NAT)(一)
  4. 解决Win10运行软件程序提示【管理员已阻止你运行此应用】
  5. CSS移动端适配方案
  6. 数组push之后赋值给新变量之后输出为数字问题
  7. chronodex怎么用_以终为始的时间流管理
  8. 虚拟机安装的CentOS系统不能上网解决办法
  9. 局域网网络监控和透明文件加密原理、需求、模式、实例、功能、部署、方案全攻略
  10. Cura二次开发之源码编译