(四)Activiti7 之实战应用

(外链:以下是一整套Activiti7 的内容,有兴趣的可以看看)


1 基本流程

1.1 流程图

此处每个 userTask 均需设置执行人
在这里插入图片描述

1.2 BPMN 文件
<?xml version="1.0" encoding="UTF-8"?>
<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:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.activiti.org/testm1625990337688" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="m1625990337688" name="" targetNamespace="http://www.activiti.org/testm1625990337688">
  <process id="zhanleai_approve_base" name="测试出差申请流程" processType="None" isClosed="false" isExecutable="true">
    <documentation />
    <startEvent id="_2" name="StartEvent" />
    <userTask id="_3" name="创建出差申请" activiti:assignee="张三" activiti:exclusive="true">
      <documentation />
      <extensionElements>
        <activiti:taskListener event="create" class="com.gh.maintenance.controller.activiti_example.ActivitiApproveListener" />
      </extensionElements>
    </userTask>
    <userTask id="_4" name="经理审批" activiti:assignee="李四" activiti:exclusive="true">
      <documentation />
      <extensionElements />
    </userTask>
    <userTask id="_5" name="总经理审批" activiti:assignee="老马" activiti:exclusive="true">
      <documentation />
      <extensionElements />
    </userTask>
    <userTask id="_6" name="财务审批" activiti:assignee="小王" activiti:exclusive="true" />
    <endEvent id="_7" name="EndEvent" />
    <sequenceFlow id="_8" sourceRef="_2" targetRef="_3" />
    <sequenceFlow id="_9" sourceRef="_4" targetRef="_5" />
    <sequenceFlow id="_10" sourceRef="_5" targetRef="_6" />
    <sequenceFlow id="_11" sourceRef="_6" targetRef="_7" />
    <sequenceFlow id="_12" sourceRef="_3" targetRef="_4" />
  </process>
  <bpmndi:BPMNDiagram id="Diagram-_1" name="New Diagram" documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0">
    <bpmndi:BPMNPlane bpmnElement="zhanleai_approve_base">
      <bpmndi:BPMNEdge id="BPMNEdge__12" bpmnElement="_12" sourceElement="_3" targetElement="_4">
        <di:waypoint x="650" y="13" />
        <di:waypoint x="700" y="13" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge__11" bpmnElement="_11" sourceElement="_6" targetElement="_7">
        <di:waypoint x="1110" y="13" />
        <di:waypoint x="1162" y="13" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge__10" bpmnElement="_10" sourceElement="_5" targetElement="_6">
        <di:waypoint x="960" y="13" />
        <di:waypoint x="1010" y="13" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge__9" bpmnElement="_9" sourceElement="_4" targetElement="_5">
        <di:waypoint x="800" y="13" />
        <di:waypoint x="860" y="13" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge__8" bpmnElement="_8" sourceElement="_2" targetElement="_3">
        <di:waypoint x="501" y="13" />
        <di:waypoint x="550" y="13" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="Shape-_2" bpmnElement="_2">
        <dc:Bounds x="465" y="-5" width="32" height="32" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="393" y="6" width="53" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_3" bpmnElement="_3">
        <dc:Bounds x="550" y="-27" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_4" bpmnElement="_4">
        <dc:Bounds x="700" y="-27" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_5" bpmnElement="_5">
        <dc:Bounds x="860" y="-27" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_6" bpmnElement="_6">
        <dc:Bounds x="1010" y="-27" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_7" bpmnElement="_7">
        <dc:Bounds x="1162" y="-5" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="1215" y="6" width="49" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
1.3 启动流程实例
/**
 * 启动流程实例
 * `act_hi_actinst`    流程实例执行历史信息
 * `act_hi_identitylink` 流程参与用户的历史信息
 * `act_hi_procinst`     流程实例的历史信息
 * `act_hi_taskinst`     流程任务的历史信息
 * `act_ru_execution`    流程执行信息
 * `act_ru_identitylink`  流程的正在参与用户信息
 * `act_ru_task`         流程当前任务信息
 */
@RequestMapping("/startProcess")
public String startProcess(String key) {

    // 1、根据流程定义的id启动流程
    ProcessInstance instance = runtimeService.startProcessInstanceByKey(key);
    // 2、输出内容
    log.info("流程定义ID:" + instance.getProcessDefinitionId());
    log.info("流程实例ID:" + instance.getId());
    log.info("当前活动的ID:" + instance.getActivityId());

    return "出差申请流程启动成功!";
}
1.4 查询个人待执行任务
/**
 * 查询个人待执行的任务
 */
@RequestMapping("/getUnfinishTaskList")
public List<Map<String,String>> getUnfinishTaskList(String key, String taskAssignee) {

    // 1、根据流程key 和 任务的负责人 查询任务
    List<Task> taskList = taskService.createTaskQuery()
            .processDefinitionKey(key) //流程Key
            .taskAssignee(taskAssignee)  //要查询的负责人
            .list();

    List<Map<String,String>> taskMapList = new ArrayList<>();
    // 2、输出
    for (Task task : taskList) {
        Map<String,String> taskMap = new HashMap<>();
        taskMap.put("processInstanceId",task.getProcessInstanceId());               //流程实例
        taskMap.put("id",task.getId());                                             //任务Id
        taskMap.put("assignee",task.getAssignee());                                 //任务负责人
        taskMap.put("name",task.getName());                                         //任务名称

        //取流程中设置的变量值(基本类型)
//            taskMap.put("taskAssignee", Objects.nonNull(taskService.getVariable(task.getId(),"出差申请人"))?taskService.getVariable(task.getId(),"出差申请人").toString():"");           //出差申请人
//            taskMap.put("days", Objects.nonNull(taskService.getVariable(task.getId(),"请假天数"))?taskService.getVariable(task.getId(),"请假天数").toString():"");                      //出差天数
//            taskMap.put("evaluateFee", Objects.nonNull(taskService.getVariable(task.getId(),"出差预计费用"))?taskService.getVariable(task.getId(),"出差预计费用").toString():"");        //出差预计费用
//            taskMap.put("startDate", Objects.nonNull(taskService.getVariable(task.getId(),"出差开始日期"))?taskService.getVariable(task.getId(),"出差开始日期").toString():"");          //出差开始日期

        //取流程中设置的变量值(bean类型)
        taskMap.put("approveInfo",Objects.nonNull(taskService.getVariable(task.getId(),"出差信息"))?JSONObject.toJSONString(taskService.getVariable(task.getId(),"出差信息")):"");

        taskMapList.add(taskMap);
    }

    return taskMapList;
}
1.5 完成个人任务
/**
 * (以张三创建出差申请为例)
 * 完成个人任务 : 创建出差申请
 * `act_ru_task` 这里的 '创建出差申请' 会变为 '经理审批'
 * 也就是也是下一个任务:  经理审批
 * `act_hi_taskinst` 这里的'创建出差申请'这条记录会有开始时间和结束时间
 * 然后还会增加一条记录 '经理审批'
 */
@RequestMapping("/completeTask")
public String completeTask(String key,String taskAssignee,String days,String evaluateFee, String startDate) {

    // 查找该负责人下所有的任务
    Task task = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskAssignee(taskAssignee)
            .singleResult();

    //设置流程变量(基本类型),前提是该流程实例必须未执行完成 —— 存在 act_ru_variable 表中,对应取值即可
//        taskService.setVariable(task.getId(), "请假人", taskAssignee);
//        taskService.setVariable(task.getId(), "出差天数",days);
//        taskService.setVariable(task.getId(), "出差预计费用", evaluateFee);
//        taskService.setVariable(task.getId(), "出差开始日期", startDate);

    //设置流程变量(JavaBean类型),前提是该流程实例必须未执行完成 —— 存在 act_ru_variable 表中,但是实际值存在 act_ge_bytearray 表中
    ApproveInfo approveInfo = ApproveInfo.builder()
            .taskAssignee(taskAssignee)
            .days(days)
            .evaluateFee(evaluateFee)
            .startDate(startDate)
            .build();

    taskService.setVariable(task.getId(),"出差信息",approveInfo);

    //执行流程
    taskService.complete(task.getId());

    return "当前," + task.getAssignee() + "已完成任务:" + task.getName() ;
}
1.6 根据任务ID完成任务
/**
 * 根据任务ID来完成任务
 */
@RequestMapping("/completeTaskByTaskId")
public String completeTaskByTaskId(String taskId) {
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    taskService.complete(taskId);
    return "当前已完成任务:" + task.getName() ;
}

2 排他网关

部分代码跟前面简单流程的有重复,我这部分就只贴流程图、bpmn文件和核心代码了

2.1 流程图

排他网关需要配置出口的表达式,然后通过 activiti 参数传值的形式会自动识别到该值,自动进行程序流转。
在这里插入图片描述

2.2 BPMN 文件
<?xml version="1.0" encoding="UTF-8"?>
<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:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.activiti.org/testm1625990337688" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="m1625990337688" name="" targetNamespace="http://www.activiti.org/testm1625990337688">
  <process id="zhanleai_approve_reject" name="测试出差申请流程" processType="None" isClosed="false" isExecutable="true">
    <documentation />
    <startEvent id="_1" name="流程开始">
      <documentation />
      <extensionElements />
      <outgoing>Flow_11ejhh5</outgoing>
    </startEvent>
    <userTask id="_2" name="创建出差申请" activiti:assignee="张三" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_08ru13p</incoming>
      <incoming>Flow_11ejhh5</incoming>
      <outgoing>Flow_1b2032e</outgoing>
    </userTask>
    <userTask id="_4" name="经理审批" activiti:assignee="李四" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_1fc8hv7</incoming>
      <outgoing>Flow_13ro4z7</outgoing>
    </userTask>
    <userTask id="_5" name="总经理审批" activiti:assignee="老马" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_13ro4z7</incoming>
      <outgoing>Flow_1jpug20</outgoing>
    </userTask>
    <userTask id="_7" name="财务审批" activiti:assignee="小王" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_09owxd3</incoming>
      <outgoing>Flow_1m3z2le</outgoing>
    </userTask>
    <sequenceFlow id="_11" sourceRef="_7" targetRef="_9" />
    <userTask id="_8" name="大老板审批" activiti:assignee="老赵" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_0p8i7yo</incoming>
      <outgoing>Flow_149ikim</outgoing>
      <outgoing>Flow_1h2q7h5</outgoing>
    </userTask>
    <sequenceFlow id="Flow_149ikim" sourceRef="_8" targetRef="_9" />
    <exclusiveGateway id="_6">
      <documentation />
      <incoming>Flow_1jpug20</incoming>
      <outgoing>Flow_09owxd3</outgoing>
      <outgoing>Flow_08ru13p</outgoing>
    </exclusiveGateway>
    <sequenceFlow id="Flow_1jpug20" sourceRef="_5" targetRef="_6" />
    <sequenceFlow id="Flow_09owxd3" name="同意审批" sourceRef="_6" targetRef="_7">
      <documentation />
      <conditionExpression xsi:type="tFormalExpression">${status==1}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="Flow_08ru13p" name="驳回申请" sourceRef="_6" targetRef="_2">
      <documentation />
      <conditionExpression xsi:type="tFormalExpression">${status==0}</conditionExpression>
    </sequenceFlow>
    <exclusiveGateway id="_3" name="">
      <documentation />
      <incoming>Flow_1b2032e</incoming>
      <outgoing>Flow_1fc8hv7</outgoing>
      <outgoing>Flow_0p8i7yo</outgoing>
    </exclusiveGateway>
    <sequenceFlow id="Flow_11ejhh5" sourceRef="_1" targetRef="_2" />
    <sequenceFlow id="Flow_1b2032e" sourceRef="_2" targetRef="_3">
      <documentation />
    </sequenceFlow>
    <sequenceFlow id="Flow_1fc8hv7" name="非特殊情况" sourceRef="_3" targetRef="_4">
      <documentation />
      <conditionExpression xsi:type="tFormalExpression">${status==0}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="Flow_0p8i7yo" name="特殊情况" sourceRef="_3" targetRef="_8">
      <documentation />
      <conditionExpression xsi:type="tFormalExpression">${status==1}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="Flow_1h2q7h5" sourceRef="_8" targetRef="_9">
      <documentation />
    </sequenceFlow>
    <sequenceFlow id="Flow_1m3z2le" sourceRef="_7" targetRef="_9" />
    <sequenceFlow id="Flow_13ro4z7" sourceRef="_4" targetRef="_5" />
    <endEvent id="_9" name="EndEvent">
      <documentation />
      <incoming>Flow_1h2q7h5</incoming>
      <incoming>Flow_1m3z2le</incoming>
      <terminateEventDefinition id="TerminateEventDefinition_1q47fr4" />
    </endEvent>
  </process>
  <bpmndi:BPMNDiagram id="Diagram-_1" name="New Diagram" documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0">
    <bpmndi:BPMNPlane bpmnElement="zhanleai_approve_reject">
      <bpmndi:BPMNEdge id="Flow_13ro4z7_di" bpmnElement="Flow_13ro4z7">
        <di:waypoint x="485" y="310" />
        <di:waypoint x="485" y="340" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1m3z2le_di" bpmnElement="Flow_1m3z2le">
        <di:waypoint x="485" y="640" />
        <di:waypoint x="485" y="750" />
        <di:waypoint x="622" y="750" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1h2q7h5_di" bpmnElement="Flow_1h2q7h5">
        <di:waypoint x="800" y="330" />
        <di:waypoint x="800" y="750" />
        <di:waypoint x="658" y="750" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0p8i7yo_di" bpmnElement="Flow_0p8i7yo">
        <di:waypoint x="640" y="125" />
        <di:waypoint x="640" y="190" />
        <di:waypoint x="800" y="190" />
        <di:waypoint x="800" y="250" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="698" y="165" width="44" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1fc8hv7_di" bpmnElement="Flow_1fc8hv7">
        <di:waypoint x="640" y="125" />
        <di:waypoint x="640" y="190" />
        <di:waypoint x="485" y="190" />
        <di:waypoint x="485" y="230" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="535" y="165" width="55" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1b2032e_di" bpmnElement="Flow_1b2032e">
        <di:waypoint x="640" y="30" />
        <di:waypoint x="640" y="75" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_11ejhh5_di" bpmnElement="Flow_11ejhh5">
        <di:waypoint x="640" y="-82" />
        <di:waypoint x="640" y="-50" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_08ru13p_di" bpmnElement="Flow_08ru13p">
        <di:waypoint x="460" y="480" />
        <di:waypoint x="360" y="480" />
        <di:waypoint x="360" y="-10" />
        <di:waypoint x="590" y="-10" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="353" y="225" width="44" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_09owxd3_di" bpmnElement="Flow_09owxd3">
        <di:waypoint x="485" y="505" />
        <di:waypoint x="485" y="560" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="478" y="523" width="45" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1jpug20_di" bpmnElement="Flow_1jpug20">
        <di:waypoint x="485" y="420" />
        <di:waypoint x="485" y="455" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="Shape-_2" bpmnElement="_1">
        <dc:Bounds x="622" y="-118" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="618" y="-147" width="44" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_3" bpmnElement="_2">
        <dc:Bounds x="590" y="-50" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_4" bpmnElement="_4">
        <dc:Bounds x="435" y="230" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_5" bpmnElement="_5">
        <dc:Bounds x="435" y="340" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_6" bpmnElement="_7">
        <dc:Bounds x="435" y="560" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_19lsvak_di" bpmnElement="_8">
        <dc:Bounds x="750" y="250" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Gateway_06brwuq_di" bpmnElement="_6" isMarkerVisible="true">
        <dc:Bounds x="460" y="455" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Gateway_1izdxic_di" bpmnElement="_3" isMarkerVisible="true">
        <dc:Bounds x="615" y="75" width="50" height="50" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="607" y="125" width="66" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_1y7rj7q_di" bpmnElement="_9">
        <dc:Bounds x="622" y="732" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="616" y="775" width="49" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
2.3 排他网关核心代码

其实也就是流程图配置参数,然后调用的时候从前端传进来,后端代码需要将这个放到 variableMap 对象中,activiti 会自动根据 status 的值来判断,从而自动流转。
在这里插入图片描述

3 指定任意节点

流程图和 bpmn 复用排他网关

3.1 核心流程点

用户在前端页面的操作如下:

  • 查询已执行的任务节点信息【前端】
  • 选择节点信息【前端】
  • 改变节点信息【前端】
3.2 根据流程实例ID查询已执行的任务节点信息
/**
 *  根据流程实例ID查询已执行的任务节点信息
 *
 *  act_hi_taskinst:历史流程任务表
 * 
 * @Date 2023/6/14 15:03
 * @Param [processInstanceId]
 * @return 
 **/
@RequestMapping("/getRunNodesByProcInstId")
public Map<String,String> getRunNodesByProcInstId(String processInstanceId) {
    Map<String,String> map = new LinkedHashMap();
    // 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
    List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(processInstanceId)
            .activityType("userTask")   //用户任务
            .finished()                 //已经执行的任务节点
            .orderByHistoricActivityInstanceEndTime()
            .asc()
            .list();

    // 已执行的节点ID集合
    if(Objects.nonNull(historicActivityInstanceList) && historicActivityInstanceList.size()>0){
        for (HistoricActivityInstance historicActivityInstance:historicActivityInstanceList){
            if(!map.containsKey(historicActivityInstance.getActivityId())){
                map.put(historicActivityInstance.getActivityId(),historicActivityInstance.getActivityName());
            }
        }
    }
    return map;
}
3.3 改变节点到指定节点
/**
 * 改变节点到指定节点
 * @param rejectNodeId 指定节点ID
 * @param processInstanceId 流程实例ID
 * @param assignee 负责人
 * @return
 */
@RequestMapping("/changeRunNode")
public String changeRunNode(String rejectNodeId, String processInstanceId, String assignee) {
    // 查找该负责人下所有的任务
    Task task = taskService.createTaskQuery()
            .processInstanceId(processInstanceId)
            .singleResult();

    //如果当前节点处理人不是该用户,就无法进行改变节点操作
    if (!assignee.equals(task.getAssignee())) {
        return "当前用户无法改变流程节点";
    }

    //获取当前节点
    String currActivityId = task.getTaskDefinitionKey();
    String processDefinitionId = task.getProcessDefinitionId();
    BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
    FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currActivityId);

    if (null == currFlow) {
        List<SubProcess> subProcessList = bpmnModel.getMainProcess().findFlowElementsOfType(SubProcess.class, true);
        for (SubProcess subProcess : subProcessList) {
            FlowElement flowElement = subProcess.getFlowElement(currActivityId);
            if (flowElement != null) {
                currFlow = (FlowNode) flowElement;
                break;
            }
        }
    }
    //获取目标节点
    FlowNode targetFlow = (FlowNode) bpmnModel.getFlowElement(rejectNodeId);

    //如果不是同一个流程(子流程)不能进行改变节点操作
    if (!(currFlow.getParentContainer().equals(targetFlow.getParentContainer()))) {
        return "不是同一个流程,无法进行改变节点操作";
    }

    //记录原活动方向
    List<SequenceFlow> oriSequenceFlows = Lists.newArrayList();
    oriSequenceFlows.addAll(currFlow.getOutgoingFlows());

    //清理活动方向
    currFlow.getOutgoingFlows().clear();

    //建立新的方向
    List<SequenceFlow> newSequenceFlows = Lists.newArrayList();
    SequenceFlow newSequenceFlow = new SequenceFlow();
    String uuid = UUID.randomUUID().toString().replace("-", "");
    newSequenceFlow.setId(uuid);
    newSequenceFlow.setSourceFlowElement(currFlow);  //原节点
    newSequenceFlow.setTargetFlowElement(targetFlow);  //目标节点
    newSequenceFlows.add(newSequenceFlow);
    currFlow.setOutgoingFlows(newSequenceFlows);

    //审批意见叠加
    //variables 审批意见     act_ru_variable  变量表
    Map<String, Object> variables = task.getProcessVariables();
    variables.put("status","2");
    variables.put("msg","资料填写有误,请重新填写!");

    //完成节点任务
    taskService.complete(task.getId(), variables);
    //恢复原方向
    currFlow.setOutgoingFlows(oriSequenceFlows);

    return "改变流程到指定节点,已完成!";
}

4 并行网关

4.1 流程图

在这里插入图片描述

4.2 BPMN 文件
<?xml version="1.0" encoding="UTF-8"?>
<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:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.activiti.org/testm1625990337688" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="m1625990337688" name="" targetNamespace="http://www.activiti.org/testm1625990337688">
  <process id="zhanleai_approve_parallel" name="测试出差申请流程" processType="None" isClosed="false" isExecutable="true">
    <documentation />
    <startEvent id="_1" name="流程开始">
      <documentation />
      <extensionElements />
      <outgoing>Flow_11ejhh5</outgoing>
    </startEvent>
    <userTask id="_2" name="创建出差申请" activiti:assignee="张三" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_08ru13p</incoming>
      <incoming>Flow_11ejhh5</incoming>
      <outgoing>Flow_1b2032e</outgoing>
    </userTask>
    <userTask id="_4" name="经理审批" activiti:assignee="李四" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_1fc8hv7</incoming>
      <outgoing>Flow_13ro4z7</outgoing>
    </userTask>
    <userTask id="_5" name="总经理审批" activiti:assignee="老马" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_13ro4z7</incoming>
      <outgoing>Flow_1jpug20</outgoing>
    </userTask>
    <userTask id="_7" name="财务审批" activiti:assignee="小王" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_09owxd3</incoming>
      <outgoing>Flow_1m3z2le</outgoing>
    </userTask>
    <sequenceFlow id="_11" sourceRef="_7" targetRef="_9" />
    <userTask id="_8" name="大老板审批" activiti:assignee="老赵" activiti:exclusive="true">
      <documentation />
      <extensionElements />
      <incoming>Flow_0p8i7yo</incoming>
      <outgoing>Flow_149ikim</outgoing>
      <outgoing>Flow_1h2q7h5</outgoing>
    </userTask>
    <sequenceFlow id="Flow_149ikim" sourceRef="_8" targetRef="_9" />
    <exclusiveGateway id="_6">
      <documentation />
      <incoming>Flow_1jpug20</incoming>
      <outgoing>Flow_09owxd3</outgoing>
      <outgoing>Flow_08ru13p</outgoing>
    </exclusiveGateway>
    <sequenceFlow id="Flow_1jpug20" sourceRef="_5" targetRef="_6" />
    <sequenceFlow id="Flow_09owxd3" name="同意审批" sourceRef="_6" targetRef="_7">
      <documentation />
      <conditionExpression xsi:type="tFormalExpression">${status==1}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="Flow_08ru13p" name="驳回申请" sourceRef="_6" targetRef="_2">
      <documentation />
      <conditionExpression xsi:type="tFormalExpression">${status==0}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="Flow_11ejhh5" sourceRef="_1" targetRef="_2" />
    <sequenceFlow id="Flow_1b2032e" sourceRef="_2" targetRef="_3">
      <documentation />
    </sequenceFlow>
    <sequenceFlow id="Flow_1fc8hv7" name="" sourceRef="_3" targetRef="_4">
      <documentation />
    </sequenceFlow>
    <sequenceFlow id="Flow_0p8i7yo" name="" sourceRef="_3" targetRef="_8">
      <documentation />
    </sequenceFlow>
    <sequenceFlow id="Flow_1h2q7h5" sourceRef="_8" targetRef="_9">
      <documentation />
    </sequenceFlow>
    <sequenceFlow id="Flow_1m3z2le" sourceRef="_7" targetRef="_9" />
    <sequenceFlow id="Flow_13ro4z7" sourceRef="_4" targetRef="_5" />
    <parallelGateway id="_3" name="">
      <documentation />
      <incoming>Flow_1b2032e</incoming>
      <outgoing>Flow_1fc8hv7</outgoing>
      <outgoing>Flow_0p8i7yo</outgoing>
    </parallelGateway>
    <endEvent id="_9" name="结束任务">
      <documentation />
      <incoming>Flow_1h2q7h5</incoming>
      <incoming>Flow_1m3z2le</incoming>
      <terminateEventDefinition id="TerminateEventDefinition_1gxwlzk" />
    </endEvent>
  </process>
  <bpmndi:BPMNDiagram id="Diagram-_1" name="New Diagram" documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0">
    <bpmndi:BPMNPlane bpmnElement="zhanleai_approve_parallel">
      <bpmndi:BPMNEdge id="Flow_13ro4z7_di" bpmnElement="Flow_13ro4z7">
        <di:waypoint x="485" y="310" />
        <di:waypoint x="485" y="340" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1m3z2le_di" bpmnElement="Flow_1m3z2le">
        <di:waypoint x="485" y="640" />
        <di:waypoint x="485" y="750" />
        <di:waypoint x="622" y="750" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1h2q7h5_di" bpmnElement="Flow_1h2q7h5">
        <di:waypoint x="840" y="350" />
        <di:waypoint x="840" y="750" />
        <di:waypoint x="658" y="750" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0p8i7yo_di" bpmnElement="Flow_0p8i7yo">
        <di:waypoint x="640" y="125" />
        <di:waypoint x="640" y="190" />
        <di:waypoint x="840" y="190" />
        <di:waypoint x="840" y="270" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="718" y="165" width="44" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1fc8hv7_di" bpmnElement="Flow_1fc8hv7">
        <di:waypoint x="640" y="125" />
        <di:waypoint x="640" y="190" />
        <di:waypoint x="485" y="190" />
        <di:waypoint x="485" y="230" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="535" y="165" width="55" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1b2032e_di" bpmnElement="Flow_1b2032e">
        <di:waypoint x="640" y="30" />
        <di:waypoint x="640" y="75" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_11ejhh5_di" bpmnElement="Flow_11ejhh5">
        <di:waypoint x="640" y="-82" />
        <di:waypoint x="640" y="-50" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_08ru13p_di" bpmnElement="Flow_08ru13p">
        <di:waypoint x="460" y="480" />
        <di:waypoint x="360" y="480" />
        <di:waypoint x="360" y="-10" />
        <di:waypoint x="590" y="-10" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="353" y="225" width="44" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_09owxd3_di" bpmnElement="Flow_09owxd3">
        <di:waypoint x="485" y="505" />
        <di:waypoint x="485" y="560" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="478" y="523" width="45" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1jpug20_di" bpmnElement="Flow_1jpug20">
        <di:waypoint x="485" y="420" />
        <di:waypoint x="485" y="455" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="Shape-_2" bpmnElement="_1">
        <dc:Bounds x="622" y="-118" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="618" y="-147" width="44" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_3" bpmnElement="_2">
        <dc:Bounds x="590" y="-50" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_4" bpmnElement="_4">
        <dc:Bounds x="435" y="230" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_5" bpmnElement="_5">
        <dc:Bounds x="435" y="340" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_6" bpmnElement="_7">
        <dc:Bounds x="435" y="560" width="100" height="80" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_19lsvak_di" bpmnElement="_8">
        <dc:Bounds x="790" y="270" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Gateway_06brwuq_di" bpmnElement="_6" isMarkerVisible="true">
        <dc:Bounds x="460" y="455" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Gateway_02haxla_di" bpmnElement="_3">
        <dc:Bounds x="615" y="75" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_1mmhxvi_di" bpmnElement="_9">
        <dc:Bounds x="622" y="732" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="619" y="775" width="44" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
4.3 核心动作

并行网关没有什么特别的设置,直接画流程图,正常流转就能结束。但是需要注意一点,必须将结束事件设置为:Terminate End Event,不然会出现整个流程无法结束的情况。
在这里插入图片描述

5 任务监听器

  • create:任务创建后触发
  • Assignment:任务分配后触发
  • Delete:任务完成后触发
  • All:所有任务都触发
5.1 流程图

针对某个 userTask 设置监听器,选择“创建后”,java类设置全路径为:com.gh.maintenance.controller.activiti_example.ActivitiApproveListener
在这里插入图片描述

5.2 BPMN 文件
<?xml version="1.0" encoding="UTF-8"?>
<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:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.activiti.org/testm1625990337688" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="m1625990337688" name="" targetNamespace="http://www.activiti.org/testm1625990337688">
  <process id="zhanleai_approve_listener" name="测试出差申请流程" processType="None" isClosed="false" isExecutable="true">
    <documentation />
    <startEvent id="_2" name="StartEvent" />
    <userTask id="_3" name="创建出差申请" activiti:assignee="张三" activiti:exclusive="true">
      <documentation />
      <extensionElements>
        <activiti:taskListener event="create" class="com.gh.maintenance.controller.activiti_example.ActivitiApproveListener" />
      </extensionElements>
    </userTask>
    <userTask id="_4" name="经理审批" activiti:assignee="李四" activiti:exclusive="true">
      <documentation />
      <extensionElements />
    </userTask>
    <userTask id="_5" name="总经理审批" activiti:assignee="老马" activiti:exclusive="true">
      <documentation></documentation>
      <extensionElements />
    </userTask>
    <userTask id="_6" name="财务审批" activiti:assignee="小王" activiti:exclusive="true">
      <documentation></documentation>
      <extensionElements />
    </userTask>
    <endEvent id="_7" name="EndEvent" />
    <sequenceFlow id="_8" sourceRef="_2" targetRef="_3" />
    <sequenceFlow id="_9" sourceRef="_4" targetRef="_5" />
    <sequenceFlow id="_10" sourceRef="_5" targetRef="_6" />
    <sequenceFlow id="_11" sourceRef="_6" targetRef="_7" />
    <sequenceFlow id="_12" sourceRef="_3" targetRef="_4" />
  </process>
  <bpmndi:BPMNDiagram id="Diagram-_1" name="New Diagram" documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0">
    <bpmndi:BPMNPlane bpmnElement="zhanleai_approve_listener">
      <bpmndi:BPMNEdge id="BPMNEdge__12" bpmnElement="_12" sourceElement="_3" targetElement="_4">
        <di:waypoint x="477.5" y="160" />
        <di:waypoint x="477.5" y="195" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge__11" bpmnElement="_11" sourceElement="_6" targetElement="_7">
        <di:waypoint x="481" y="440" />
        <di:waypoint x="481" y="510" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge__10" bpmnElement="_10" sourceElement="_5" targetElement="_6">
        <di:waypoint x="480" y="340" />
        <di:waypoint x="480" y="385" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge__9" bpmnElement="_9" sourceElement="_4" targetElement="_5">
        <di:waypoint x="477.5" y="250" />
        <di:waypoint x="477.5" y="285" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="BPMNEdge__8" bpmnElement="_8" sourceElement="_2" targetElement="_3">
        <di:waypoint x="481" y="27" />
        <di:waypoint x="481" y="105" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="0" height="0" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="Shape-_2" bpmnElement="_2">
        <dc:Bounds x="465" y="-5" width="32" height="32" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="32" height="32" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_3" bpmnElement="_3">
        <dc:Bounds x="435" y="105" width="85" height="55" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_4" bpmnElement="_4">
        <dc:Bounds x="435" y="195" width="85" height="55" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_5" bpmnElement="_5">
        <dc:Bounds x="435" y="285" width="85" height="55" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_6" bpmnElement="_6">
        <dc:Bounds x="440" y="385" width="85" height="55" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="85" height="55" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Shape-_7" bpmnElement="_7">
        <dc:Bounds x="465" y="510" width="32" height="32" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="0" y="0" width="32" height="32" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
5.3 任务监听器核心代码
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;

/**
 * @Description: 监听器 【create-任务创建后触发  Assignment-任务分配后触发  Delete-任务完成后触发  All-所有任务都触发】
 *
 * @Author: zhanleai
 * @Date:2023/6/16 11:37
 */
@Slf4j
public class ActivitiApproveListener implements TaskListener {
    @Override
    public void notify(DelegateTask delegateTask) {
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>此监听器触发机制为:"+delegateTask.getEventName());
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>触发监听任务ID值为:"+delegateTask.getId());
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>负责人为:"+delegateTask.getAssignee());
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>任务名称"+delegateTask.getName());
    }
}


(外链:以下是一整套Activiti7 的内容,有兴趣的可以看看)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "Activiti 实战 pdf" 是一本介绍Activiti流程引擎实战的电子书。该书主要介绍了Activiti的架构、流程设计、流程部署、活动和事件处理、任务管理、用户管理、历史记录、定时任务等内容。通过该书的学习,读者可以了解Activiti的基本原理,掌握Activiti的基本使用方法,在实际项目中使用Activiti开发高效、可靠的业务流程应用Activiti是一个开源的BPM流程引擎,它实现了BPMN 2.0规范,并提供了基于Java和Spring的API和服务。Activiti可以方便地与各种应用和平台集成,例如Spring、Spring Boot、Camunda、Drools、MuleSoft等。Activiti被广泛应用于企业级业务流程管理、工作流、电子商务、人力资源、金融等领域。 该书的作者是Tijs Rademakers、Ronald van Luttikhuizen、Jos Dirksen等人,他们是Activiti架构师和专家。该书除了提供详尽的文档和指导外,还包含了一些实践案例和示例代码,可以帮助读者更好地理解和运用Activiti。无论是初学者还是有经验的开发者,都可以从该书中获得收益,它是一本不可多得的Activiti学习资源。 ### 回答2: Activiti 实战 PDF 是一本关于 Activiti 工作流引擎的实践指南书籍,该书适合对工作流引擎有一定了解并希望使用 Activiti 实现工作流的开发人员和架构师阅读。 该书主要涵盖了 Activiti 的基本概念和使用方法,包括工作流引擎的基础知识、流程定义和流程实例的创建、流程图的绘制、任务分配和处理、流程监控和报表等。 这本书通过丰富的实例代码和图示,展示了 Activiti 在实际项目中的应用场景,并详细介绍了如何配置和使用 Activiti,如如何在 Java 代码中使用 Activiti API,如何使用 Spring 集成 Activiti 等。 此外,该书还包含了一些高级的话题,如如何自定义 Activiti 服务、如何在 Activiti 中使用规则引擎和消息中间件等,这些内容对于需要深入了解 Activiti 的开发人员来说具有很大的价值。 总之,Activiti 实战 PDF 对于掌握 Activiti 工作流引擎的开发人员和架构师来说是一本非常实用的实践指南,它不仅能够帮助读者掌握 Activiti 的基本概念和使用方法,还能够帮助他们实现更加复杂的工作流场景。 ### 回答3: Activiti 实战 PDF 是一本关于 Activiti 工作流引擎的实战指南,主要面向开发者和系统管理员,并以实际案例为基础,介绍了 Activiti 的核心概念、基本流程的构建以及高级特性等内容。 本书由熟悉 Activiti 的领域专家撰写,详细介绍了 Activiti 的工作原理、配置和使用方式。其中涵盖了多种流程设计方法,包括界面设计、BPMN 规范和 XML 定义等,并结合实际案例演示了如何使用 Activiti 构建自定义流程应用。 此外,本书还阐述了 Activiti 中的用户、任务、表单、数据和事件等概念,以及如何使用 Activiti Explorer 管理和监控流程的运行与执行情况。最后,本书还介绍了使用 Activiti 进行流程自动化部署、管理与维护的技巧和方法。 总的来说,Activiti 实战 PDF 为初学者和高级用户提供了深入学习 Activiti 工作流引擎的最佳实践方法,帮助用户将其应用于实际开发项目中,提高工作效率和流程管理的可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值