Noções básicas do fluxo de trabalho do Activiti

1. Conheça a Activiti

Endereço do site oficial: https://www.activiti.org/
O projeto Activiti é uma nova plataforma BPM de código aberto baseada na licença Apache, construída do zero e tem como objetivo fornecer suporte ao novo padrão BPMN 2.0, incluindo suporte ao Object Management Group (OMG). ), proporcionando implementação técnica diante de novas oportunidades tecnológicas, como interoperabilidade e arquitetura em nuvem.

1. Crie um mecanismo de fluxo de trabalho

1. Introduzir dependências

 <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
    </dependency>
     <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.6</version>
    </dependency>

    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-engine</artifactId>
      <version>6.0.0</version>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>6.0.0</version>
    </dependency>
    <!--bpmn 模型处理-->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-bpmn-model</artifactId>
      <version>6.0.0</version>
    </dependency>
    <!--bpmn 转换-->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-bpmn-converter</artifactId>
      <version>6.0.0</version>
    </dependency>
    <!--bpmn json数据转换-->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-json-converter</artifactId>
      <version>6.0.0</version>
    </dependency>
    <!--bpmn 布局-->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-bpmn-layout</artifactId>
      <version>6.0.0</version>
      <scope>test</scope>
    </dependency>
    <!--activiti 云支持-->
    <dependency>
      <groupId>org.activiti.cloud</groupId>
      <artifactId>activiti-cloud-services-api</artifactId>
      <version>7.0.0.Beta1</version>
    </dependency>

    <!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.41</version>
    </dependency>
    <!--mybatis-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.4</version>
    </dependency>
    <!--数据库连接池-->
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.4</version>
    </dependency>
  </dependencies>

2. Escreva o arquivo de configuração de log

log4j.rootLogger=INFO,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.conversionPattern=%d %p [%c] - %m%n

3. Escreva o arquivo de configuração de atividades

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--在默认方式下,bean的id固定为:processEngineConfiguration-->

    <!--配置数据库连接池-->
    <bean id="database" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///act?characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="12345678"/>
        <property name="maxActive" value="3"/>
        <property name="maxIdle" value="1"/>
    </bean>

    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!--配置数据库信息-->
        <!--<property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>-->
        <!--<property name="jdbcUrl" value="jdbc:mysql:///act?characterEncoding=UTF-8"/>-->
        <!--<property name="jdbcUsername" value="root"/>-->
        <!--<property name="jdbcPassword" value="12345678"/>-->

        <!--使用数据库连接池-->
        <property name="dataSource" ref="database"/>
        <!--activiti数据库表生成策略,true表示数据表如果存在直接使用,如果不存在则创建-->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>

</beans>

4. Crie classes de teste e gere tabelas de banco de dados

package com.yzs;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.junit.Test;

public class ActivitiTest {
    
    

    //使用activiti提供的两种方式来创建数据表
    @Test
    public void testCreateDbTable(){
    
    
        //默认创建方式
        //ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //一般创建方式
        ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml", "processEngineConfiguration");
        ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
        System.out.println(processEngine);
    }
}

2. Primeiros passos com o Activiti

Crie um processo de fluxo de trabalho de atividades:

  • Defina o processo: De acordo com a especificação BPMN, use a ferramenta de definição de processo e use símbolos de processo para descrever todo o processo.
  • Processo de implantação: carregue o arquivo de definição de processo desenhado no banco de dados e gere os dados da tabela.
  • Inicie o processo: Use o código java para operar o conteúdo da tabela do banco de dados.
Nome do Serviço função de serviço
Serviço de Repositório Gestão de recursos
RuntimeService Classe de gerenciamento de operação de processo
TaskService Gerenciamento de tarefas
Serviço de histórico Gestão histórica
Gerente de Serviço Aula de gerenciamento de motor

O código do caso de teste é o seguinte:

package com.yzs;

import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.*;
import java.util.List;
import java.util.zip.ZipInputStream;

public class ActivitiDemo {
    
    

    /**
     * 测试流程部署
     */
    @Test
    public void testDeployment(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3、使用service进行流程部署,定义流程名字,将bpmn部署到数据库中
        Deployment deploy = repositoryService.createDeployment()
                .name("出差申请流程")
                .addClasspathResource("bpmn/evection.bpmn")
                .deploy();
        //4、输出部署信息
        System.out.println("流程部署id="+deploy.getId());
        System.out.println("流程部署名字="+deploy.getName());
    }

    /**
     * 启动流程实例
     */
    @Test
    public void testStartProcess(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //3、根据流程定义的id启动流程
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection");
        //4、输出流程信息
        System.out.println("流程定义id="+instance.getProcessDefinitionId());
        System.out.println("流程实例id="+instance.getId());
        System.out.println("当前活动id="+instance.getActivityId());
    }

    /**
     * 查询个人待执行任务
     */
    @Test
    public void testFindPersonalTaskList(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        //3、使用流程key、任务的负责人来查询任务
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey("myEvection")
                .taskAssignee("zhangsan")
                .list();
        //4、输出任务信息
        for (Task task:taskList){
    
    
            System.out.println("流程实例id="+task.getProcessInstanceId());
            System.out.println("任务id="+task.getId());
            System.out.println("任务名称="+task.getName());
            System.out.println("任务负责人="+task.getAssignee());
        }
    }

    /**
     * 完成个人任务
     */
    @Test
    public void completTask(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        //3、根据任务id完成任务
        taskService.complete("2505");
    }

    /**
     * 使用zip包进行批量部署
     */
    @Test
    public void deployProcessByZip(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3、流程部署 读取资源包文件,构造成inputStream
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/evection.zip");
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        Deployment deploy = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();
        //4、输出部署信息
        System.out.println("流程部署id="+deploy.getId());
        System.out.println("流程部署名字="+deploy.getName());
    }

    /**
     * 查询流程定义
     */
    @Test
    public void queryProcessDefinition(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3、获取ProcessDefinitionQuery对象
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.processDefinitionKey("myEvection")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();
        //4、输出信息
        for (ProcessDefinition processDefinition:processDefinitionList){
    
    
            System.out.println("流程定义id="+processDefinition.getId());
            System.out.println("流程定义名称="+processDefinition.getName());
            System.out.println("流程定义key="+processDefinition.getKey());
            System.out.println("流程定义版本="+processDefinition.getVersion());
        }
    }

    /**
     * 删除流程部署信息
     */
    @Test
    public void deleteDeployment(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3、通过部署id来删除
        String deploymentId = "1";
        repositoryService.deleteDeployment(deploymentId);

        //当前流程如果尚未完成,想要删除需要使用级联方式
        //repositoryService.deleteDeployment(deploymentId,true);
    }

    /**
     * 下载资源文件
     */
    @Test
    public void getDeployment() throws IOException {
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3、获取查询对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("myEvection")
                .singleResult();
        //4、通过流程定义信息,获取部署id、png名字、bpmn名字
        String deploymentId = processDefinition.getDeploymentId();
        String pngName = processDefinition.getDiagramResourceName();
        String bpmnName = processDefinition.getResourceName();
        //5、传递部署id,读取资源信息(png、bpmn)
        InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);
        InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);
        //6、构造OutputStream
        File pngFile = new File("d:/evection.png");
        File bpmnFile = new File("d:/evection.bpmn");
        FileOutputStream pngOutput = new FileOutputStream(pngFile);
        FileOutputStream bpmnOutput = new FileOutputStream(bpmnFile);
        //7、输入流与输出流的转换
        IOUtils.copy(pngInput,pngOutput);
        IOUtils.copy(bpmnInput,bpmnOutput);
        //8、关闭流
        pngOutput.close();
        bpmnOutput.close();
        pngInput.close();
        bpmnInput.close();
    }

    /**
     * 查看历史信息
     */
    @Test
    public void findHistoryInfo(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取HistoryService
        HistoryService historyService = processEngine.getHistoryService();
        //3、获取actinst表查询对象
        HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
        //4、查询表内容
        List<HistoricActivityInstance> list = historicActivityInstanceQuery.processInstanceId("2501").orderByHistoricActivityInstanceStartTime().asc().list();
        //5、输出信息
        for (HistoricActivityInstance historicActivityInstance : list){
    
    
            System.out.println(historicActivityInstance.getActivityId());
            System.out.println(historicActivityInstance.getActivityName());
            System.out.println(historicActivityInstance.getProcessDefinitionId());
            System.out.println(historicActivityInstance.getProcessInstanceId());
            System.out.println("-----------------------");
        }
    }

     /**
     * 添加业务key到数据表中
     */
    @Test
    public void addBusinessKey(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //3、启动流程,添加businessKey
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myEvection", "1001");
        //4、输出
        System.out.println("businessKey="+processInstance.getBusinessKey());
    }

    /**
     * 全部流程实例的挂起和激活
     */
    @Test
    public void suspendAllProcessInstance(){
    
    
        //1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3、查询流程定义,获取流程定义查询对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("myEvection")
                .singleResult();
        //4、获取当前流程定义的实例是否都是挂起状态
        boolean suspended = processDefinition.isSuspended();
        //5、获取流程定义的id
        String processDefinitionId = processDefinition.getId();
        //6、如果是挂起状态,改为激活状态
        if (suspended){
    
    
            repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
            System.out.println("流程id="+processDefinitionId+",状态为激活");
        }else {
    
    
            //7、如果是激活状态,改为挂起状态
            repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
            System.out.println("流程id="+processDefinitionId+",状态为挂起");
        }
    }

    /**
     * 单个流程实例的挂起与激活
     */
    @Test
    public void suspendSingleProcessInstance(){
    
    
        //1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //3、获取流程实例对象
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId("7501")
                .singleResult();
        //4、获取当前流程实例的暂停状态
        boolean suspended = processInstance.isSuspended();
        //5、获取流程实例id
        String processInstanceId = processInstance.getId();
        //6、如果是挂起状态,改为激活状态
        if (suspended){
    
    
            runtimeService.activateProcessInstanceById(processInstanceId);
            System.out.println("流程实例id="+processInstanceId+",状态为激活");
        }else {
    
    
            //7、如果是激活状态,改为挂起状态
            runtimeService.suspendProcessInstanceById(processInstanceId);
            System.out.println("流程实例id="+processInstanceId+",状态为挂起");
        }
    }
}

3. Atividades avançadas

1. Pessoa responsável pela atribuição de tarefas pessoais

Método 1: alocação fixa

Insira a descrição da imagem aqui

Método 2: atribuição de expressão

activiti usa expressões UEL. UEL faz parte da especificação JavaEE6. UEL (Unified Expression Language) é a linguagem de expressão unificada e suporta as duas linguagens de expressão a seguir:

  • Valor UEL: por exemplo: ${assignee0}
  • Método UEL: Por exemplo: ${UserBean.getUserId}
package com.yzs;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

public class AssigneeUelTest {
    
    

    /**
     * 流程部署
     */
    @Test
    public void testDeployment(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3、使用service进行流程部署,定义流程名字,将bpmn部署到数据库中
        Deployment deploy = repositoryService.createDeployment()
                .name("出差申请流程")
                .addClasspathResource("bpmn/evection.bpmn")
                .deploy();
        //4、输出部署信息
        System.out.println("部署id="+deploy.getId());
        System.out.println("部署名字="+deploy.getName());
    }

    /**
     * 启动流程实例
     */
    @Test
    public void startAssigneeUel(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //设定Assignee的值,用来替换uel表达式
        Map<String, Object> map = new HashMap<>();
        map.put("assignee0","张三");
        map.put("assignee1","李四");
        map.put("assignee2","王五");
        map.put("assignee3","赵六");
        //3、根据流程定义的id启动流程
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection",map);
        //4、输出流程信息
        System.out.println("流程定义id="+instance.getProcessDefinitionId());
        System.out.println("流程实例id="+instance.getId());
        System.out.println("当前活动id="+instance.getActivityId());
    }
}

Método 3: alocação de ouvinte

As opções no evento listener incluem:

  • Criar: acionado após a criação da tarefa
  • Atribuição: acionada após a atribuição da tarefa
  • Excluir: acionado após a conclusão da tarefa
  • Todos: Acionado quando todos os eventos ocorrem.
    Insira a descrição da imagem aqui
    Crie uma classe de escuta:
package com.yzs;

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;

public class MyTaskListener implements TaskListener {
    
    
    /**
     * 指定负责人
     * @param delegateTask
     */
    @Override
    public void notify(DelegateTask delegateTask) {
    
    
        if ("创建出差申请".equals(delegateTask.getName()) && "create".equals(delegateTask.getEventName())){
    
    
            delegateTask.setAssignee("xiaoyu");
        }
    }
}

2. Variáveis ​​de processo

(1) Tipo

  • Corda
  • Inteiro
  • curto
  • longo
  • dobro
  • boleano
  • data
  • binário
  • serializável

Nota : Se o pojo for armazenado em uma variável de processo, a interface de serialização serializável deve ser implementada. Para evitar que os campos recém-adicionados não possam ser desserializados, o serializável precisa ser gerado.

(2. Âmbito

  • Variável globa: Nomes de variáveis ​​repetidos não são permitidos. Se você definir uma variável com o mesmo nome, o valor definido posteriormente substituirá o valor da variável definido anteriormente.
  • Variável local: os nomes das variáveis ​​podem ser iguais e os escopos não afetam uns aos outros.

(3) Como usar

  • Usando expressões UEL em propriedades
  • Usando expressões UEL em fios

(4) Implementação de código:
Escreva a classe de entidade pojo e implemente a interface de serialização serializável.

package com.yzs;

import java.io.Serializable;
import java.util.Date;

//出差实体类
public class Evection implements Serializable {
    
    
    //出差id
    private String id;
    //出差人
    private String name;
    //出差时间
    private Date time;

    public String getId() {
    
    
        return id;
    }

    public void setId(String id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public Date getTime() {
    
    
        return time;
    }

    public void setTime(Date time) {
    
    
        this.time = time;
    }
}

Escrever aula de teste

package com.yzs;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.junit.Test;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class VariablesTest {
    
    
    /**
     * 流程部署
     */
    @Test
    public void testDeployment(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3、使用service进行流程部署,定义流程名字,将bpmn部署到数据库中
        Deployment deploy = repositoryService.createDeployment()
                .name("出差申请流程")
                .addClasspathResource("bpmn/evection.bpmn")
                .deploy();
        //4、输出部署信息
        System.out.println("部署id="+deploy.getId());
        System.out.println("部署名字="+deploy.getName());
    }

    /**
     * 启动流程实例
     */
    @Test
    public void startAssigneeUel(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //设定Assignee的值,用来替换uel表达式
        Evection evection = new Evection();
        evection.setId("1");
        evection.setName("张三");
        evection.setTime(new Date());

        Map<String, Object> map = new HashMap<>();
        map.put("evection",evection);
        map.put("assignee0","张三");
        map.put("assignee1","李四");
        map.put("assignee2","王五");
        map.put("assignee3","赵六");
        //3、根据流程定义的id启动流程
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection",map);
        //4、输出流程信息
        System.out.println("流程定义id="+instance.getProcessDefinitionId());
        System.out.println("流程实例id="+instance.getId());
        System.out.println("当前活动id="+instance.getActivityId());
    }
}

3. Como definir variáveis ​​globais de processo

(1) Defina variáveis ​​ao iniciar o processo.

   /**
    * 启动流程实例
    */
   @Test
   public void startAssigneeUel(){
    
    
       //1、创建ProcessEngine
       ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
       //2、获取RuntimeService
       RuntimeService runtimeService = processEngine.getRuntimeService();

       //设定Assignee的值,用来替换uel表达式
       Evection evection = new Evection();
       evection.setId("1");
       evection.setName("张三");
       evection.setTime(new Date());

       Map<String, Object> map = new HashMap<>();
       map.put("evection",evection);
       map.put("assignee0","张三");
       map.put("assignee1","李四");
       map.put("assignee2","王五");
       map.put("assignee3","赵六");
       //3、根据流程定义的id启动流程
       ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection",map);
       //4、输出流程信息
       System.out.println("流程定义id="+instance.getProcessDefinitionId());
       System.out.println("流程实例id="+instance.getId());
       System.out.println("当前活动id="+instance.getActivityId());
   }

(2) Defina variáveis ​​durante o processamento da tarefa.

	/**
     * 完成任务,判断当前用户是否有权限
     */
    @Test
    public void completTask(){
    
    
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        
        //3、创建变量集合
        Map<String, Object> map = new HashMap<>();
        Evection evection = new Evection();
        evection.setId("1");
        evection.setName("张三");
        evection.setTime(new Date());
        //4、定义流程变量
        map.put("evection",evection);

        //5、校验该负责人可以完成当前任务,查询到就去完成任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvection")
                .taskAssignee("张三")
                .singleResult();
        if(task != null){
    
       
	        //6、根据任务id完成任务
	        taskService.complete(task.getId(),map);
        }
    }

(3) Definido através da instância do processo atual. (A instância do processo ainda não deve estar concluída)

	@Test
    public void setGlobalVariableByExecutionId(){
    
    
        String executionId = "2601";
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        
        //3、创建变量集合
        Evection evection = new Evection();
        evection.setId("1");
        evection.setName("张三");
        evection.setTime(new Date());
        //4、通过流程实例id设置流程变量
        runtimeService.setVariable(executionId,"evection",evection);

//       一次设置多个值
//      runtimeService.setVariables(executionId,variables);
    }

(4) Definido pela tarefa atual.

	@Test
    public void setGlobalVariableByTaskId(){
    
    
        String taskId = "1404";
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        
        //3、创建变量集合
        Evection evection = new Evection();
        evection.setId("1");
        evection.setName("张三");
        evection.setTime(new Date());
        //4、通过任务设置流程变量
        taskService.setVariable(taskId,"evection",evection);

//       一次设置多个值
//      taskService.setVariables(taskId,variables);

Nota : Se nenhuma condição for definida para a conexão, será tomada a linha com menor número de vazão.

4. Como definir variáveis ​​de processo locais

(1) Defina variáveis ​​durante o processamento da tarefa.

    @Test
    public void completTask(){
    
    
    	String taskId = "1404";
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        
        //3、创建变量集合
        Map<String, Object> map = new HashMap<String,Object>();
        Evection evection = new Evection();
        evection.setId("1");
        evection.setName("张三");
        evection.setTime(new Date());
        //4、定义流程变量
        map.put("evection",evection);

        //5、设置local变量,作用域为该任务
        taskService.setVariablesLocal(taskId,map);
        //6、完成任务
        taskService.complete(taskId);
    }

(2) Definido pela tarefa atual.

	@Test
    public void setGlobalVariableByTaskId(){
    
    
        String taskId = "1404";
        //1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        
        //3、创建变量集合
        Evection evection = new Evection();
        evection.setId("1");
        evection.setName("张三");
        evection.setTime(new Date());
        //4、通过任务设置流程变量
        taskService.setVariableLocal(taskId,"evection",evection);

//       一次设置多个值
//      taskService.setVariablesLocal(taskId,variables);

5. Tarefas de grupo

Processo de processamento de tarefas de grupo: Consultar tarefas de grupo –> Tarefas de coleta (reivindicação) –> Consultar tarefas individuais –> Processar tarefas individuais

/**
     * 查询组任务
     */
    @Test
    public void findGroupTaskList(){
    
    
        //流程定义key
        String key = "myEvection";
        //任务候选人
        String candidateUser = "liming";

        //1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        //3、查询组任务
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskCandidateUser(candidateUser)
                .list();
        for (Task task:taskList){
    
    
            System.out.println("流程实例id="+task.getProcessInstanceId());
            System.out.println("任务id="+task.getId());
            System.out.println("任务负责人="+task.getAssignee());
        }
    }

    /**
     * 拾取任务
     */
    @Test
    public void claimTask(){
    
    
        //任务id
        String taskId = "65001";
        //任务候选人
        String candidateUser = "liming";


        //1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        //3、查询组任务
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskCandidateUser(candidateUser)
                .singleResult();
        //拾取任务
        if (task != null){
    
    
            taskService.claim(taskId,candidateUser);
            System.out.println("任务拾取成功");
        }
    }

    /**
     * 归还任务
     */
    @Test
    public void assigneeToGroup(){
    
    
        //任务id
        String taskId = "65001";
        //任务负责人
        String assignee = "liming";


        //1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        //3、查询组任务
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskAssignee(assignee)
                .singleResult();
        //归还任务,其实就是把任务的负责人设置为空
        if (task != null){
    
    
            taskService.claim(taskId,null);
            System.out.println("任务归还成功");
        }
    }

    /**
     * 交接任务
     */
    @Test
    public void assigneeToCandidateUser(){
    
    
        //任务id
        String taskId = "65001";
        //任务负责人
        String assignee = "liming";
        //任务候选人
        String candidateUser = "lisi";

        //1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
        //3、查询组任务
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskAssignee(assignee)
                .singleResult();
        //交接任务,其实就是把任务的负责人设置为新的候选人
        if (task != null){
    
    
            taskService.claim(taskId,candidateUser);
            System.out.println("任务交接成功");
        }
    }

6. Portal

(1) Portal exclusivo

Gateway exclusivo, utilizado para implementação de decisões no processo. Quando o processo for executado neste gateway, todas as ramificações determinarão se a condição é verdadeira e, se for verdadeira, a ramificação será executada.

Nota : O gateway exclusivo selecionará apenas uma ramificação verdadeira para execução. Se houver duas condições de ramificação verdadeiras, o gateway exclusivo escolherá a ramificação com o menor valor de ID para executar.

Por que usar um gateway exclusivo?
A ramificação pode ser implementada sem um gateway exclusivo, como definir condições de ramificação na condição de conexão. A desvantagem de definir condições de condição na conexão: Se as condições não forem atendidas, o processo será encerrado (final anormal). Se um gateway exclusivo for usado para determinar a direção do ramal, o sistema lançará uma exceção se todas as condições para a linha que sai do gateway não forem atendidas.

(2) Gateway paralelo

O gateway paralelo permite que o processo seja dividido em vários ramos, e vários ramos também podem ser reunidos.A função do gateway paralelo é baseada nos fluxos de sequência de entrada e saída.

  • Ramificação bifurcada: todos os fluxos de sequência de saída após a paralelização, e uma ramificação simultânea é criada para cada fluxo de sequência.
  • Convergência de junção: Todas as filiais que chegam ao gateway paralelo e esperam aqui entram na filial.Depois que todas as filiais que entram no fluxo sequencial chegarem, o processo passará pelo gateway de convergência.

Nota : Se o mesmo gateway paralelo tiver vários fluxos de sequência de entrada e de saída, ele terá recursos de ramificação e fusão. Neste momento, o gateway primeiro agregará todos os fluxos de sequência recebidos e depois os dividirá em múltiplas ramificações paralelas. A principal diferença de outros gateways é que os gateways paralelos não analisam condições. Mesmo que as condições sejam definidas no fluxo de sequência, elas serão ignoradas.

(3) Incluindo gateway

Os gateways inclusivos podem ser vistos como uma combinação de gateways exclusivos e gateways paralelos. Tal como acontece com o gateway exclusivo, você pode definir condições no fluxo de sequência de saída e o gateway que as contém irá resolvê-las. Mas a principal diferença é que o gateway incluído pode selecionar mais de um fluxo sequencial, assim como o gateway paralelo. A funcionalidade que abrange o gateway é baseada em fluxos de sequência de entrada e saída.

  • Ramificação: todas as condições do fluxo de sequência de saída serão analisadas, e o fluxo de sequência com resultado verdadeiro continuará a ser executado em paralelo, e uma ramificação será criada para cada fluxo de sequência.
  • Convergência: Quando todas as ramificações paralelas chegarem ao gateway, elas entrarão no estado de espera até que chegue cada ramificação que entra no fluxo sequencial contendo o token do processo. Esta é a maior diferença dos gateways paralelos. Em outras palavras, o gateway que o contém apenas aguardará que o fluxo de sequência de entrada seja selecionado para execução. Após a agregação, o processo continua através do gateway que o contém.

(4) Gateway de eventos

Gateways baseados em eventos permitem que decisões de fluxo sejam tomadas com base em eventos. Cada fluxo de sequência de saída do gateway está conectado a um evento de captura intermediário. Quando o processo atingir um gateway baseado em eventos, o gateway entrará em estado de espera: a execução será suspensa. Ao mesmo tempo, assinaturas de eventos correspondentes são criadas para cada fluxo de sequência de saída.

Nota : Os fluxos de sequência de saída baseados em gateways de eventos são diferentes dos fluxos de sequência comuns. Esses fluxos de sequência não serão realmente "executados". Em vez disso, eles permitem que o mecanismo de processo decida quais eventos precisam ser inscritos para executar o processo baseado em gateway de eventos. As seguintes condições devem ser consideradas:

基于事件网关必须有两条或以上外出顺序流;
基于事件网关后,只能使用intermediateCatchEvent类型(activiti不支持基于事件网关后连接ReceiveTask。);
连接到事件网关的中间捕获事件必须只有一个入口顺序流。

Acho que você gosta

Origin blog.csdn.net/fish332/article/details/118308271
Recomendado
Clasificación