springboot integra la configuración paralela en serie de tareas de múltiples instancias de Activiti

Esta publicación de blog se refiere a la siguiente
tarea de instancias múltiples de activiti de blogger
[nèng - Activiti6] Introducción a Activiti6 (7) - Tarea de instancias múltiples
Combate real de Activiti (5): contraseña

La diferencia entre serie de instancias múltiples y paralelo

  1. Paralelo significa proceder al mismo tiempo, por ejemplo, si se asigna una tarea a n personas para su procesamiento, estas n personas recibirán la tarea al mismo tiempo y podrán procesarla al mismo tiempo sin verse afectadas por cada una de ellas.
    El nodo act_ru_task configurado con múltiples instancias tendrá múltiples datos de tareas.

  2. En serie significa que después de que una persona completa el trabajo o tarea, otra persona lo procesa hasta que se completa por completo, y cada tarea depende de la finalización de la tarea anterior.
    El nodo act_ru_task configurado con múltiples instancias siempre tiene solo un dato para este nodo.

Uno, configuración paralela bpmn

Un proceso sencillo para configurar el paralelismo en las tareas del usuario. (No hablaré de serie, si entiendes paralelo, también entiendes serie)

diagrama bpmn

inserte la descripción de la imagen aquí

xml de instancia de flujo de trabajo

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
  <process id="cq" name="产权工作流" isExecutable="true">
    <documentation>产权会签</documentation>
    <startEvent id="sid-start" name="开始会签"/>
    <userTask id="sid-task2" name="村民表决" activiti:assignee="${assignee}">
      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee">
        <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.5 || pass == true}</completionCondition>
      </multiInstanceLoopCharacteristics>
    </userTask>
    <userTask id="sid-task3" name="镇街审核" activiti:assignee="${assignee}"/>
    <endEvent id="sid-end" name="结束"/>
    <sequenceFlow id="sid-45a0cbe9-6112-4a07-b95c-62545a0171fa" sourceRef="sid-task3" targetRef="sid-end"/>
    <userTask id="sid-task1" name="填写申请资料" activiti:assignee="${assignee}"/>
    <sequenceFlow id="sid-661add14-02b3-4794-b440-edf1798c82a8" sourceRef="sid-start" targetRef="sid-task1"/>
    <sequenceFlow id="sid-19cfbdbf-01f9-4c8d-9614-31300dbe461a" sourceRef="sid-task1" targetRef="sid-task2"/>
    <exclusiveGateway id="sid-gateway"/>
    <sequenceFlow id="sid-c8eeefa1-2f24-4daf-9e15-90d462529992" sourceRef="sid-task2" targetRef="sid-gateway"/>
    <sequenceFlow id="sid-d054bb13-bf87-46e2-9649-5044b9416f6d" sourceRef="sid-gateway" targetRef="sid-task3" name="通过">
      <conditionExpression xsi:type="tFormalExpression">${pass==true}</conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-92a9d1a2-f73c-46de-b493-44a0b56e3e21" sourceRef="sid-gateway" targetRef="sid-task1" name="拒绝">
      <conditionExpression xsi:type="tFormalExpression">${pass=false}</conditionExpression>
    </sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_cq">
    <bpmndi:BPMNPlane bpmnElement="cq" id="BPMNPlane_cq">
      <bpmndi:BPMNShape id="shape-85388f7c-e845-43d0-b84b-6679cefb3110" bpmnElement="sid-start">
        <omgdc:Bounds x="-110.0" y="-15.0" width="30.0" height="30.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-3fab3d96-c577-44b1-a1b3-f6a6249a14bc" bpmnElement="sid-task2">
        <omgdc:Bounds x="195.0" y="-40.0" width="100.0" height="80.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-08995250-1075-40e2-b92c-a5dd140fbcd5" bpmnElement="sid-task3">
        <omgdc:Bounds x="475.0" y="-40.0" width="100.0" height="80.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-d8775c65-537f-49d1-a05a-b65fef4d4ee8" bpmnElement="sid-end">
        <omgdc:Bounds x="650.0" y="-15.0" width="30.0" height="30.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="edge-2d6eaf90-8343-4483-92c6-716781168133" bpmnElement="sid-45a0cbe9-6112-4a07-b95c-62545a0171fa">
        <omgdi:waypoint x="575.0" y="0.0"/>
        <omgdi:waypoint x="650.0" y="0.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="shape-ed57a314-acc1-410e-8cd0-e6cc1c022668" bpmnElement="sid-task1">
        <omgdc:Bounds x="0.0" y="-40.0" width="100.0" height="80.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="edge-62841ec0-6a53-44ff-a21f-529024508c08" bpmnElement="sid-661add14-02b3-4794-b440-edf1798c82a8">
        <omgdi:waypoint x="-80.0" y="0.0"/>
        <omgdi:waypoint x="0.0" y="0.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-92c7b154-d003-40cd-b8b4-cd1a25fbc533" bpmnElement="sid-19cfbdbf-01f9-4c8d-9614-31300dbe461a">
        <omgdi:waypoint x="100.0" y="0.0"/>
        <omgdi:waypoint x="195.0" y="0.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="shape-3a522932-3abf-4cf8-977f-e6dd0a5abdac" bpmnElement="sid-gateway">
        <omgdc:Bounds x="365.0" y="-20.0" width="40.0" height="40.0"/>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="edge-f35924a4-0134-4585-8933-81aa7e821c26" bpmnElement="sid-c8eeefa1-2f24-4daf-9e15-90d462529992">
        <omgdi:waypoint x="295.0" y="0.0"/>
        <omgdi:waypoint x="365.0" y="0.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-1ea70a14-127d-4ddd-8339-b389d61b3654" bpmnElement="sid-d054bb13-bf87-46e2-9649-5044b9416f6d">
        <omgdi:waypoint x="405.0" y="0.0"/>
        <omgdi:waypoint x="475.0" y="0.0"/>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-3cc368c6-0af2-4635-a4d4-27358568222b" bpmnElement="sid-92a9d1a2-f73c-46de-b493-44a0b56e3e21">
        <omgdi:waypoint x="385.0" y="-20.0"/>
        <omgdi:waypoint x="385.0" y="-127.50001"/>
        <omgdi:waypoint x="55.0" y="-127.500015"/>
        <omgdi:waypoint x="55.0" y="-40.0"/>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

Instrucciones de configuración de instancias múltiples

<userTask id="sid-task2" name="村民表决" activiti:assignee="${assignee}">
      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee">
        <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.5 || pass == true}</completionCondition>
      </multiInstanceLoopCharacteristics>
</userTask>
  1. isSequential falso es paralelo, verdadero es serial
  2. completeCondition es el juicio condicional de múltiples instancias
  3. pass es mi variable personalizada, otras son variables integradas

Descripción de la variable incorporada del atributo de instancia múltiple, las variables en el elemento completeCondition están básicamente integradas y no es necesario pasar parámetros, excepto que yo personalizo el paso, por lo que debe pasar parámetros

1.nrOfActiveInstances La cantidad de instancias actualmente activas, es decir, la cantidad de instancias que aún no se han completado. El número de instancias actualmente activas, siempre 1 para la ejecución secuencial (en serie) de instancias múltiples.

2.loopCounter tiene tiempos de bucle

3. nrOfInstances número total de instancias

4.nrOfCompletedInstances El número de instancias completadas

Entonces, el siguiente código significa que más de la mitad del número total de participantes puede pasar y fluir al siguiente nodo.

<completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.5 || pass == true}

Fuera de tema: loopCardinality se repite dos veces antes de fluir al siguiente nodo, generalmente no se escribirá hasta morir

<multiInstanceLoopCharacteristics isSequential="true">
  <loopCardinality>2</loopCardinality>
</multiInstanceLoopCharacteristics>

No usé loopCardinality
inserte la descripción de la imagen aquí

2. Inicio del proceso

1. Proceso de implementación

//使用RepositoryService进行部署
 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 RepositoryService repositoryService = processEngine.getRepositoryService();
 //使用RepositoryService进行部署
 DeploymentBuilder builder = repositoryService.createDeployment();
 Deployment deployment = builder
                             .addClasspathResource("bpmn/cq/cq.bpmn20.xml")
                             .addClasspathResource("bpmn/cq/cq.png")
                             .name("产权工作流").deploy();


 //输出部署信息
 System.out.println("流程部署id:" + deployment.getId());
 System.out.println("流程部署名称:" + deployment.getName());

Una vez que la implementación sea exitosa, puede ver los datos en la siguiente tabla, el núcleo es act_re_procdef (definición del proceso implementado

act_ge_bytearray (definición de proceso genérica y tabla de recursos de proceso)
inserte la descripción de la imagen aquí

act_re_deployment (información de la unidad de implementación)
inserte la descripción de la imagen aquí

act_re_procdef (definición de proceso implementado)
inserte la descripción de la imagen aquí

2. Proceso de inicio

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();

Map<String, Object> variables = new HashMap<>();
variables.put("assignee","小强");
//根据流程定义Id启动流程
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("cq",variables);

//输出实例信息
System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例id:" + processInstance.getId());
System.out.println("当前活动Id:" + processInstance.getActivityId());

3. Configuración dinámica

Descripción de parámetros:

activiti:assignee="${assignee}"
activiti:elementVariable="assignee" #多实例任务依赖上面的配置${
    
    assignee}
activiti:collection="assigneeList" #你需要传参的变量

ejemplo xm

<userTask id="sid-task2" name="村民表决" activiti:assignee="${assignee}">
      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee">
        <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.5 || pass == true}</completionCondition>
      </multiInstanceLoopCharacteristics>
</userTask>

realizar tareas

 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        TaskService taskService = processEngine.getTaskService();
        //根据流程key和任务的负责人查询任务并选择其中的一个任务处理,这里用的
        //是singleResult返回一条,真实环境中是通过步骤5中查询出所有的任务,然后在页面上选择一个任务进行处理.
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("cq") //流程Key
                .taskAssignee("小强")  //要查询的负责人
                .singleResult();

        if(task!=null){
    
    
            Map<String, Object> variables = new HashMap<>();
            List<String> list = Arrays.asList("小红", "小张", "小李");
            variables.put("assigneeList", list);
            //完成任务,参数:任务id
            taskService.complete(task.getId(),variables);

            System.out.println("任务执行成功");

        }else {
    
    
            System.out.println("无任务执行");
        }

Debido a que configuré paralelo y definí Xiaohong, Xiaozhang y Xiaoli, cuando el flujo va al nodo de instancias múltiples, verá los datos de tres tareas. Si es en serie, siempre verá solo un dato, etc. ejecuta, aparecerán otros datos de la tarea.

inserte la descripción de la imagen aquí

Cuando el flujo se transfiere a un nodo de instancias múltiples, puede probarlo usted mismo. Cuando más de la mitad de los usuarios se ejecutan o pasan = verdadero, lo transferirá al siguiente nodo.

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        TaskService taskService = processEngine.getTaskService();
        //根据流程key和任务的负责人查询任务并选择其中的一个任务处理,这里用的
        //是singleResult返回一条,真实环境中是通过步骤5中查询出所有的任务,然后在页面上选择一个任务进行处理.
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("cq") //流程Key
                .taskAssignee("小张")  //要查询的负责人
                .singleResult();

        if(task!=null){
    
    
            //Map<String, Object> variables = new HashMap<>();

            //variables.put("pass", true);

            //完成任务,参数:任务id
            //taskService.complete(task.getId(),variables);

            taskService.complete(task.getId());

            System.out.println("任务执行成功");

        }else {
    
    
            System.out.println("无任务执行");
        }

Cuatro Resumen

PD: Si hay decenas, cientos o miles de personas que firmarán, no se recomienda usarlo, de lo contrario, será difícil solucionar el problema si algo sale mal.
El programa anterior ha resuelto problemas de uso común sobre firma, registro, reducción de signos, cierre de sesión, configuración de peso y configuración de condiciones de pase personalizadas (condición de pase personalizado).

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

Si utiliza el modo serie para operar, la variable nrOfActiveInstances siempre es 1, porque la operación +1 solo se realizará en paralelo.

Supongo que te gusta

Origin blog.csdn.net/qq407995680/article/details/132597980
Recomendado
Clasificación