Activiti7工作流

一、工作流介绍

Activiti7是开源的工作流引擎

工作流(Workflow)就是工作流程的计算模型,即将工作流程中的工作如何前后组织在一起的逻辑和规则在计算机中以恰当的模型进行表示并对其实施计算。工作流要解决的主要问题是:为实现某个业务目标,在多个参与者之间,利用计算机,按某种预定规则自动传递文档、信息或者任务。

二、安装插件

插件名字

actiBPM

离线安装

IDEA新版本需要到插件市场下载并离线安装。

Activiti7工作流_第1张图片

重启IDEA

Activiti7工作流_第2张图片

三、BPMN介绍

所有符号

Activiti7工作流_第3张图片

完整的工作流由StartEvent开始,由EndEvent结束,中间穿插着各种Task任务,Gateway负责构建复杂的流程(如请假审批,请假1天的,和请假3天的流程是不一样的),SubProcess子流程,Annotation注解。

四、Activiti使用步骤

  1. 部署Activiti,整合Activiti依赖
  2. 定义流程,BPMN建模
  3. 部署流程,把流程内容存储起来
  4. 启动流程实例,开始一次业务流程运作
  5. 用户查询代办任务,activiti查询流程到哪个步骤
  6. 用户办理业务,查询到自己的待办任务后就可以办理某个业务了
  7. 结束流程,没有下一个任务节点流程就完成了

五、创建数据库表

创建数据库

Activiti7工作流_第4张图片

创建项目

Activiti7工作流_第5张图片

导入依赖

<properties>
    <activiti.version>7.0.0.Beta3activiti.version>
properties>

<dependency>
    <groupId>org.activitigroupId>
    <artifactId>activiti-engineartifactId>
    <version>${activiti.version}version>
    
    <exclusions>
        <exclusion>
            <artifactId>mybatisartifactId>
            <groupId>org.mybatisgroupId>
        exclusion>
    exclusions>
dependency>

<dependency>
    <groupId>org.activitigroupId>
    <artifactId>activiti-springartifactId>
    <version>${activiti.version}version>
dependency>

<dependency>
    <groupId>org.activitigroupId>
    <artifactId>activiti-bpmn-modelartifactId>
    <version>${activiti.version}version>
dependency>

<dependency>
    <groupId>org.activitigroupId>
    <artifactId>activiti-bpmn-converterartifactId>
    <version>${activiti.version}version>
dependency>

<dependency>
    <groupId>org.activitigroupId>
    <artifactId>activiti-json-converterartifactId>
    <version>${activiti.version}version>
dependency>

<dependency>
    <groupId>org.activitigroupId>
    <artifactId>activiti-bpmn-layoutartifactId>
    <version>${activiti.version}version>
dependency>

创建配置文件

image-20210516022824881

activiti.cfg.xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl"
                  value="jdbc:mysql://**********/activiti-service-dev?useUnicode=true&characterEncoding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="**********"/>
    bean>

    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        
        <property name="dataSource" ref="dataSource"/>
        
        <property name="databaseSchemaUpdate" value="true"/>
    bean>
beans>

生成表结构

package com.qiang.activiti;

import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
@Slf4j
class ActivitiServiceApplicationTests {

    /**
     * 生成表结构
     */
    @Test
    public void testCreateTable() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        log.info("testCreateTable{}", defaultProcessEngine);
    }

}

启动程序

Activiti7工作流_第6张图片

运行结果

生成25张表。

Activiti7工作流_第7张图片

六、流程引擎主要方法

Activiti7工作流_第8张图片

七、BPMN流程建模

新建文件

Activiti7工作流_第9张图片

新建一个请假流程

Activiti7工作流_第10张图片

整体流程配置,设置流程ID为leave,名字为员工请假审批流程

Activiti7工作流_第11张图片

配置提交请假申请的责任人为worker

Activiti7工作流_第12张图片

配置部门经理审批的责任人为manager

Activiti7工作流_第13张图片

配置财务主管审批的责任人为financer

Activiti7工作流_第14张图片

八、导出流程图

将BPMN文件复制一份为XML文件

image-20210516225827950

选择BPMN设计器

Activiti7工作流_第15张图片

查看流程图

Activiti7工作流_第16张图片

导出流程图

Activiti7工作流_第17张图片

九、部署流程

9.1 单个流程部署

/**
 * 部署流程(单个流程)
 */
@Test
public void testDeployment() {
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取 repositoryService 实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 使用 repositoryService 进行部署
    Deployment deployment = repositoryService.createDeployment()
            // 对应的 bpmn 文件
            .addClasspathResource("bpmn/leave.bpmn")
            // 对应的流程图文件,命名规范(流程ID.png)为 leave.png/jpg/gif/svg
            .addClasspathResource("bpmn/image/leave.png")
            .name("请假申请流程")
            .deploy();
    // 获取部署后的信息
    log.info("部署的流程ID:{}", deployment.getId());
    log.info("部署流程名称:{}", deployment.getName());
}

启动实例

Activiti7工作流_第18张图片

数据已经存到数据库

Activiti7工作流_第19张图片

包括XML文件以及图片文件

Activiti7工作流_第20张图片

9.2 批量流程部署

将bpmn文件以及流程图文件按规定名字打成压缩包

Activiti7工作流_第21张图片

文件位置

Activiti7工作流_第22张图片

实例代码

/**
 * 批量部署流程
 */
@Test
public void testDeploymentByZip() {
    InputStream inputStream = this
            .getClass()
            .getClassLoader().getResourceAsStream("bpmn/zip/test.zip");
    assert inputStream != null;
    ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取 repositoryService 实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 使用 repositoryService 进行部署
    Deployment deployment = repositoryService.createDeployment()
            .addZipInputStream(zipInputStream)
            .deploy();
    // 获取部署后的信息
    log.info("部署的流程ID:{}", deployment.getId());
    log.info("部署流程名称:{}", deployment.getName());
}

启动实例

Activiti7工作流_第23张图片

数据已经存到数据库

Activiti7工作流_第24张图片

包括XML文件以及图片文件

Activiti7工作流_第25张图片

十、启动流程实例

根据流程 ID 启动流程

/**
 * 启动流程实例
 */
@Test
public void testStartProcess() {
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取 runtimeService 实例
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 根据流程 ID 启动流程
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave");
    // 获取启动流程后的信息
    log.info("流程定义ID:{}", processInstance.getProcessDefinitionId());
    log.info("流程实例ID:{}", processInstance.getId());
    log.info("当前活动ID:{}", processInstance.getActivityId());
}

执行结果

Activiti7工作流_第26张图片

十一、查询待办任务

启动流程实例后,该节点到达了提交请假申请的节点,需要任务负责人查询当前负责的待办任务(当前负责人为worker要提交请假申请)。

/**
 * 查询当前负责人的待办任务
 */
@Test
public void testFindPersonalTaskList() {
    // 当前负责人
    String assignee = "worker";
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 创建 taskService
    TaskService taskService = processEngine.getTaskService();
    // 根据流程 Key 和任务负责人查询代办任务
    List<Task> tasks = taskService.createTaskQuery()
            // 流程 Key
            .processDefinitionKey("leave")
            // 负责人
            .taskAssignee(assignee)
            .list();
    tasks.forEach(task -> {
        log.info("流程实例ID:{}", task.getProcessInstanceId());
        log.info("流程任务ID:{}", task.getId());
        log.info("流程任务负责人:{}", task.getAssignee());
        log.info("流程任务名称:{}", task.getName());
    });
}

启动实例

Activiti7工作流_第27张图片

十二、完成任务

当前任务节点到了worker审批,根据查询到的任务ID完成任务。

/**
 * 完成任务
 */
@Test
public void testCompleteTask() {
    // 当前负责人
    String assignee = "worker";
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 创建 taskService
    TaskService taskService = processEngine.getTaskService();
    Task task = taskService.createTaskQuery()
            .processDefinitionKey("leave")
            // 负责人
            .taskAssignee(assignee)
            // 返回一个任务
            .singleResult();
    // 根据任务ID完成任务
    taskService.complete(task.getId());
}

启动实例

Activiti7工作流_第28张图片

完成任务后,再次查询worker的代办任务已经没有了,任务已经流转到了部门经理审批了,此时可以查询到manager的待办任务了。

/**
 * 查询当前负责人的待办任务
 */
@Test
public void testFindPersonalTaskList() {
    // 当前负责人
    String assignee = "manager";
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 创建 taskService
    TaskService taskService = processEngine.getTaskService();
    // 根据流程 Key 和任务负责人查询代办任务
    List<Task> tasks = taskService.createTaskQuery()
            // 流程 Key
            .processDefinitionKey("leave")
            // 负责人
            .taskAssignee(assignee)
            .list();
    tasks.forEach(task -> {
        log.info("流程实例ID:{}", task.getProcessInstanceId());
        log.info("流程任务ID:{}", task.getId());
        log.info("流程任务负责人:{}", task.getAssignee());
        log.info("流程任务名称:{}", task.getName());
    });
}

启动实例

Activiti7工作流_第29张图片

十三、查询当前流程定义

查询当前流程定义下有哪些实例正在跑。

/**
 * 查询当前流程定义
 */
@Test
public void testQueryProcessInstance(){
    // 流程定义Key
    String processDefinitionKey = "leave";
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取 runtimeService 实例
    RuntimeService runtimeService = processEngine.getRuntimeService();
    List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery()
            .processDefinitionKey(processDefinitionKey)
            .list();
    processInstances.forEach(processInstance -> {
        log.info("===========================================");
        log.info("流程实例ID:{}", processInstance.getProcessInstanceId());
        log.info("所属流程定义ID:{}", processInstance.getProcessDefinitionId());
        log.info("是否执行完成:{}", processInstance.isEnded());
        log.info("是否暂停流程:{}", processInstance.isSuspended());
        log.info("当前活动标识:{}", processInstance.getActivityId());
        log.info("业务关键字:{}", processInstance.getBusinessKey());
    });
}

启动实例

Activiti7工作流_第30张图片

这里两个流程

Activiti7工作流_第31张图片

十四、查询所有流程定义

查询在一个BPMN文件中定义了哪些流程。

/**
 * 查询所有流程定义
 */
@Test
public void testQueryProcessDefinition() {
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取 repositoryService 实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 获取 processDefinitionQuery 实例
    ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
    List<ProcessDefinition> processDefinitions = processDefinitionQuery.processDefinitionKey("leave")
            // 按照版本排序
            .orderByProcessDefinitionVersion()
            // 倒序
            .desc()
            // 返回集合
            .list();
    processDefinitions.forEach(processDefinition -> {
        log.info("===========================================");
        log.info("流程定义ID:{}", processDefinition.getId());
        log.info("流程定义NAME:{}", processDefinition.getName());
        log.info("流程定义KEY:{}", processDefinition.getKey());
        log.info("流程定义Version:{}", processDefinition.getVersion());
        log.info("流程部署ID:{}", processDefinition.getDeploymentId());
    });
}

启动实例

Activiti7工作流_第32张图片

十五、删除流程

/**
 * 删掉流程
 */
@Test
public void testDeleteDeployment() {
    // 流程部署Id
    String deploymentId = "1";
    // 创建 processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取 repositoryService 实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 根据Id删除,如果该流程有实例正在启动则报错
    repositoryService.deleteDeployment(deploymentId);
    // 根据Id删除,如果该流程有实例正在启动则会级联删除
    repositoryService.deleteDeployment(deploymentId,true);
}

九十九、常见问题

1.1 BPMN文件乱码

设置IDEA的编码格式为UTF-8。

Activiti7工作流_第33张图片

加上这一行然后重启IDEA即可。

-Dfile.encoding=UTF-8

Activiti7工作流_第34张图片

乱码解决。

Activiti7工作流_第35张图片

1.2 数据库版本不一致

问题:

org.activiti.engine.ActivitiException: Could not update Activiti database schema: unknown version from database: '6.0.0.4'

解决:

<activiti.version>6.0.0activiti.version>

<dependency>
    <groupId>org.activitigroupId>
    <artifactId>activiti-springartifactId>
    <version>${activiti.version}version>
dependency>

作者(Author):小强崽
来源(Source):https://www.wuduoqiang.com/archives/Activiti7工作流
协议(License):署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
版权(Copyright):商业转载请联系作者获得授权,非商业转载请注明出处。 For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source.

你可能感兴趣的:(Activiti,activiti)