Activiti流程基本使用

Hello,大家好,我是你们的CodeWorld,今天抽空写了这么一篇Activiti的基本使用,上一届我们对Activiti进行了入门教学,那么我们今天就开始下一节的讲解,相信你会有很多的收获。
Activiti流程基本使用_第1张图片

安装一个插件

我们可以通过如下方式来安装插件,首先选中Plugins然后选中Install Plugin from Disk,然后再从硬盘里面加载对应的jar包,这个jar包可以直接从这里下载

bpmn插件

提取码:tvbl
Activiti流程基本使用_第2张图片

创建一个SpringBoot项目

这里我就不用去多说了吧,我相信都会一键创建SpringBoot项目

POM文件

<!--引入Activiti和springboot整合的依赖-->
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <!--此处必须用M2版本的,否则必须强制使用SpringSecurity来做用户认证-->
    <version>7.1.0.M2</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.45</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.6.6</version>
</dependency>

引入以上的依赖信息

yml文件配置

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/activiti?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  activiti:
    check-process-definitions: false
    db-history-used: true
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true
server:
  port: 8002

我们需要去创建一个activiti这个数据库,不然找不到数据库

编写代码创建数据库表信息

Activiti流程基本使用_第3张图片
看来我们的引擎对象已获取到了
那么我们再来看看数据库中是否已经创建好表结构了

Activiti流程基本使用_第4张图片

果不其然,表结构已经创建好了,

表结构的诠释

我们可以看到这25张表都是以act开头的。

然后中间部分重点说一下:

  • ge表示通用类型的数据
  • hi表示历史数据
  • re表示流程定义的内容和静态资源
  • ru表示存放运行时的数据,这些表中的数据,Activiti在流程运行的时候才会保存,运行结束之后就会删除掉。

具体的每张表的含义,可以看下表:

表分类 表名称 描述
一般数据 ACT_GE_BYTEARRAY 通用的流程定义和流程资源
ACT_GE_PROPERTY 系统相关属性
流程历史记录 ACT_HI_ACTINST 历史的流程实例
ACT_HI_ATTACHMENT 历史的流程附件
ACT_HI_COMMENT 历史的说明性信息
ACT_HI_DETAIL 历史的流程运行中的细节信息
ACT_HI_IDENTITYLINK 历史的流程运行过程中用户关系
ACT_HI_PROCINST 历史的流程实例
ACT_HI_TASKINST 历史的任务实例
ACT_HI_VARINST 历史的流程运行中的变量信息
用户用户组表 ACT_ID_GROUP 身份信息-组信息
ACT_ID_INFO 身份信息-组信息
ACT_ID_MEMBERSHIP 身份信息-用户和组关系的中间表
ACT_ID_USER 身份信息-用户信息
流程定义表 ACT_RE_DEPLOYMENT 部署单元信息
ACT_RE_MODEL 模型信息
ACT_RE_PROCDEF 已部署的流程定义
运行实例表 ACT_RU_EVENT_SUBSCR 运行时事件
ACT_RU_EXECUTION 运行时流程执行实例
ACT_RU_IDENTITYLINK 运行时用户关系信息
ACT_RU_JOB 运行时作业
ACT_RU_TASK 运行时任务
ACT_RU_VARIABLE 运行时变量表

这里我们就对activiti的数据库介绍就到这里了,那么接下来就开始实战练习了

创建一个bpmn文件

我们需要在resources下面新建一个example.bpmn的文件,并将流程图画好如下

Activiti流程基本使用_第5张图片

然后我们去写一个测试类来启动我们的流程

/**
 * 部署流程
 */
@Test
public void testCreateProcess(){
    Deployment examineDeployment = repositoryService.createDeployment()
            .name("审批实例流程")
            .addClasspathResource("example.bpmn")
            .deploy();
    log.info("流程部署Id=" + examineDeployment.getId());
    log.info("流程部署名字" + examineDeployment.getName());
}

image.png
这里我们就把任务流程部署好了,接下来我们在看看数据库的信息

Activiti流程基本使用_第6张图片

流程部署分析

  • ACT_RE_DEPLOYMENT:流程定义部署记录表,每次部署都会在这张表里面增加一条数据
  • ACT_RE_PROCDEF:这张表表示流程定义表,我们具体的流程定义都存放在这个表里面,这个表里面有个字段key,不同的流程定义就是通过这个key来标识的。
  • ACT_GE_BYTEARRAY:这张表存放的是流程原始资源,也就是我们的bpmn文件和png文件的二进制数据
  • ACT_GE_PROPERTY:操作属性表,每次只要我们操作了数据库这张表的数据都会有改动,我们不用太过于在意。

测试代码

Activiti流程基本使用_第7张图片
我们从这个表里面看见一个 Key(后面会讲,这个很重要),我们现在需要通过这个key来查询流程的定义

查询流程定义

/**
 * 查询流程定义
 */
@Test
public void testSelectProcess() {
     //获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    //获取RepositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    //获取流程定义查询器
    ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
    //通过key查询对应的流程定义,返回的是满足条件的一个List
    List processDefinitions = processDefinitionQuery.processDefinitionKey("myProcess_1")
            .orderByProcessDefinitionVersion()//同样的key可能查询出来的流程定义有多个,这个时候我们需要通过定义的版本倒叙排列一下。
            .desc()
            .list();
    for (ProcessDefinition processDefinition : processDefinitions) {
        log.info("流程定义Id:" + processDefinition.getId());
        log.info("流程定义Key:" + processDefinition.getKey());
        log.info("流程定义Version:" + processDefinition.getVersion());
        log.info("流程定义Name:" + processDefinition.getName());
    }
}

运行结果

image.png

如果我们再次执行部署流程的测试代码

Activiti流程基本使用_第8张图片
我们就会发现又会新增了一条流程记录信息

Activiti流程基本使用_第9张图片
并且我们发现这是两个不同的流程,但是他们的key是默认相同的

Activiti流程基本使用_第10张图片
所以,我们再次执行查询流程定义的测试代码

Activiti流程基本使用_第11张图片
这样我们就会发现同一个key定义了不同的流程,同样的key可能查询出来的流程定义有多个,这个时候我们需要通过定义的版本倒叙排列一下。

不过有个问题,我们的最终会一个流程一个key,那么多个流程的话,我们最终也只会使用最新的那个流程,那么我们上述的查询方法就会有问题,所以我们改用以下方式来查询

image.png
那么我们就看见了只查询出了我们最近定义的流程

删除流程

/**
 * 删除流程
 */
@Test
public void testDeleteProcess() {
    //获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    //获取RepositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    //这里定义流程部署的Id
    String deploymentId = "67199f40-5d72-11ec-8eee-764ca19a8e09";
    //删除流程部署信息,这个时候会把部署信息和对应的流程定义一并删除
    repositoryService.deleteDeployment(deploymentId);
}

我们去看看我们的数据库,是否还存在该流程(67199f40-5d72-11ec-8eee-764ca19a8e09)

Activiti流程基本使用_第12张图片
的确,数据库中的流程已经被删除了

但是这里要注意,我们虽然吧流程给删除了,但是流程中历史信息不会被删除
后面我们会继续试验

问题来了:
删除流行定义的时候,可能会遇到如下的坑,就是如果我们有流程已经启动了,并且还没有执行完成,正在这个时候,如果我们删除其对应的流程定义是无法删除的。我们可以试试看发现抛异常了。那么如果领导要求我们必须非得要删除怎么办?这个时候,我们的做法应该是删除流程定义的时候,同时把对应的正在进行中的流程实例数据一并删除。

我们只需要将这个方法加一个true

repositoryService.deleteDeployment(deploymentId,true);

流程历史信息查看

/**
 * 流程历史记录信息查看
 */
@Test
public void testSelectHistoryProcess() {
    //获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    //获取HistoryService
    HistoryService historyService = processEngine.getHistoryService();
    //获取历史流程实例查询对象
    HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
    //获取历史流程实例
    List historicProcessInstances = historicProcessInstanceQuery.deploymentId("eac62be3-5d77-11ec-a7ac-764ca19a8e09").orderByProcessInstanceStartTime().desc().list();
    historicProcessInstances.forEach(historicProcessInstance -> {
        log.info("流程Id是:" + historicProcessInstance.getId());
        log.info("流程定义名称是:" + historicProcessInstance.getProcessDefinitionName());
        log.info("流程开始时间:" + historicProcessInstance.getStartTime());
        log.info("流程结束时间:" + historicProcessInstance.getEndTime());
    });
}

流程实例的流程详情

/**
 * 获取历史流程数据活动记录
 */
@Test
public void  testSelectProcessDetail(){
    //获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    //获取HistoryService
    HistoryService historyService = processEngine.getHistoryService();
    //获取历史的活动实例的查询对象
    HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
    //获取历史的对应流程实例信息流转数据
    List activityInstances = historicActivityInstanceQuery.processInstanceId("eac62be3-5d77-11ec-a7ac-764ca19a8e09").list();
    for (HistoricActivityInstance activityInstance : activityInstances) {
        log.info("Id:" + activityInstance.getId());
        log.info("节点名称:" + activityInstance.getActivityName());
        log.info("对应的流程实例Id:" + activityInstance.getProcessInstanceId());
        log.info("对应的流程定义Id:" + activityInstance.getProcessDefinitionId());
    }
}

以上我们就对流程的相关的知识点做了基本的讲述,满满的干货,接下来就会讲解任务执行了
好了,本次的技术解析就到这里了?如果觉得不错的话,点亮一下小星星codeworld-cloud-shop 只看不点,不是好孩子哦!!

欢迎加入QQ群(964285437)

Activiti流程基本使用_第13张图片

欢迎加入公众号

Activiti流程基本使用_第14张图片

你可能感兴趣的:(Java,activiti,spring,boot,java,activiti)