Activiti7学习

目录

1.Activiti7简介

1.1工作流

1.2Activiti官网

1.3BPMN建模语言

2.使用步骤

3.Activiti环境搭建

3.1 bpmn 插件安装

3.2 Activiti部署

4.表结构介绍

核心类解析

5.Activiti入门

1.流程设计器使用

1.1认识流程图

1.2绘制流程图

2.流程操作

6.Businesskey

7.挂机和激活流程实例

8.流程变量

8.1流程变量的作用域

8.2使用Global流程变量

8.3使用Local流程变量

9.网关

1.排他网关

2.并行网关

3.包含网关

10.任务分配

1.分配任务负责人

2.组任务分配

1.设置多个任务负责人


1.Activiti7简介

Activiti是目前使用最为广泛的开源工作流引擎

1.1工作流

工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定 义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。

例如员工的入职、请假、出差、采购等等、还有一些关键业务如订单申请、合同审核等等,这些过程, 都是一个工作流。

1.2Activiti官网

官方网站:https://www.activiti.org/

1.3BPMN建模语言

谈到BPMN,我们首先要了解BPM。BPM,即Business Process Management,中文为业务流程管理。它是一种系统化的方法,旨在构建完整、连贯的业务流程,并持续优化以提高组织的工作效率。在诸如EMBA、MBA等主流商业教育课程中,BPM都是不可或缺的一部分。

BPMN,全称为业务流程模型和符号,是一种用于描述业务流程的建模标准。它是由BPMI(业务流程管理倡议)首次提出的,并由一整套标准的业务流程建模符号组成。使用BPMN,我们可以快速准确地定义业务流程。

BPMN在2004年5月首次发布,并在2005年9月并入OMG(对象管理组织)。OMG于2011年1月发布了BPMN 2.0的最终版本。BPMN已成为各大BPM厂商广泛接受的BPM标准,其中Activiti就是使用BPMN 2.0进行流程建模和流程执行管理。

BPMN利用一组符号来描述业务流程中的各种事件。通过在这些符号事件之间建立连线,我们可以完整地描述一个业务流程。这种标准化的建模方式使得业务流程更加清晰、易于理解和管理,从而提高了业务流程的效率和准确性。

常用流程图形

2.使用步骤

部署activiti:

需要把业务系统和Activiti的环境集成 在一起进行部署。

流程定义:

使用activiti流程建模工具定义业务流程(.bpmn文件) 。

部署流程定义:

通过Activiti提供的API,将流程定义文件(.bpmn文件)部署到系统中。

启动流程实例:

启动一个流程实例表示开始一次业务流程的运行。

例如员工提交请假申请后,就可以开启一个流程实例,从而 推动后续的审批等操作。

查询待办任务:

由于业务流程现在由Activiti管理,用户可以通过Activiti查询当前流程的执行状态以及他们需要处理的待办任务。Activiti负责跟踪和管理这些任务,而开发人员无需编写自定义的SQL查询语句。

处理任务:

用户查询到自己的待办任务后,就可以办理某个业务,如果这个 业务办理完成还需要其他用户办理,就可以由activiti帮我们把工作流程往后面的 步骤推动。

结束流程:

当所有任务节点都已完成且没有后续任务时,该流程实例即宣告结束。

3.Activiti环境搭建

JDK 8或以上版本;然后需要一个数据库用来保 存流程定义数据,建议mysql 5或以上版本。

3.1 bpmn 插件安装

我用的是Activiti BPMN visualizer,网上大多数用的都是 actiBPM但是这个插件你IDEA版本太高了用不了,又得在官网下载,又得改配置文件,改完了还有各种BUG如果你IDEA在2020版本或者更早可以试试

3.2 Activiti部署

1.创建 mysql 数据库 activiti

2.新建IDEA工程

3.导入依赖

   <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <log4j.version>1.2.12</log4j.version>
        <activiti.version>7.0.0.Beta1</activiti.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 模型处理 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 转换 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn json数据转换 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 布局 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- activiti 云支持 -->
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>${activiti.version}</version>
        </dependency>


        <!-- log start -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.7</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.7</version>
        </dependency>



    <!-- mysql驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.32</version>
    </dependency>
    <!-- mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <!-- 链接池 -->
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>

        <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.1</version>
    </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>6.0.11</version>
            <scope>test</scope>
        </dependency>
 

4.添加log4j配置

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:\activiti7.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n

5.activiti配置

 resource 下新建 activiti.cfg.xml 文件

<?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/contex
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 这里可以使用 链接池 dbcp-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"
        />
        <property name="url" value="jdbc:mysql://localhost:3306/activiti?serverTimezone=GMT" />
        <property name="username" value="root" />
        <property name="password" value="123456" />

    </bean>
    <bean id="processEngineConfiguration"
          class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- 引用数据源 上面已经设置好了-->
        <property name="dataSource" ref="dataSource" />
        <!-- activiti数据库表处理策略 -->
        <property name="databaseSchemaUpdate" value="true"/>

    </bean>
</beans>

6.初始化数据库表

新建测试类

内容如下

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

public class TestCreateTable {



    @Test
            public void testCreateTable(){
  ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        System.out.println(processEngine);
    }

}

运行完了后发现数据库多了25张表

4.表结构介绍

核心类解析

类名解释
RepositoryServiceactiviti的资源管理类
RuntimeServiceactiviti的流程运行管理类
TaskServiceactiviti的任务管理类
HistoryServiceactiviti的历史管理类
ManagerServiceactiviti的引擎管理类

5.Activiti入门

1.流程设计器使用

1.1认识流程图

事件 Event

事件是驱动工作流发展的核心对象,在工作流的流程定制过程中会经常看到。

活动 Activity 活动是工作或任务的一个通用术语。一个活动可以是一个任务,也可以是当前流程 的子处理流程。并且,活动会有不同的类型。例如Activiti中定义了 UserTask,ScriptTask,ServiceTask,MailTask等等多种类型。这些活动是构成整个业 务流程的主体。

网关 GateWay 网关是用来处理角色的,他决定了工作流的业务走向。有几种常用的网关需要了解 一下:

排他网关 只有一条路径会被选择。流程执行到该网关时,会按照输出流的顺序逐个计算,当 条件的结果为true时,继续执行当前网关的输出流。 如果有多条线路计算结构都是true,则会执行第一个值为true的路线。如果所有 网关计算结果都没有true,引擎会抛出异常。

排他网关需要和条件顺序流结合使用,default属性指定默认顺序流,当所有的条 件不满足时会执行默认顺序流。

并行网关 所有路径会被同时选择。 并行执行所有输出顺序流,为每一条顺序流创建一个并行执行路线。最终,在所有 的执行路线都执行完后才继续向下执行。

包容网关 可以同时执行多条路线。相当于是排他网关和并行网关的结合。 可以在网关上设置条件,计算每条路线上的表达式。当表达式计算结果为true时, 创建一个并行线路并继续执行。最终,当所有需要执行的线路都执行完成后才继续 向下执行。

事件网关 专门为中间捕获事件而设置。允许设置多个输出流指向多个不同的中间捕获事件。 当流程执行到事件网关后,流程出于等待状态,需要等待抛出对应的事件才能将等 待状态转换为活动状态。 流向 Flow 流就是连接两个流程节点的连线,代表了流程之间的关联关系。

流向 Flow

流就是连接两个流程节点的连线,代表了流程之间的关联关系。

1.2绘制流程图

在resource里面新建一个包,然后新建这种文件

创建完后点击

在这个页面右键后会显示各种流程符号

先来创建一个简单的流程图

每一个模块都可以选中后设置他们的属性

点击空白的地方设置该流程图的属性

2.流程操作

新建一个测试类ActivitiDemo

流程部署定义

@Test
public void testDeployment(){
  /*  ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.
            createProcessEngineConfigurationFromResource("activiti.cfg.xml","processEngineConfiguration");*/
    //1.创建ProcessEngine
    ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
            buildProcessEngine();
/*    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();*/
    //2.得到RepositoryService 实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    //3.使用RepositoryService 进行部署
    Deployment deployment = repositoryService.createDeployment()
            .addClasspathResource("bpmn/bpmn11.bpmn20.xml")
//            .addClasspathResource("bpmn/diagram1.png")
            .name("员工请假2")
            .deploy();
    System.out.println("流程部署id" + deployment.getId());
    System.out.println("流程部署名称" + deployment.getName());
}

这里我用ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine()就报错ProcessEngine抛空指针异常

我修改成 ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml")之后又说我cpdb版本不对,改一下版本就好了

输出内容

zip 压缩包上传

@Test
public void deployProcessByZip() {
    // 定义zip输入流
    InputStream inputStream = this
            .getClass()
            .getClassLoader()
            .getResourceAsStream(
                    "bpmn/Leave.zip");
    ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    // 获取repositoryService
    ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
            buildProcessEngine();
    RepositoryService repositoryService = processEngine
            .getRepositoryService();
    // 流程部署
    Deployment deployment = repositoryService.createDeployment()
            .addZipInputStream(zipInputStream)
            .deploy();
    System.out.println("流程部署id:" + deployment.getId());
    System.out.println("流程部署名称:" + deployment.getName());
}

启动流程实例

  @Test
    public void testStartProcess(){
//        1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        2、获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
//        3、根据流程定义Id启动流程
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey("bpmn11");
//        输出内容
        System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例id:" + processInstance.getId());
        System.out.println("当前活动Id:" + processInstance.getActivityId());
    }

查询当前个人待执行的任务

@Test
    public void testFindPersonalTaskList() {
//        任务负责人
        String assignee = "张经理1";
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        创建TaskService
        TaskService taskService = processEngine.getTaskService();
//        根据流程key 和 任务负责人 查询任务
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("bpmn11") //流程Key
                .taskAssignee(assignee)//只查询该任务负责人的任务
                .list();

        for (Task task : list) {
            System.out.println("流程实例id:" + task.getProcessInstanceId());
            System.out.println("任务id:" + task.getId());
            System.out.println("任务负责人:" + task.getAssignee());
            System.out.println("任务名称:" + task.getName());

        }
    }

完成任务

 @Test
    public void completTask(){
//        获取引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        获取taskService
        TaskService taskService = processEngine.getTaskService();

//        根据流程key 和 任务的负责人 查询任务
//        返回一个任务对象
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("bpmn11") //流程Key
                .taskAssignee("李四1")  //要查询的负责人
                .singleResult();

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

查询流程定义

  @Test
    public void queryProcessDefinition(){
        //        获取引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();

//        repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
//        得到ProcessDefinitionQuery 对象
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//          查询出当前所有的流程定义
//          条件:processDefinitionKey =Evection
//          orderByProcessDefinitionVersion 按照版本排序
//        desc倒叙
//        list 返回集合
        List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey("demo1")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();
//      输出流程定义信息
        for (ProcessDefinition processDefinition : definitionList) {
            System.out.println("流程定义 id="+processDefinition.getId());
            System.out.println("流程定义 name="+processDefinition.getName());
            System.out.println("流程定义 key="+processDefinition.getKey());
            System.out.println("流程定义 Version="+processDefinition.getVersion());
            System.out.println("流程部署ID ="+processDefinition.getDeploymentId());
        }
    }

查询流程实例

 @Test
    public void queryProcessInstance() {
        // 流程定义key
        String processDefinitionKey = "bpmn11";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        List<ProcessInstance> list = runtimeService
                .createProcessInstanceQuery()
                .processDefinitionKey(processDefinitionKey)//
                .list();

        for (ProcessInstance processInstance : list) {
            System.out.println("----------------------------");
            System.out.println("流程实例id:"
                    + processInstance.getProcessInstanceId());
            System.out.println("所属流程定义id:"
                    + processInstance.getProcessDefinitionId());
            System.out.println("是否执行完成:" + processInstance.isEnded());
            System.out.println("是否暂停:" + processInstance.isSuspended());
            System.out.println("当前活动标识:" + processInstance.getActivityId());
            System.out.println("业务关键字:"+processInstance.getBusinessKey());
        }
    }

删除流程

 @Test
    public void deleteDeployment() {
        // 流程部署id
        String deploymentId = "1";

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 通过流程引擎获取repositoryService
        RepositoryService repositoryService = processEngine
                .getRepositoryService();
        //删除流程定义,如果该流程定义已有流程实例启动则删除时出错
        repositoryService.deleteDeployment(deploymentId);
        //设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式,如果流程
//        repositoryService.deleteDeployment(deploymentId, true);
    }

查看历史信息

@Test
    public void findHistoryInfo(){
//      获取引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        获取HistoryService
        HistoryService historyService = processEngine.getHistoryService();
//        获取 actinst表的查询对象
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
//        查询 actinst表,条件:根据 InstanceId 查询,查询一个流程的所有历史信息
//        instanceQuery.processInstanceId("2501");
//        查询 actinst表,条件:根据 DefinitionId 查询,查询一种流程的所有历史信息
//        instanceQuery.processDefinitionId("myLeave:1:22504");
//        增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
//        查询所有内容
        List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
//        输出
        for (HistoricActivityInstance hi : activityInstanceList) {
            System.out.println(hi.getActivityId());
            System.out.println(hi.getActivityName());
            System.out.println(hi.getProcessDefinitionId());
            System.out.println(hi.getProcessInstanceId());
            System.out.println("<==========================>");
        }
    }

6.Businesskey

Activiti 提供了将工作流程与实际业务完美结合的关键功能。例如,在审批业务订单时,虽然订单的详细信息存储在其他系统中,但审批人员需要查看这些信息以做出决策。通过使用 businessKey,我们可以将订单 ID 与流程实例关联起来,从而使审批人员能够快速地在业务系统中找到相应的订单详细信息。

在设计业务整合时,businessKey 的数据格式可以根据具体需求进行定制。无论是使用逗号拼接的关键信息,还是 JSON 格式,都可以根据实际情况选择。但需要注意的是,数据库中该字段的长度限制为 255 个字符,因此在进行设计时需要确保不会超出这个限制。

通过合理地使用 businessKey,我们可以实现工作流程与实际业务的无缝集成,提高审批效率和准确性,从而更好地满足业务需求。

 @Test
    public void addBusinessKey(){
//        1、获取流程引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        2、获取RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
//        3、启动流程的过程中,添加businesskey
//           第一个参数:流程定义的key
//           第二个参数:businessKey,存出差申请单的id,
        ProcessInstance instance = runtimeService.
                startProcessInstanceByKey("bpmn11", "320001");
//        4、输出
        System.out.println("businessKey=="+instance.getBusinessKey());

    }

7.挂机和激活流程实例

在之前的讨论中,我们探讨了如何删除一个流程。但在实际应用中,有时我们只需要暂时停止某个流程,以便在未来的某个时间点重新启动。例如,在月底可能不需要处理报销审批流程,年底可能不希望启动借贷审批流程,或者在非工作日时段,我们可能不希望处理售后报销流程。在这种情况下,我们可以将流程设置为挂起状态,以停止其执行。一旦流程被挂起,它就不会继续执行,直到被重新激活。通过挂起操作,我们可以有效地管理业务流程的执行,以满足特定的业务需求和条件。

全部流程实例的 挂起和 激活

@Test
    public void suspendAllProcessInstance(){
//        1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、获取Repositoryservice
        RepositoryService repositoryService = processEngine.getRepositoryService();
//        3、查询流程定义,获取流程定义的查询对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("demo1")
                .singleResult();
//        4、获取当前流程定义的实例是否都是挂起状态
        boolean suspended = processDefinition.isSuspended();
//        5、获取流程定义的id
        String definitionId = processDefinition.getId();
//        6、如果是挂起状态,改为激活状态
        if(suspended){
//            如果是挂起,可以执行激活的操作,参数1:流程定义id 参数2:是否激活,参数3:激活时间
            repositoryService.activateProcessDefinitionById(definitionId,
                    true,
                    null);
            System.out.println("流程定义id:"+definitionId+",已激活");
        }else {
//        7、如果是激活状态,改为挂起状态,参数1:流程定义id 参数2:是否暂停 参数3 :暂停的时间
            repositoryService.suspendProcessDefinitionById(definitionId,
                    true,
                    null);
            System.out.println("流程定义id:"+definitionId+",已挂起");
        }
    }

挂起、激活单个流程实例

 @Test
    public void suspendSingleProcessInstance(){
//        1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        2、RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
//        3、通过RuntimeService获取流程实例对象
        ProcessInstance instance = runtimeService.createProcessInstanceQuery()
                .processInstanceId("20001")
                .singleResult();
//        4、得到当前流程实例的暂停状态,true-已暂停  false -激活
        boolean suspended = instance.isSuspended();
//        5、获取流程实例id
        String instanceId = instance.getId();
//        6、判断是否已经暂停,如果已经暂停,就执行激活操作
        if(suspended){
//            如果已经暂停,就执行激活
            runtimeService.activateProcessInstanceById(instanceId);
            System.out.println("流程实例id:"+instanceId+"已经激活");
        }else {
//        7、如果是激活状态,就执行暂停操作
            runtimeService.suspendProcessInstanceById(instanceId);
            System.out.println("流程实例id:"+instanceId+"已经暂停");
        }
    }

完成个人任务

@Test
    public void completTask(){
//        1、获取流程引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        2、获取TaskService
        TaskService taskService = processEngine.getTaskService();
//        3、使用taskservice获取任务,参数 流程实例的id,负责人
        Task task = taskService.createTaskQuery()
                .processInstanceId("20001")
                .taskAssignee("worker")
                .singleResult();
        System.out.println("流程实例id=="+task.getProcessInstanceId());
        System.out.println("流程任务id=="+task.getId());
        System.out.println("负责人=="+task.getAssignee());
        System.out.println("任务名称=="+task.getName());
//        4、根据任务的id完成任务
        taskService.complete(task.getId());
    }

8.流程变量

流程变量在Activiti中起到了关键作用。在请假流程中,虽然步骤是固定的,但当业务需求变得更复杂时,如根据请假天数调整审批层级,流程变量就显得尤为重要。通过使用流程变量,我们可以根据不同条件动态调整流程的执行路径,从而满足各种复杂的业务需求。这意味着,流程变量为Activiti提供了更大的灵活性和可配置性,使其能够适应各种实际业务流程的需求。

8.1流程变量的作用域

在Activiti中,变量的作用域可以分为两种:Global和Local。

Global变量是流程变量的默认作用域,表示整个流程实例的范围。Global变量中的名称必须是唯一的,不能重复。如果设置了相同的变量名,后设置的变量值会直接覆盖先前的变量值。

相比之下,Local变量的作用域仅限于单个任务或执行实例的范围,其作用范围较小。由于Local变量在不同的任务或执行实例中作用,它们的范围是互不影响的,因此变量名称可以相同。Local变量名也可以与Global变量名相同,而不会产生冲突或影响。

通过合理地使用Global和Local变量,可以更好地管理和控制业务流程的执行,满足各种复杂的业务需求。

8.2使用Global流程变量

定义好流程变量后,就可以在整个流程定义中使用这些流程变量了。

例如可以在 某些任务属性如assignee上使用${assignee},或者在某些连线上使用${day<3}。 Activiti中可以使用UEL表达式来使用这些流程变量。

UEL表达式可以直接获取一 个变量的值,可以计算一个Boolean结果的表达式,还可以直接使用某些对象的属 性。例如对于之前创建的请假流程,如果要实现3天以内部门经理审核,3天以上增 加总经理审核,可以做如下调整:

点击线段在 Condition expression中编写条件 

我的这个插件生成的uel表达式不识别大于等于小于号

然后我把actiBPM里面的代码复制进来了

大概格式是

<![CDATA[${evection.num<3}]]>

启动流程时设置变量 在启动流程实例时设置流程变量,这时流程变量的作用域是整个流程实例。相当于 是Global作用域。

核心代码:

runtimeService.startProcessInstanceByKey(key,variables);

任务办理时设置变量 在完成任务时,可以设置流程变量。这些流程变量仅在当前任务完成后,其他节点才可以使用。这些变量的作用范围是整个流程实例。如果流程实例中已经存在相同名字的变量,后设置的变量将覆盖先前的变量。这意味着,流程变量的设置和使用是动态的,可以根据流程的执行情况而变化,从而实现更加灵活的业务流程控制。

核心代码:

taskService.complete(task.getId(),map);

通过当前流程实例设置

@Test
    public void testStartProcess(){
//        获取流程引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();

//        流程定义的Key
        String key = "bpmn5";
//        流程变量的map
        Map<String,Object> variables = new HashMap<>();
//        设置流程变量
        Evection evection = new Evection();
//        设置出差日期
        evection.setNum(2d);
//        把流程变量的pojo放入map
        variables.put("evection",evection);
//        设定任务的负责人
        variables.put("assignee0","李四12");
        variables.put("assignee1","王经理12");
        variables.put("assignee2","张财务12");
        variables.put("assignee3","杨总经理12");
//        启动流程
        runtimeService.startProcessInstanceByKey(key,variables);
     //   runtimeService.startProcessInstanceByKey(key,"DSADASD",variables);
    }

通过当前任务设置

  @Test
    public void completTask(){
//        流程定义的Key
        String key = "demo4";
//        任务负责人
       String assingee = "李四6";
    //   String assingee = "王经理5";
   //     String assingee = "张财务4";
//        String assingee = "张财务3";
//        设置流程变量
//        Evection Evection = new Evection();
        设置出差时间
//        Evection.setNum(2d);
        Map<String,Object> map = new HashMap<>();
        map.put("assignee1","aaa");
        //        获取流程引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        获取taskservice
        TaskService taskService = processEngine.getTaskService();
//        查询任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey(key)
                .taskAssignee(assingee)
                .singleResult();
        if(task != null){
            //局部
       //     taskService.setVariablesLocal(task.getId(),map);
            //     根据任务id   完成任务,并传递流程变量
            taskService.complete(task.getId(),map);
            System.out.println(task.getId()+"----任务已完成");
        }

    }

8.3使用Local流程变量

local流程变量同样可以有多个设置的地方。

任务办理时设置

任务办理时设置local流程变量,当前运行的流程实例只能在该任务结束前使用,任 务结束该变量无法在当前流程实例使用,可以通过查询历史任务查询。关键代码:

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

通过当前任务设置 在完成任务时设置流程变量,该流程变量只有在该任务完成后其它结点才可使用该 变量,它的作用域是整个流程实例,如果设置的流程变量的key在流程实例中已存在 相同的名字则后设置的变量替换前边设置的变量。核心代码:

@Test
public void setLocalVariableByTaskId(){
// 当前待办任务id
String taskId="173001";
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Evection evection = new Evection ();
evection.setNum(3d);
// 通过任务设置流程变量
taskService.setVariableLocal(taskId, "evection", evection);
// 一次设置多个值
//taskService.setVariablesLocal(taskId, variables)}

9.网关

1.排他网关

排他网关,用来在流程中实现决策。 当流程执行到这个网关,所有分支都会判断条 件是否为true,如果为true则执行该分支

如果我是一名员工我要请2天假

2.并行网关

并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功 能是基于进入和外出顺序流的

例:

我是一个员工我要请假三天

3.包含网关

包含网关可以看做是排他网关和并行网关的结合体。

如果我要请假两天就需要李经理和经理审批 

四天就是总经理和经理审批

4.事件网关

事件网关允许我们根据事件来判断流程的流向。在网关中,每个外发的顺序流都会连接到中间捕获事件。当流程到达一个基于事件的事件网关时,网关会进入等待状态,暂时停止执行。同时,为每个外发的顺序流创建相应的事件订阅。这意味着,根据不同的事件触发,流程可以流向不同的方向,从而实现灵活的流程控制。

10.任务分配

1.分配任务负责人

可 以使用UEL表达式配合流程变量来灵活指定

 public void testStartProcess(){
//        获取流程引擎
        ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").
                buildProcessEngine();
//        获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();

//        流程定义的Key
        String key = "bpmn5";
//        流程变量的map
        Map<String,Object> variables = new HashMap<>();
//        设置流程变量
        Evection evection = new Evection();
//        设置出差日期
        evection.setNum(2d);
//        把流程变量的pojo放入map
        variables.put("evection",evection);
//        设定任务的负责人
        variables.put("assignee0","李四12");
        variables.put("assignee1","王经理12");
        variables.put("assignee2","张财务12");
        variables.put("assignee3","杨总经理12");
//        启动流程
        runtimeService.startProcessInstanceByKey(key,variables);
     //   runtimeService.startProcessInstanceByKey(key,"DSADASD",variables);
    }

2.组任务分配

1.设置多个任务负责人

流程部署启动,提交申请之后

需要候选人拾取任务

 @Test
        public void claimTask() {
//        获取引擎
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取TaskService
            TaskService taskService = processEngine.getTaskService();
//        当前任务的id
            String taskId = "297502";
//        任务候选人
            String candidateUser = "zhang";
//        查询任务
            Task task = taskService.createTaskQuery()
                    .taskId(taskId)
                    .taskCandidateUser(candidateUser)
                    .singleResult();
            if (task != null) {
//            拾取任务
                taskService.claim(taskId, candidateUser);
                System.out.println("taskid-" + taskId + "-用户-" + candidateUser + "-拾取任务完成");
            }
        }

任务的归还

  @Test
        public void testAssigneeToGroupTask() {
//        获取引擎
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取TaskService
            TaskService taskService = processEngine.getTaskService();
//        当前任务的id
            String taskId = "297502";
//        任务负责人
            String assignee = "zhang";
//        根据key 和负责人来查询任务
            Task task = taskService.createTaskQuery()
                    .taskId(taskId)
                    .taskAssignee(assignee)
                    .singleResult();
            if (task != null) {
//            归还任务 ,就是把负责人 设置为空
                taskService.setAssignee(taskId, null);
                System.out.println("taskid-" + taskId + "-归还任务完成");
            }
        }

任务的交接

 @Test
        public void testAssigneeToCandidateUser() {
//        获取引擎
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取TaskService
            TaskService taskService = processEngine.getTaskService();
//        当前任务的id
            String taskId = "297502";
//        任务负责人
            String assignee = "zhang";
//        任务候选人
            String candidateUser = "zhao";
//        根据key 和负责人来查询任务
            Task task = taskService.createTaskQuery()
                    .taskId(taskId)
                    .taskAssignee(assignee)
                    .singleResult();
            if (task != null) {
//            交接任务 ,就是把负责人 设置为空
                taskService.setAssignee(taskId, candidateUser);
                System.out.println("taskid-" + taskId + "-交接任务完成");
            }
        }

完成个人任务

 @Test
        public void completTask() {
//        流程定义的Key
            String key = "demo10";
//        任务负责人
            String assingee = "zhao";
//        String assingee = "";
            //        获取流程引擎
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取taskservice
            TaskService taskService = processEngine.getTaskService();
//        查询任务
            Task task = taskService.createTaskQuery()
                    .processDefinitionKey(key)
                    .taskAssignee(assingee)
                    .singleResult();
            if (task != null) {
                //     根据任务id来   完成任务
                taskService.complete(task.getId());

        }
    }

  • 32
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值