文章目录

  • 1.1 简介
  • 1.2 中间事件
    • 1.3 定时中间事件
      • 1.3.1 简介
      • 1.3.2 设计流程图
    • 1.4 信号中间事件
      • 1.4.1 简介
      • 1.4.2 触发信号事件
      • 1.4.3 查询信号事件的订阅
      • 1.4.4 信号事件范围
      • 1.4.5 信号中间Catching事件
        • 1.4.5.1 简介
        • 1.4.5.2 设计流程图
      • 1.4.6 信号中间Throwing事件
        • 1.4.6.1 简介
        • 1.4.6.2 设计流程图
    • 1.5 消息中间事件
      • 1.5.1 消息事件的定义
      • 1.5.2 触发消息事件
      • 1.5.3 查询消息事件的订阅
      • 1.5.4 消息中间事件的定义
      • 1.5.5 设计流程图

1.1 简介

版权声明:本文部分为CSDN博主「司马缸砸缸了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接

1.2 中间事件

中间事件分为两类:中间Cathing事件和中间Throwing事件,当流程到达中间Cathing事件时,它会一直等待知道接收到消息,才会触发。当流程到达中间Throwing事件时,该事件会自动触发并抛出结果。
BPMN2.0中定义的中间Cathing事件有:消息中间事件,定时器中间事件,条件中间事件,连接中间事件,信号中间事件,组合中间事件,并行中间事件等。
中间Throwing事件有:无指定中间事件,消息中间事件,补偿中间事件,连接中间事件,信号中间事件,组合中间事件等。

1.3 定时中间事件

1.3.1 简介

定时器中间事件是一个Catching事件,当执行到达捕获事件节点, 就会启动一个定时器。 当定时器触发(一段时间之后),流程就会沿着定时中间事件的外出节点继续执行。

1.3.2 设计流程图

场景:用户支付成功后等待一分钟,商家发货


流程文件bpmn

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1596009257179" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"><process id="timing" isClosed="false" isExecutable="true" name="Timing" processType="None"><startEvent id="_2" name="开始"/><userTask activiti:assignee="user1" activiti:exclusive="true" id="_3" name="支付"/><userTask activiti:assignee="user2" activiti:exclusive="true" id="_4" name="发货"/><endEvent id="_5" name="结束"/><sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/><intermediateCatchEvent id="_7" name="IntermediateCatchingEvent"><timerEventDefinition id="_7_ED_1"><timeDuration><![CDATA[PT1M]]></timeDuration></timerEventDefinition></intermediateCatchEvent><sequenceFlow id="_8" sourceRef="_3" targetRef="_7"/><sequenceFlow id="_9" sourceRef="_7" targetRef="_4"/><sequenceFlow id="_10" sourceRef="_4" targetRef="_5"/></process><bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"><bpmndi:BPMNPlane bpmnElement="timing"><bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="310.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"><omgdc:Bounds height="55.0" width="85.0" x="150.0" y="305.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"><omgdc:Bounds height="55.0" width="85.0" x="380.0" y="305.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"><omgdc:Bounds height="32.0" width="32.0" x="595.0" y="315.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7"><omgdc:Bounds height="32.0" width="32.0" x="285.0" y="315.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3"><omgdi:waypoint x="32.0" y="326.0"/><omgdi:waypoint x="150.0" y="332.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_3" targetElement="_7"><omgdi:waypoint x="235.0" y="332.5"/><omgdi:waypoint x="285.0" y="331.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_7" targetElement="_4"><omgdi:waypoint x="317.0" y="331.0"/><omgdi:waypoint x="380.0" y="332.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_4" targetElement="_5"><omgdi:waypoint x="465.0" y="332.5"/><omgdi:waypoint x="595.0" y="331.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

测试类

package com.yb.activiti6;import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;
import java.util.List;/*** @author liangjie@itcast.cn* @version 1.0* @date 2020/7/23*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiDemoTest11 {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate IdentityService identityService;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate ProcessEngine processEngine;@Autowiredprivate HistoryService historyService;/*** 发布流程,测试定时中间事件* @throws IOException*/@Testpublic void deploymentProcesses_zip(){Deployment deploy = repositoryService.createDeployment().name("测试-定时中间事件-1")//创建流程名称.addClasspathResource("processes/activiti_timing.bpmn")//指定zip完成部署.addClasspathResource("processes/activiti_timing.png").deploy();System.out.println("部署id:"+deploy.getId());System.out.println("部署名称:"+deploy.getName());}/*** 启动流程,测试定时中间事件*/@Testpublic void startProcess() throws InterruptedException{//可根据id,key,message启动流程ProcessInstance parallel = runtimeService.startProcessInstanceByKey("timing");System.out.println("流程实例id:"+parallel.getId());System.out.println("流程定义id:"+parallel.getProcessDefinitionId());System.out.println("========================================================");List<Task> list = taskService.createTaskQuery().taskAssignee("user1").list();for (Task task : list) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());//完成支付任务taskService.complete(task.getId());}//暂停70秒System.out.println("暂停70秒");Thread.sleep(1000 * 70);list = taskService.createTaskQuery().taskAssignee("user2").list();for (Task task : list) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());//完成发货任务taskService.complete(task.getId());}}
}

效果

1.4 信号中间事件

1.4.1 简介

信号中间事件分为Catching事件和Throwing事件。

1.4.2 触发信号事件

既可以通过bpmn节点由流程实例触发一个信号,也可以通过API触发。
手动触发信号:

// 把信号发送给全局所有订阅的处理器
RuntimeService.signalEventReceived(String signalName);
// 把信号发送给指定执行流
RuntimeService.signalEventReceived(String signalName, String executionId);

1.4.3 查询信号事件的订阅

List<Execution> executions = runtimeService.createExecutionQuery().signalEventSubscriptionName("alert").list();

1.4.4 信号事件范围

默认,信号会在流程引擎范围内进行广播。就是说, 你可以在一个流程实例中抛出一个信号事件,其他不同流程定义的流程实例 都可以监听到这个事件。然而,有时只希望在同一个流程实例中响应这个信号事件。 比如一个场景是,流程实例中的同步机制,如果两个或更多活动是互斥的。
如果想要限制信号事件的范围,可以使用信号事件定义的scope 属性 (不是BPMN2.0的标准属性):

<signal id="alertSignal" name="alert" activiti:scope"processInstance"/>

1.4.5 信号中间Catching事件

1.4.5.1 简介

信号中间Catching事件会等待被触发,直到接收到相应的信号。

1.4.5.2 设计流程图

例如有如下场景,流程启动后或产生两条执行流,一条用户支付成功后发送信号,第二条等待接收信号后进入发货节点。


流程文件bpmn

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1596011479461" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"><process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"><startEvent id="_2" name="开始"/><parallelGateway gatewayDirection="Unspecified" id="_3" name="ParallelGateway"/><userTask activiti:assignee="user1" activiti:exclusive="true" id="_4" name="支付"/><serviceTask activiti:exclusive="true" id="_5" name="生成订单"/><parallelGateway gatewayDirection="Unspecified" id="_6" name="ParallelGateway"/><endEvent id="_7" name="结束"/><intermediateCatchEvent id="_8" name="IntermediateCatchingEvent"><signalEventDefinition id="_8_ED_1" signalRef="SIG_1"/></intermediateCatchEvent><userTask activiti:assignee="user2" activiti:exclusive="true" id="_9" name="发货"/><sequenceFlow id="_10" sourceRef="_2" targetRef="_3"/><sequenceFlow id="_11" sourceRef="_3" targetRef="_4"/><sequenceFlow id="_12" sourceRef="_3" targetRef="_5"/><sequenceFlow id="_13" sourceRef="_5" targetRef="_8"/><sequenceFlow id="_14" sourceRef="_8" targetRef="_9"/><sequenceFlow id="_15" sourceRef="_9" targetRef="_6"/><sequenceFlow id="_16" sourceRef="_4" targetRef="_6"/><sequenceFlow id="_17" sourceRef="_6" targetRef="_7"/></process><signal id="SIG_1" name="pay"/><bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"><bpmndi:BPMNPlane bpmnElement="myProcess_1"><bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="240.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"><omgdc:Bounds height="32.0" width="32.0" x="130.0" y="240.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"><omgdc:Bounds height="55.0" width="85.0" x="205.0" y="100.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"><omgdc:Bounds height="55.0" width="85.0" x="210.0" y="365.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6"><omgdc:Bounds height="32.0" width="32.0" x="640.0" y="240.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7"><omgdc:Bounds height="32.0" width="32.0" x="760.0" y="240.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_8" id="Shape-_8"><omgdc:Bounds height="32.0" width="32.0" x="390.0" y="375.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_9" id="Shape-_9"><omgdc:Bounds height="55.0" width="85.0" x="505.0" y="365.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="_5" targetElement="_8"><omgdi:waypoint x="295.0" y="392.5"/><omgdi:waypoint x="390.0" y="391.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_3" targetElement="_5"><omgdi:waypoint x="162.0" y="256.0"/><omgdi:waypoint x="210.0" y="392.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_15" id="BPMNEdge__15" sourceElement="_9" targetElement="_6"><omgdi:waypoint x="590.0" y="392.5"/><omgdi:waypoint x="640.0" y="256.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_14" id="BPMNEdge__14" sourceElement="_8" targetElement="_9"><omgdi:waypoint x="422.0" y="391.0"/><omgdi:waypoint x="505.0" y="392.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_17" id="BPMNEdge__17" sourceElement="_6" targetElement="_7"><omgdi:waypoint x="672.0" y="256.0"/><omgdi:waypoint x="760.0" y="256.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_16" id="BPMNEdge__16" sourceElement="_4" targetElement="_6"><omgdi:waypoint x="290.0" y="127.5"/><omgdi:waypoint x="640.0" y="256.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_3" targetElement="_4"><omgdi:waypoint x="162.0" y="256.0"/><omgdi:waypoint x="205.0" y="127.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_2" targetElement="_3"><omgdi:waypoint x="32.0" y="256.0"/><omgdi:waypoint x="130.0" y="256.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

测试类

package com.yb.activiti6;import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;
import java.util.List;/*** @version 1.0* @date 2020/7/23*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiDemoTest12 {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate IdentityService identityService;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate ProcessEngine processEngine;@Autowiredprivate HistoryService historyService;/*** 发布流程,测试信号中间Catching事件* @throws IOException*/@Testpublic void deploymentProcesses_zip(){Deployment deploy = repositoryService.createDeployment().name("测试-信号中间Catching事件-1")//创建流程名称.addClasspathResource("processes/activiti_signalCenter.bpmn")//指定zip完成部署.addClasspathResource("processes/activiti_signalCenter.png").deploy();System.out.println("部署id:"+deploy.getId());System.out.println("部署名称:"+deploy.getName());}/*** 启动流程,测试信号中间Catching事件*/@Testpublic void startProcess() throws InterruptedException{//可根据id,key,message启动流程ProcessInstance parallel = runtimeService.startProcessInstanceByKey("myProcess_1");System.out.println("流程实例id:"+parallel.getId());System.out.println("流程定义id:"+parallel.getProcessDefinitionId());System.out.println("========================================================");List<Task> list = taskService.createTaskQuery().taskAssignee("user1").list();for (Task task : list) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());//完成支付任务System.out.println("task name:"+task.getName());taskService.complete(task.getId());}// 查询当前流程实例中订阅了“pay”信号的执行流List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(parallel.getId()).signalEventSubscriptionName("pay").list();for (Execution exe: executions) {System.out.println("执行流ID: " + exe);// 发送信号runtimeService.signalEventReceived("pay", exe.getId());}list = taskService.createTaskQuery().taskAssignee("user2").list();for (Task task : list) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());//完成发货任务System.out.println("task name:"+task.getName());taskService.complete(task.getId());}}
}

效果

1.4.6 信号中间Throwing事件

1.4.6.1 简介

信号中间Throwing事件用于抛出信号,当流程到达该事件时,会直接抛出信号,其他引用了相同信号的信号Catching事件会被触发。
设置activiti:async 代表同步异步执行, 可以控制捕获这个信号的信号中间Catching事件,将会在同一事务中完成,

1.4.6.2 设计流程图

例如有如下场景,流程启动后或产生两条执行流,一条用户支付成功后发送信号,第二条等待接收信号后进入发货节点。

流程文件bpmn

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1596013137129" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"><process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"><startEvent id="_2" name="开始"/><parallelGateway gatewayDirection="Unspecified" id="_3" name="ParallelGateway"/><userTask activiti:assignee="user1" activiti:exclusive="true" id="_4" name="支付"/><serviceTask activiti:class="com.yb.activiti6.delegate.NewOrderDelegate" activiti:exclusive="true" id="_5" name="生成订单"/><userTask activiti:assignee="user2" activiti:exclusive="true" id="_6" name="发货"/><intermediateCatchEvent id="_7" name="IntermediateCatchingEvent"><signalEventDefinition id="_7_ED_1" signalRef="SIG_1"/></intermediateCatchEvent><intermediateThrowEvent id="_8" name="IntermediateThrowingEvent"><signalEventDefinition id="_8_ED_1" signalRef="SIG_1"/></intermediateThrowEvent><parallelGateway gatewayDirection="Unspecified" id="_9" name="ParallelGateway"/><endEvent id="_10" name="结束"/><sequenceFlow id="_11" sourceRef="_2" targetRef="_3"/><sequenceFlow id="_12" sourceRef="_3" targetRef="_4"/><sequenceFlow id="_13" sourceRef="_3" targetRef="_5"/><sequenceFlow id="_14" sourceRef="_4" targetRef="_8"/><sequenceFlow id="_15" sourceRef="_8" targetRef="_9"/><sequenceFlow id="_16" sourceRef="_5" targetRef="_7"/><sequenceFlow id="_17" sourceRef="_7" targetRef="_6"/><sequenceFlow id="_18" sourceRef="_6" targetRef="_9"/><sequenceFlow id="_19" sourceRef="_9" targetRef="_10"/></process><signal id="SIG_1" name="pay"/><bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"><bpmndi:BPMNPlane bpmnElement="myProcess_1"><bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"><omgdc:Bounds height="32.0" width="32.0" x="-5.0" y="225.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"><omgdc:Bounds height="32.0" width="32.0" x="110.0" y="225.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"><omgdc:Bounds height="55.0" width="85.0" x="240.0" y="75.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"><omgdc:Bounds height="55.0" width="85.0" x="235.0" y="395.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6"><omgdc:Bounds height="55.0" width="85.0" x="475.0" y="395.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7"><omgdc:Bounds height="32.0" width="32.0" x="385.0" y="405.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_8" id="Shape-_8"><omgdc:Bounds height="32.0" width="32.0" x="510.0" y="85.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_9" id="Shape-_9"><omgdc:Bounds height="32.0" width="32.0" x="655.0" y="245.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_10" id="Shape-_10"><omgdc:Bounds height="32.0" width="32.0" x="755.0" y="245.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="_3" targetElement="_5"><omgdi:waypoint x="142.0" y="241.0"/><omgdi:waypoint x="235.0" y="422.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_3" targetElement="_4"><omgdi:waypoint x="142.0" y="241.0"/><omgdi:waypoint x="240.0" y="102.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_15" id="BPMNEdge__15" sourceElement="_8" targetElement="_9"><omgdi:waypoint x="542.0" y="101.0"/><omgdi:waypoint x="655.0" y="261.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_14" id="BPMNEdge__14" sourceElement="_4" targetElement="_8"><omgdi:waypoint x="325.0" y="102.5"/><omgdi:waypoint x="510.0" y="101.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_17" id="BPMNEdge__17" sourceElement="_7" targetElement="_6"><omgdi:waypoint x="417.0" y="421.0"/><omgdi:waypoint x="475.0" y="422.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_16" id="BPMNEdge__16" sourceElement="_5" targetElement="_7"><omgdi:waypoint x="320.0" y="422.5"/><omgdi:waypoint x="385.0" y="421.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_19" id="BPMNEdge__19" sourceElement="_9" targetElement="_10"><omgdi:waypoint x="687.0" y="261.0"/><omgdi:waypoint x="755.0" y="261.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_18" id="BPMNEdge__18" sourceElement="_6" targetElement="_9"><omgdi:waypoint x="560.0" y="422.5"/><omgdi:waypoint x="655.0" y="261.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_2" targetElement="_3"><omgdi:waypoint x="27.0" y="241.0"/><omgdi:waypoint x="110.0" y="241.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

测试类

package com.yb.activiti6;import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;
import java.util.List;/*** @version 1.0* @date 2020/7/23*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiDemoTest13 {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate IdentityService identityService;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate ProcessEngine processEngine;@Autowiredprivate HistoryService historyService;/*** 发布流程,测试信号中间Throwing事件* @throws IOException*/@Testpublic void deploymentProcesses_zip(){Deployment deploy = repositoryService.createDeployment().name("测试-信号中间Throwing事件-1")//创建流程名称.addClasspathResource("processes/activiti_signalCenter2.bpmn")//指定zip完成部署.addClasspathResource("processes/activiti_signalCenter2.png").deploy();System.out.println("部署id:"+deploy.getId());System.out.println("部署名称:"+deploy.getName());}/*** 启动流程,测试信号中间Throwing事件*/@Testpublic void startProcess() throws InterruptedException{//可根据id,key,message启动流程ProcessInstance parallel = runtimeService.startProcessInstanceByKey("myProcess_2");System.out.println("流程实例id:"+parallel.getId());System.out.println("流程定义id:"+parallel.getProcessDefinitionId());System.out.println("========================================================");List<Task> list = taskService.createTaskQuery().taskAssignee("user1").list();for (Task task : list) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());//完成支付任务System.out.println("task name:"+task.getName());taskService.complete(task.getId());}//暂停3秒System.out.println("暂停3秒");Thread.sleep(1000 * 3);list = taskService.createTaskQuery().taskAssignee("user2").list();for (Task task : list) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());//完成发货任务System.out.println("task name:"+task.getName());taskService.complete(task.getId());}}
}

效果

1.5 消息中间事件

1.5.1 消息事件的定义

消息事件是一种引用了消息定义的事件,与信号时间不同的是,消息只能只想一个接收人,不能像信号事件一样广播。
分为消息开始事件和中间消息事件。

1.5.2 触发消息事件

消息开始事件

ProcessInstance startProcessInstanceByMessage(String messageName);
ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object> processVariables);

消息中间事件

void messageEventReceived(String messageName, String executionId);
void messageEventReceived(String messageName, String executionId, HashMap<String, Object> processVariables);

1.5.3 查询消息事件的订阅

消息开始事件

ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().messageEventSubscription("msgStart").singleResult();

消息中间事件

Execution execution = runtimeService.createExecutionQuery().messageEventSubscriptionName("msg").processInstanceId(pi.getId()).singleResult();

1.5.4 消息中间事件的定义

消息中间事件作为流程一个节点使用

1.5.5 设计流程图

场景:用户支付成功后等待一分钟,商家发货

流程文件bpmn

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1596014623730" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"><message id="MSG_1" name="msg"/><process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"><startEvent id="_2" name="开始"/><intermediateCatchEvent id="_3" name="IntermediateCatchingEvent"><messageEventDefinition id="_3_ED_1" messageRef="MSG_1"/></intermediateCatchEvent><userTask activiti:exclusive="true" id="_4" name="用户任务"/><endEvent id="_5" name="结束"/><sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/><sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/><sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/></process><bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"><bpmndi:BPMNPlane bpmnElement="myProcess_1"><bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"><omgdc:Bounds height="32.0" width="32.0" x="-10.0" y="205.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"><omgdc:Bounds height="32.0" width="32.0" x="205.0" y="205.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"><omgdc:Bounds height="55.0" width="85.0" x="415.0" y="195.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"><omgdc:Bounds height="32.0" width="32.0" x="655.0" y="205.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3"><omgdi:waypoint x="22.0" y="221.0"/><omgdi:waypoint x="205.0" y="221.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4"><omgdi:waypoint x="237.0" y="221.0"/><omgdi:waypoint x="415.0" y="222.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5"><omgdi:waypoint x="500.0" y="222.5"/><omgdi:waypoint x="655.0" y="221.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram>
</definitions>

测试类

package com.yb.activiti6;import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;
import java.util.List;/*** @author liangjie@itcast.cn* @version 1.0* @date 2020/7/23*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiDemoTest14 {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate IdentityService identityService;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate ProcessEngine processEngine;@Autowiredprivate HistoryService historyService;/*** 发布流程,测试消息中间事件* @throws IOException*/@Testpublic void deploymentProcesses_zip(){Deployment deploy = repositoryService.createDeployment().name("测试-消息中间事件-1")//创建流程名称.addClasspathResource("processes/activiti_message.bpmn")//指定zip完成部署.addClasspathResource("processes/activiti_message.png").deploy();System.out.println("部署id:"+deploy.getId());System.out.println("部署名称:"+deploy.getName());}/*** 启动流程,测试消息中间事件*/@Testpublic void startProcess() throws InterruptedException{//可根据id,key,message启动流程ProcessInstance parallel = runtimeService.startProcessInstanceByKey("myProcess_1");System.out.println("流程实例id:"+parallel.getId());System.out.println("流程定义id:"+parallel.getProcessDefinitionId());System.out.println("========================================================");Execution msg = runtimeService.createExecutionQuery().messageEventSubscriptionName("msg").processInstanceId(parallel.getId()).singleResult();System.out.println("Execution: " + msg);runtimeService.messageEventReceived("msg",msg.getId());//暂停3秒System.out.println("暂停3秒");Thread.sleep(1000 * 3);List<Task> list = taskService.createTaskQuery().taskAssignee("msgUser").list();for (Task task : list) {System.out.println("任务ID:" + task.getId());System.out.println("任务名称:" + task.getName());System.out.println("任务创建时间:" + task.getCreateTime());System.out.println("任务委派人:" + task.getAssignee());System.out.println("流程实例ID:" + task.getProcessInstanceId());//完成发货任务System.out.println("task name:"+task.getName());taskService.complete(task.getId());}}
}

效果
向消息中间事件发送信息,触发消息中间事件,流程向下走到用户任务,完成任务,流程结束。

到此,定时器中间事件,信号中间事件,消息中间事件,测试完毕。

Activiti6--入门学习--中间事件相关推荐

  1. lua语言入门学习(八)项目初体验之玩家事件(2)

    lua语言入门学习 今天是实习的第二周,前辈给我的任务是熟悉playerevent中每个函数的基本功能. 文章目录 lua语言入门学习 前言 一.代码 1.代码功能自己简析 1.代码功能自己简析 2. ...

  2. python速成要多久2019-8-28_2019最全Python入门学习路线,不是我吹,绝对是最全

    近几年Python的受欢迎程度可谓是扶摇直上,当然了学习的人也是愈来愈多.一些学习Python的小白在学习初期,总希望能够得到一份Python学习路线图,小编经过多方汇总为大家汇总了一份Python学 ...

  3. 【python教程入门学习】Python实现自动玩贪吃蛇程序

    这篇文章主要介绍了通过Python实现的简易的自动玩贪吃蛇游戏的小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学一学 实现效果 先看看效果 这比我手动的快多了,而且是单机的,自动玩没惹 ...

  4. 零基础入门学习Python(33)-图形用户界面编程(GUI编程)EasyGui

    用户界面编程,即平时说的GUI(Graphical User Interface)编程,那些带有按钮.文本.输入框的窗口的编程 EasyGui是一个非常简单的GUI模块,一旦导入EasyGui模块,P ...

  5. 自学python推荐书籍2019-2019最全Python入门学习路线,不是我吹,绝对是最全

    近几年Python的受欢迎程度可谓是扶摇直上,当然了学习的人也是愈来愈多.一些学习Python的小白在学习初期,总希望能够得到一份Python学习路线图,小编经过多方汇总为大家汇总了一份Python学 ...

  6. 零基础python必背代码-零基础入门学习python 96集全

    零基础入门学习python 96集全 第000讲 愉快的开始(视频+课件)xa0 第001讲 我和Python第一次亲密接触(视频+课件)xa0 第002讲 用Python设第一个游戏(视频+课件+源 ...

  7. Python入门学习之异常处理机制

    异常即是一个事件,该事件会在程序执行过程中发生影响程序的正常执行.python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误.今天的Python入门学习课程就给大家讲解一下异常 ...

  8. JBox2d入门学习二 -----我的小鸟

    入门学习一当中我学会了如何定义并且创建一个世界,在世界当中定义并且创建一个刚体,并尝试给刚体一个力.最近比较忙..现在抽空实现了一个类似于愤怒小鸟的例子,先看看图吧.   贴代码,注解写的比较详细了, ...

  9. vue入门学习(基础篇)

    vue入门学习总结: vue的一个组件包括三部分:template.style.script. vue的数据在data中定义使用. 数据渲染指令:v-text.v-html.{{}}. 隐藏未编译的标 ...

  10. 零基础学python pdf-Python pdf(零基础入门学习Python)V1.0 最新版

    Python pdf(零基础入门学习Python)是一款功能强劲专业实用的Python电子书籍.想要零基础入门学习Python?那就快试试绿色先锋小编推荐的Python pdf最新版下载使用.由作者小 ...

最新文章

  1. makefile 中 =, :=, ?=, +=的区别
  2. 突破帧率天花板,超速全时视觉感知芯片重塑机器视觉技术体系
  3. 云计算将成为媒体融合发展与数字化变革的加速剂
  4. powershell设置了权限依旧无法运行脚本_没用的知识汇总+1 Windows 权限维持汇总...
  5. 实验 8 数组2 ok
  6. angular5 httpclient的示例实战
  7. 黑客与画家 第十四章
  8. c windows控制台输出颜色文字
  9. lua的元表metatable及元方法
  10. 解决 Angular 官网下载的库 Schematics 执行 npm run build 时遇到的编译错误
  11. 计算机教学难点重点,浅述如何解决小学信息技术教学中的重点、难点
  12. 水逆的 Google,或许应该向百度取个经?
  13. git pull没有更新成功_关于git pull时出现的问题及解决反思
  14. 基于ARM的智能灯光控制系统(11)状态更新
  15. 3dXXX Android,Android横竖屏 mdpi hdpi xhdpi xxhdpi xxxhdpi
  16. 魔芋粉的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  17. 软件测试助理利弊,女生做软件测试的利弊都有什么?
  18. Npm配置全局安装插件目录以及命令用法扩展
  19. 黑马程序员C++ 第二阶段 核心程序
  20. PHP根据汉字转换拼音

热门文章

  1. outlook2019登录126邮箱(imap)
  2. 计算机基础知识测试1,计算机基础知识测试试题及答案(网络)1
  3. BCH硬分叉,又一场“权力的游戏” | 8问大事件
  4. ESP分区和MSR分区下怎么重做GHOST系统
  5. AcWing 1107 魔板
  6. ubuntu安装nvidia驱动
  7. 奥克兰大学计算机科学与技术,奥克兰大学计算机科学专业怎么样?成为IT达人就靠它...
  8. Udacity Self-Driving数据集介绍
  9. v-model中修饰符lazy,number, trim的作用
  10. 网站受到流量攻击怎么办