前后端分离Springboot 整合使用activiti7教程(一)(全网最细)

activiti7关于SpringBoot前后端分离项目的详细教程

文章目录

本篇文章是从网上购买的教程然后整理出来的笔记,供大家一起学习参考。

一、Activiti工作流概述

这一章节就是对工作流的基础概述,对此比较熟悉的可以直接跳过。

1.1 什么是工作流

工作流的简单概念就是用于流程审批的。

如:请假审批流程、报销审批流程、出差审批流程、合同审批流程等。

工作流(Workflflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者 之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。 工作流引擎,主要是为了帮忙我们实现流程自动化控制,对应的Activiti引擎就可以实现自动化控制。 工作流管理系统是一个软件系统,它完成工作量的定义和管理,并按照在系统中预先定义好的工作流规则进行工作

1.2 工作流应用场景

工作流应用场景:

  • 业务类:合同审批流程、订单处理流程、出入库审批流程等。
  • 行政类:请假流程、出差流程、用车流程、办公用品申请流程等。
  • 财务类:报销流程、支付流程等。
  • 客户服务类:售后跟踪、客户投诉等。

1.3 什么是Activiti

Activiti 是由 jBPM (BPM,Business Process Management 即业务流程管理) 的创建者 Tom Baeyens 离开 JBoss 之后建立的项目,构建在开发 jBPM 版本 1 到 4 时积累的多年经验的基础之上,旨在创建下一代的 BPM 解 决方案。 Activiti 是一个开源的工作流引擎,它实现了BPMN 2.0规范,可以发布设计好的流程定义,并通过api进行流程调 度。 Activiti 作为一个遵从 Apache 许可的工作流和业务流程管理开源平台,其核心是基于Java的超快速、超稳定的BPMN2.0 流程引擎,强调流程服务的可嵌入性和可扩展性,同时更加强调面向业务人员。

Activiti 流程引擎重点关注在系统开发的易用性和轻量性上。每一项 BPM 业务功能 Activiti 流程引擎都以服务的形 式提供给开发人员。通过使用这些服务,开发人员能够构建出功能丰富、轻便且高效的 BPM 应用程序。

Activiti是一个针对企业用户、开发人员、系统管理员的轻量级工作流业务管理平台,其核心是使用Java开发的快 速、稳定的BPMN 2.0流程引擎。Activiti是在ApacheV2许可下发布的,可以运行在任何类型的Java程序中,例如服 务器、集群、云服务等。Activiti可以完美地与Spring集成。同时,基于简约思想的设计使Activiti非常轻量级。

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

1.4 Activiti开发流程

1、画流程定义模型:

遵守BPMN的流程规范,使用BPMN的流程定义工具,通过 流程符号 把整个业务流程定义出来,可以将流程定义文件字节流保存到模型数据表中(Model)。 其实用可视化工具画出来的每一个流程图都是一个.bpmn文件,在idea中也可以随时使用插件把bpmn文件进行可视化查看。

2、部署流程定义:

加载画好的流程定义文件,将它转换成流程定义数据(ProcessDefifinition),保存到流程定义数据表中。

3、启动流程(提交流程申请):

生成流程实例数据(ProcessInstance),生成第1个节点的任务数据(Task);

4、处理人审批流程节点任务:

完成任务审批,生成审批结果,生成下一节点任务数据。直至满足条件,流程走到结束节点。

1.5 BPMN 2.0规范是什么

其实就是使用bpmn的规范来定义画流程图,最终会形成一个bpmn文件。

业务流程模型注解(Business Process Modeling Notation - BPMN)是业务流程模型的一种标准图形注解。这个 标准是由对象管理组(Object Management Group - OMG)维护的。

标准的早期版本(1.2版以及之前)仅仅限制在模型上, 目标是在所有的利益相关者之间形成通用的理解, 在文 档,讨论和实现业务流程之上。 BPMN标准证明了它自己,现在市场上许多建模工具都使用了BPMN标准中的元素和结构。 BPMN规范的2.0版本,当前已经处于最终阶段了, 允许添加精确的技术细节在BPMN的图形和元素中, 同时制定 BPMN元素的执行语法。 通过使用XML语言来指定业务流程的可执行语法, BPMN规范已经演变为业务流程的语 言, 可以执行在任何兼容BPMN2的流程引擎中, 同时依然可以使用强大的图形注解。 目BPMN2.0是最新的版本,它用于在BPM上下文中进行布局和可视化的沟通。BPMN 2.0是使用一些符号来明确 业务流程设计流程图的一整套符号规范,它能增进业务建模时的沟通效率。

1.6 BPMN 2.0 基本流程符号

先了解在流程设计中常见的符号:

事件Event

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

活动 Activity

活动是工作或任务的一个通用术语。一个活动可以是一个任务,还可以是一个当前流程的子处理流程; 其次,你还可以为活动指定不同的类型。常见活动如下:

网关 Gateway

网关用来处理决策:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

排他网关(x)

**只有一条路径会被选择。**流程执行到该网关时,按照输出流的顺序逐个计算,当条件的计算结果为true时,继

续执行当前网关的输出流; 如果多条线路计算结果都是 true,则会执行第一个值为 true 的线路。如果所有网关计算结果没有true,则引 擎会抛出异常。 排他网关需要和条件顺序流结合使用,default 属性指定默认顺序流,当所有的条件不满足时会执行默认顺序流。

并行网关(+)

所有路径会被同时选择 。

分支: 并行执行所有输出顺序流,为每一条顺序流创建一个并行执行线路。

汇聚 :所有从并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完成才继续向下执行。

包容网关(o)

可以同时执行多条线路,也可以在网关上设置条件。

分支:计算每条线路上的表达式,当表达式计算结果为true时,创建一个并行线路并继续执行

汇聚:所有从并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完成才继续向下执行。

事件网关(o+)

专门为中间捕获事件设置的,允许设置多个输出流指向多个不同的中间捕获事件。当流程执行到事件网关后,流程处于等待状态,需要等待抛出事件才能将等待状态转换为活动状态。

定时器事件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 开始定时器事件:

    可以设置时间,定时开始启动流程实例。

  • 中间定时器事件:

    设定延迟时间,当完成任务1后,到达延时时间,流程才会走向任务2。

  • 边界定时器事件:

    用于向某节点上添加边界定时事件。在设定时间内没有完成,流程实例则自动走向下一节点。

二、Activiti环境搭建和流程基础入门

2.1 框架版本号

依赖版本
Spring Boot2.5.0
Activiti7.1.0.M6

2.2 JDK

JDK1.8

2.2 MySQL

MySQL5.7

Activiti 通过数据库的数据表来进行控制业务流程,对应支持的数据库如下:

Activiti数据库类型JDBC连接示例备注
h2jdbc:h2:tcp://localhost/activiti默认配置的数据库
mysqljdbc:mysql://localhost:3306/activiti?autoReconnect=true使用mysql-connector- java数据库驱动程序进行 测试
oraclejdbc:oracle:thin:@localhost:1521:xe
postgresjdbc:postgresql://localhost:5432/activiti
db2jdbc:db2://localhost:50000/activiti
mssqljdbc:sqlserver://localhost:1433;databaseName=activiti使用Microsoft JDBC驱动程序4.0(sqljdbc4.jar)和JTDS驱动程序进行了测

在mysql服务器中创建一个activiti01数据库。注意配置好数据库之后,执行流程引擎是会自动创建数据库表的。

2.3 Maven 3.9配置

这里就不粘贴maven的配置了,网上都有各种教程。

2.4 基于 mave 构建项目

  1. 使用 idea 创建一个空工程 study-activiti

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 创建基于maven的项目,项目名: activiti-demo1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.7 pom.xml添加依赖坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mengxuegu</groupId>
    <artifactId>activiti-demo1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <!--activiti核心依赖-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>7.1.0.M6</version>
        </dependency>

        <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

        <!-- 日志  -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.26</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.26</version>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>

</project>

2.8 activiti.cfg.xml核心配置

Activiti流程引擎通过名为的XML文件进行配置 activiti.cfg.xml

在 resources 目录下创建 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必须是processEngineConfiguration -->
    <bean id="processEngineConfiguration"
          class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- 配置数据源 -->
        <property name="jdbcUrl"
                  value="jdbc:mysql://127.0.0.1:3306/activiti01?characterEncoding=utf8&amp;nullCatalogMeansCurrent=true" />
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />

        <!-- activiti 数据库表生成策略 -->
        <!--
            自动更新数据库结构
            true:适用开发环境,默认值。activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建
            false:适用生产环境。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
            create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
            drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
        -->
        <property name="databaseSchemaUpdate" value="true" />
    </bean>
</beans>

注意:防止插入中文数据乱码,要加上字符集 characterEncoding=utf8

如果报错:Table ‘activiti01.act_ge_property’ doesn’t exist

解决:jdbcUrl的后面加上 nullCatalogMeansCurrent=true

2.9 log4j.properties配置日志

如果想在控制台打印执行的sql日志,需要配置日志输出格式等,在 resources 目录下创建 log4j.properties 文件: 注意:记得修改日志文件路径。

log4j.rootCategory=debug, CONSOLE, LOGFILE
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss.SSS} %p [%t] %C.%M(%L) | %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:/03-projectCode/ideaProject/study-activiti/activiti.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

2.10 创建ProcessEngine流程引擎实例和数据表

加载类路径上的 activiti.cfg.xml ,并根据该文件中的配置构造一个流程引擎,和创建数据表。

方式如下:

import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.junit.Test; 
public class ActivitiTest01 { 
 /*** 创建ProcessEngine流程引擎,自动创建 activiti 数据表 */ @Test public void getProcessEngine() { 
     // 方式一:使用activiti提供的工具类ProcessEngines, 
     // 调用 getDefaultProcessEngine 会默认读取resource下的activiti.cfg.xml文件, 
     // 并创建 Activiti 流程引擎 和 创建数据库表 
     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();                  System.out.println(processEngine); 
     // 方式二:以编程方式创建ProcessEngineConfiguration对象 
     // 1. 等同于方式一 
     //ProcessEngineConfiguration configuration =ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault(); //ProcessEngine processEngine = configuration.buildProcessEngine(); 
     // 2. 自定义配置路径和文件名, 但流程引擎bean的id要等于processEngineConfiguration //ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml"); 
     // 3.自定义:配置路径、文件名和流程引擎bean的id //ProcessEngineConfiguration configuration =ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml", "processEngineConfiguration"); } }

2.11 Activiti 25张数据表分析

Activiti 会自动创建25张数据表。(可能不同版本生成的表的数量也会不同。)

数据库表命名

Acitiviti数据库中表的命名都是以 ACT_ 开头的。第二部分是一个两个字符用例表的标识。此用例大体与服务API是

匹配的。

ACT_GE_* GE 表示 general 。通用数据,各种情况都使用的数据 ,如存放资源文件(图片,规则等)。

ACT_HI_xxx : HI 表示history。就是这些表包含着历史的相关数据,如结束的流程实例(变量,任务等)。

ACT_RE_xxx : RE 表示repository。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则 等)。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直 很小速度很快。

ACT_RU_xxx : RU 表示 runtime。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的 数据。Activiti只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的表小且快。

ACT_EVT_EVT表示EVENT,流程引擎的通用事件日志记录表*,方便管理员跟踪处理。

表分类表名说明
通用数据
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_re_deployment部署信息表
act_re_model流程设计模型表
act_re_procdef流程定义数据表
流程运行数据表
act_ru_deadletter_job作业死亡信息表,如果作业失败超过重试次数,则写入到此表
act_ru_event_subscrthrowEvent、catchEvent时间监听信息表
act_ru_execution运行时流程执行实例表
act_ru_identitylink运行时流程人员表,主要存储任务节点与参与者的相关信息
act_ru_integration运行时积分表
act_ru_job定时异步任务数据表
act_ru_suspended_job运行时作业暂停表, 比如流程中有一个定时任务,如果把这个任务停止工作了,这个任务写入到此表中
act_ru_task运行时任务节点表
act_ru_timer_job运行时定时器作业表
act_ru_variable运行时流程变量数据表
其他表
act_procdef_info流程定义的动态变更信息
act_evt_log流程引擎的通用事件日志记录表

完善表字段

  1. Activiti 7的M4以上版本,部署流程定义时,报错如下:

报错: MySQLSyntaxErrorException: Unknown column ‘VERSION_’ in ‘field list’

解决:因为 ACT_RE_DEPLOYMENT 表缺少 VERSION_ 和 PROJECT_RELEASE_VERSION_ 字段,执行以下语句

添加

ALTER TABLE ACT_RE_DEPLOYMENT ADD COLUMN VERSION_ VARCHAR(255); ALTER TABLE ACT_RE_DEPLOYMENT ADD COLUMN PROJECT_RELEASE_VERSION_ VARCHAR(255);

在 Activiti7.1.0.M6已经有了这些,不用执行上面sql。

2.12 Activiti API服务接口

前言

Activiti

Process Engine API 和服务

引擎 API 是与 Activiti 交互的最常见方式。 您可以从ProcessEngine中获取包含工作流/ BPM方法的各种服务。 ProcessEngine和服务对象是线程安全的。因此,您可以为整个服务器保留对其中之一的引用。

Service 是工作流引擎提供用于进行工作流部署、执行、管理的服务接口,我们使用对应Service接口可以操作对应的数据表。也就是说它提供了几个基础的service,里面包含的api供我们对流程进行操作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Activiti7的Servcie核心接口

Service接口说明
RuntimeService运行时 Service,可以处理所有正在运行状态的流程实例和任务等
RepositoryService流程仓库 Service,主要用于管理流程仓库,比如流程定义的控制管理(部 署、删除、挂起、激活…)
DynamicBpmnServiceRepositoryService可以用来部署流程定义(使用xml形式定义好的),一旦 部署到Activiti(解析后保存到DB),那么流程定义就不会再变了,除了修改xml定义文件内容;而DynamicBpmnService就允许我们在程序运行过程中去修改流程定义,例如:修改流程定义中的分配角色、优先级、流程流转的条件。
TaskService任务 Service,用于管理和查询任务,例如:签收、办理等
HistoryService历史Service,可以查询所有历史数据,例如:流程实例信息、参与者信息、完成时间…
ManagementService引擎管理Service,和具体业务无关,主要用于对Activiti流程引擎的管理和维护。
  1. 核心 Service 接口实例获取方式如下:
// 会在首次调用时初始化并构建一个流程引擎,此后始终返回相同的流程引擎。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 
// 引擎管理类
ManagementService managementService = processEngine.getManagementService();
// 动态修改流程管理类
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService(); 
// 流程运行管理类 
RuntimeService runtimeService = processEngine.getRuntimeService(); 
// 流程仓库管理类 
RepositoryService repositoryService = processEngine.getRepositoryService(); 
// 任务管理类
TaskService taskService = processEngine.getTaskService(); 
// 历史管理类
HistoryService historyService = processEngine.getHistoryService(); 
// activiti 7 没有IdentityService和FormService接口 
//IdentityService identityService = processEngine.getIdentityService(); 
// FormService formService = processEngine.getFormService();

三、Activiti流程实操入门

3.1 IDEA安装actiBPM插件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

官网下载地址

3.2 绘制流程定义模型

  1. 在 /resources 目录下创建 processes 目录,用于存放流程图

  2. 创建BPMN文件:右击 processes 目录,点击【New】–>【BpmnFile】

  3. 输入文件名称 leave ,点击【OK】按钮

绘制请假申请流程图

将 xxxx.bpmn 文件放在 /resources/processes/ 目录下,即 /resources/processes/leave.bpmn

  1. 鼠标左键拖拽右侧 开始事件 符号,将其拖下左侧界面上,同样的方式再拖拽其他图标

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 添加人工任务符号,修改 Name 节点名称 领导审批,和 Assignee 节点处理人:meng

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 添加人工任务符号:修改 Name 节点名称:总经理审批,和 Assignee 节点处理人:xue

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 添加结束事件符号

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 流程连线:点击图标的中心,会变成黑白色扇形,拖拽到另一图标,即可连接

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 点击流程图的空白处(不是点击流程符号):

设置当前流程图唯一标签 ID (也称为:流程的KEY):leaveProcess ,流程名称:请假流程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 最后检查,每个人工任务节点的 Name 和 Assignee 是否也上面一致。

3.3 解决中文乱码问题

  1. 打开 Settings 窗口,点击 Editor > File Encodings > 将字符编码均设置为 UTF-8

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 打开idea安装目录,在 idea.exe.vmoptions (32位系统)和 idea64.exe.vmoptions (64位系统)文件最后

追加一行命令。 (C:\User\mengxuegu\.IntelliJIdea\config )

注意:不能有空格,不然idea重启后打不开

-Dfile.encoding=UTF-8
  1. 如果上面修改后,重启idea重新打开bpmn文件,还是乱码,则查找: C:\Users\Administrator\AppData\Roaming\JetBrains\IntelliJIdea2020.

生成png图片

将 bpmn 文件不方便随处打开提供给用户看,为了方便将流程图转成图片格式,方便随处打开演示;

并在部署流程时也需要 png 图片。

  1. 将 leave.bpmn 文件复制一份为 leave.xml

  2. 右击 leave.xml 文件,选择【Diagrams】–>【Show BPMN 2.0 Diagrams…】

  3. 如果找不到 Diagrams ,则重启 IDEA 工具

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 打开后,点击上方导出按钮,保存即可。

  1. 将生成的 leave.png 图片拷贝到 resources/processes 目录下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 可以把 leave.xml 文件删除

3.4 部署流程定义

概述

将上面在设计器中定义的流程部署到activiti数据库中,就是流程定义部署。

一般情况下,流程定义(Process Definition)是在流程设计和开发阶段完成的,它描述了工作流程的规则、流程节点、流程步骤、流程之间的转移条件等信息。流程定义通常以一种特定的格式或者规范进行定义,如 BPMN(Business Process Model and Notation)等。

而流程部署(Process Deployment)是在流程准备运行阶段完成的,它将流程定义部署到流程引擎中以便执行。在流程部署过程中,流程定义会被加载到流程引擎中,并在流程引擎中生成对应的流程实例。

通常流程部署与流程定义是一对多的关系,比如一组相关联的业务可以做成多个流程图定义,然后把他们打包成zip后统一部署。

通过调用activiti的api将流程定义的 .bpm 和 png 两个文件一个一个添加部署到activiti中,也可以将两个文件打成 zip包进行部署。

.bpmn 流程定义文件部署

  1. 代码如下:
package com.mengxuegu.test; 

import org.activiti.engine.*; 
import org.activiti.engine.impl.util.ReflectUtil; 
import org.activiti.engine.repository.Deployment; 
import org.activiti.engine.runtime.ProcessInstance; 
import org.activiti.engine.task.Task; 
import org.activiti.engine.task.TaskQuery; 
import org.junit.Test; 
import java.io.IOException; 
import java.io.InputStream; 

import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.zip.ZipInputStream; 
public class ActivitiTest02 { 
    /*** 部署流程: 
    * 1. ACT_RE_DEPLOYMENT 流程部署表,每执行一次部署,会插入一条记录 
    * 2. ACT_RE_PROCDEF 生成流程定义信息 
    * 其中 ACT_RE_DEPLOYMENT 与 ACT_RE_PROCDEF 表是一对多的关系, 
    * ACT_RE_PROCDEF 每条记录对应一个流程的定义信息(如:小梦、小谷请假申请) 
    * 3. ACT_GE_BYTEARRAY 流程资源表,插入资源数据,当前插入两条记录(.bpmn和.png资源) */ 
    @Test public void deployByFile() {
        // 1. 实例化流程引擎实例 
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 
        // 2. 获取流程定义和部署对象相关的
        Service RepositoryService repositoryService = processEngine.getRepositoryService(); 
        // 3. 创建部署对象进行流程的部署,定义一个流程的名字,把 .bpmn 和 .png 部署到数据库中   
        Deployment deployment = repositoryService.createDeployment() .name("请假申请流程") .addClasspathResource("processes/leave.bpmn") .addClasspathResource("processes/leave.png") .deploy(); 
        // 4. 输出部署信息 
        System.out.println("部署ID:" + deployment.getId() ); 
        System.out.println("部署名称:" + deployment.getName() ); } }

解决报错找不到字段

解决: ACT_RE_DEPLOYMENT 表缺少 VERSION_ 和 PROJECT_RELEASE_VERSION_ 字段,执行下面添加表字

ALTER TABLE ACT_RE_DEPLOYMENT ADD COLUMN VERSION_ VARCHAR(255); ALTER TABLE ACT_RE_DEPLOYMENT ADD COLUMN PROJECT_RELEASE_VERSION_ VARCHAR(255);

.zip 流程定义压缩包部署

将 leave.bpmn和 leave.png 压缩成 leave.zip ,放在类路径下的 processes/leave.zip 。 (所以正如上面所说,部署与定义是一对多的关系)

* 通过zip压缩包部署流程定义 */ 
    @Test public void deployByZip() { 
    // 1. 实例化流程引擎实例 
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 
    // 2. 获取流程定义和部署对象相关的Service
    RepositoryService repositoryService = processEngine.getRepositoryService(); 
    // 3. 流程部署 
    // 读取zip资源包,构成 InputStream 输入流 
    InputStream inputStream = ReflectUtil.getResourceAsStream("processes/leave.zip"); 
    // 封装 ZipInputStream 输入流进行流程部署 
    ZipInputStream zipInputStream = new ZipInputStream(inputStream); 
    Deployment deployment = repositoryService.createDeployment() .addZipInputStream(zipInputStream) .name("请假申请流程-压缩包") .deploy(); 
    // 4. 输出部署信息 
    System.out.println("部署ID:" + deployment.getId()); 
    System.out.println("部署名称:" + deployment.getName() ); }

运行后,压缩包中的 .bpm 文件和 图片文件会保存在activiti数据表中。

部署涉及的数据表

流程定义部署会涉及 activiti 的3张表:

  • act_re_deployment 流程定义部署表,每部署一次增加一条记录
  • act_re_procdef 流程定义表,部署每个新的流程定义都会在这张表中增加一条记录

注意:表中字段 KEY 是不同流程定义的唯一标识。

  • act_ge_bytearray 流程资源表,bpmn的 xml 串和 流程图片,每次增加对应资源数据

注意:

act_re_deployment 和 act_re_procdef 一对多关系,一次部署在流程部署表生成一条记录,但一次部署可以部署 多个流程定义,每个流程定义在流程定义表生成一条记录。每一个流程定义在 act_ge_bytearray 会存在两个资源 记录,bpmn 和 png。

建议:

一次部署一个流程,这样部署表和流程定义表是一对一有关系,方便读取流程部署及流程定义信息。

3.5 查询流程定义

查询部署的流程定义数据 ACT_RE_PROCDEF :

/*** 查询部署的流程定义数据 ACT_RE_PROCDEF */ 
@Test public void getProcessDefinitionList() { 
    // 1. 实例化流程引擎实例 
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 
    // 2. 获取 RepositoryService 
    RepositoryService repositoryService = processEngine.getRepositoryService(); 
    // 3. 获取 ProcessDefinitionQuery 这里的leaveProcess就是画流程图时指定的唯一的key
    ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); List<ProcessDefinition> definitionList = query.processDefinitionKey("leaveProcess") .orderByProcessDefinitionVersion() 
        // 按版本号排序 
        .desc() 
        // 降序 
        .list();
    for (ProcessDefinition pd : definitionList) 
    { 
        System.out.println("流程部署ID:" + pd.getDeploymentId());
        System.out.println("流程定义ID:" + pd.getId()); 
        System.out.println("流程定义Key:" + pd.getKey()); 
        System.out.println("流程定义名称:" + pd.getName()); 
        System.out.println("流程定义版本号:" + pd.getVersion()); 
    }
}

输出内容:

流程部署ID:1

流程定义ID:leaveProcess:1:4

流程定义Key:leaveProcess

流程定义名称:请假流程

流程定义版本号:1

启动流程实例(提交申请)

流程定义部署后,然后可以通过 activiti 工作流管理业务流程了。例如上面部署好了请假流程,可以申请请假了。 针对部署好的流程定义,每次用户发起一个新的请假申请,就对应的启动一个新的请假流程实例;

类似于 java 类与 java 对象(实例)的关系,定义好类后,使用 new 创建一个对象(实例)使用,当然可以 new 多个对象(实例)。

例如:请假流程,小梦发起一个请假申请单,对应的就启动一个针对小梦的新流程实例;小王发起一个请假申请 单,也启动针对小王的新流程实例。

3.6 启动流程实例代码

/** * 启动流程实例(提交申请) */
@Test public void startProcessInstance() {
    // 1. 实例化流程引擎实例 
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 
    // 2. 获取 RuntimeService 
    RuntimeService runtimeService = processEngine.getRuntimeService(); 
    // 开启流程实例 (流程设计图唯一标识key) 
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveProcess"); 
    System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());             System.out.println("流程实例id:" + processInstance.getId()); 
}

输出内容:

流程定义id:leaveProcess:1:4

流程实例id:2501

流程实例涉及的数据表

  • act_hi_actinst 流程实例执行的节点历史信息
  • act_hi_identitylink 流程的参与用户历史信息
  • act_hi_procinst 流程实例历史信息
  • act_hi_taskinst 流程实例的任务历史信息
  • act_ru_execution 流程运行中执行信息
  • act_ru_identitylink 流程运行中参与用户信息
  • act_ru_task 流程运行中任务信息

3.7 查询办理人待办任务

启动流程实例后,每个任务的办理人就可以查询自己当前的待办任务,然后进行办理任务。

/*** 查询指定人员的待办任务 */ 
@Test public void taskListByAssignee() { 
// 1. 实例化流程引擎实例
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 
    // 2. 获取 TaskService 
    TaskService taskService = processEngine.getTaskService(); 
    // 3. 根据流程唯一标识 key 和 任务办理人 查询任务 
    List<Task> list = taskService.createTaskQuery().processDefinitionKey("leaveProcess") 
    .taskAssignee("meng")
    .list(); 
    for (Task task : list) { 
        System.out.println("流程实例id:" + task.getProcessInstanceId());                           System.out.println("任务id:" + task.getId()); 
        System.out.println("任务名称:" + task.getName()); 
        System.out.println("任务办理人:" + task.getAssignee()); 
    } 
}

输出内容:

流程实例id:2501

任务id:2505

任务负责人:meng

任务名称:领导审批

3.8 完成待办任务

任务办理人查询待办任务,将待办任务进行完成。

  1. 先查询 meng 办理人任务,然后完成任务

  2. 再查询 xue 办理人任务,然后完成任务

  3. 这样此流程实例就完成结束。

/*** 完成待办任务 */ @Test public void completeTask() { 
    // 1. 实例化流程引擎实例 
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 
    // 2. 获取 TaskService 
    TaskService taskService = processEngine.getTaskService(); 
    // 3. 根据流程唯一标识 key 和 任务办理人 查询任务 
    Task task = taskService.createTaskQuery() .processDefinitionKey("leaveProcess") 
        // 流程 Key 
       .taskAssignee("meng") 
        // 查询 meng 的任务 
        .taskAssignee("xue") 
        .singleResult(); 
    // 目前只有一条任务,则可以只获取一条 
    // 4. 完成任务(任务id) 
    taskService.complete(task.getId());
}

3.9 查询流程实例历史节点信息

查询流程办理历史信息,通过 HistoryService 历史数据对象来获取 HistoricActivityInstanceQuery 历史节点查询 对象。

/*** 查看流程办理历史信息 */ 
@Test public void historyInfo(){ 
    // 1. 实例化流程引擎实例 
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); 
    // 2. 获取 HistoryService 
    HistoryService historyService = processEngine.getHistoryService(); 
    // 3. 获取节点历史记录查询对象 ACT_HI_ACTINST 表 
    HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery(); 
    // 实例 id 
    String processInstanceId = "10001"; 
    List<HistoricActivityInstance> list = query.processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime() 
        // 根据开始时间排序 asc 升序 
        .asc() 
        .list(); 
    for (HistoricActivityInstance hi : list) {
        System.out.print("流程定义ID: " + hi.getProcessDefinitionId());                             System.out.print(",流程实例ID: " + hi.getProcessInstanceId());                             System.out.print(",节点ID: " + hi.getActivityId()); 
        System.out.print(",节点名称: " + hi.getActivityName()); 
        System.out.print(",任务办理人:" + hi.getAssignee()); 
        System.out.print(",开始时间:" + hi.getStartTime()); 
        System.out.println("结束时间:" + hi.getEndTime()); 
    } 
}

四、SpringBoot 与 Activiti7 整合

测试完基础的功能,终于到了重头戏了,好多网上的文档斌没有教你如何把activi7如何整合到你的实际项目中。

4.1 创建模块 activiti-boot

模块名:activiti-boot

4.2 pom.xml 依赖坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mengxuegu</groupId>
    <artifactId>activiti-boot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/>
    </parent>

    <properties>
        <activiti.version>7.1.0.M6</activiti.version>
        <mybatis-plus.version>3.3.1</mybatis-plus.version>
    </properties>

    <dependencies>
        <!-- Activiti -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- java绘制activiti流程图 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-image-generator</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- activiti json转换器-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- svg转png图片工具-->
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-all</artifactId>
            <version>1.10</version>
        </dependency>

        <!-- web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <!--mybatis-plus启动器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

        <!-- SpringSecurity -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

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

        <!--<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>-->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

4.3 创建application.yml配置文件

  1. 创建 application.yml 文件,activiti 7 相关配置如下:
server:
  port: 8080
  servlet:
    context-path: /workflow

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/activiti-boot?nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowMultiQueries=true
    username: root
    password: root

  # activiti配置
  activiti:
    #自动更新数据库结构
    # true:适用开发环境,默认值。activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建
    # false:适用生产环境。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
    # create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
    # drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
    database-schema-update: true
    # activiti7与springboot整合后默认不创建历史表,需要手动开启
    db-history-used: true
      # 记录历史等级 可配置的历史级别有none, activity, audit, full
      # none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
      # activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
      # audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。
      # full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
    history-level: full
    # 是否自动检查resources下的processes目录的流程定义文件
    check-process-definitions: false
    # smtp服务器地址
    mail-server-host: smtp.qq.com
    # SSL端口号
    mail-server-port: 465
    # 开启ssl协议
    mail-server-use-ssl: true
    # 默认的邮件发送地址(发送人),如果activiti流程定义中没有指定发送人,则取这个值
    mail-server-default-from: w736486962@qq.com
    # 邮件的用户名
    mail-server-user-name: w736486962@qq.com
    # qq的smtp服务相关的授权码
    mail-server-password: xxx填写自己qq邮箱的smtp授权码
    # 关闭不自动添加部署数据 SpringAutoDeployment
    #deployment-mode: never-fail

# 日志级别是debug才能显示SQL日志
logging:
  level:
    org.activiti.engine.impl.persistence.entity: debug

4.4 创建数据库activiti-boot

只有你自己创建了数据库建立了驱动连接,才会自动生成工作流的表。这里就不讲解怎么创建数据库了。

4.5 整合SpringSecurity

  1. activiti7 与 SpringSecurity 强耦合,

创建安全认证配置类 com.mengxuegu.config.SpringSecurityConfig 类

注意:activiti7 任务办理人,必须是当前可查询到的用户名

package com.mengxuegu.workflow.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.provisioning.UserDetailsManager;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    private Logger logger = LoggerFactory.getLogger(SpringSecurityConfig.class);

    /**
     * 内存 UserDetailsManager
     */
    @Bean
    public UserDetailsService myUserDetailsService() {
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        // 初始化账号角色数据
        addGroupAndRoles(inMemoryUserDetailsManager);
        return inMemoryUserDetailsManager;
    }

    private void addGroupAndRoles(UserDetailsManager userDetailsManager) {
        // 注意:后面流程办理人,必须是当前存在的用户 username,这些都是为了后面指定流程班里人做准备
        String[][] usersGroupsAndRoles = {
                {"meng", "123456", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"xue", "123456", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"gu", "123456", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
                {"小梦", "123456", "ROLE_ACTIVITI_ADMIN", "GROUP_otherTeam"},
                {"小学", "123456", "ROLE_ACTIVITI_ADMIN", "GROUP_otherTeam"},
                {"小谷", "123456", "ROLE_ACTIVITI_ADMIN", "GROUP_otherTeam"}
        };

        for (String[] user : usersGroupsAndRoles) {
            List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
            logger.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
            userDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),
                    authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
        }
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

4.6 创建启动类

创建项目启动类 com.mengxuegu.workflflow.WorkFlowApplication

package com.mengxuegu.workflow; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication 
public class WorkFlowApplication { 
    public static void main(String[] args) { 
        SpringApplication.run(WorkFlowApplication.class, args);                               } 
}

4.7 测试Activiti流程

相关的 Activiti 服务接口,都直接依赖注入即可使用。

  1. 将上面的 activiti-demo1 工程中绘制的bpmn流程图文件,拷贝如下工程的 resources 目录下

  1. 在 src/test 目录下创建测试类 com.mengxuegu.workflflow.test.ActivitiTest01
package com.mengxuegu.workflow.test; 
import org.activiti.engine.ProcessEngine; 
import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; 
import org.junit.jupiter.api.Test; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
@SpringBootTest public class ActivitiTest01 {
    @Autowired ProcessEngine processEngine; 
    @Autowired RepositoryService repositoryService;
    /*** 获取 ProcessEngine 流程引擎,自动创建 activiti 数据表 */ 
    @Test public void getProcessEngine() { 
        // 获取 Activiti 流程引擎 和 创建数据库表, 
        // 并在 ACT_RE_DEPLOYMENT 插入一条无用的数据 
        SpringAutoDeployment System.out.println(processEngine); 
    }
    /*** 部署流程: */ 
    @Test public void deployByFile() { 
        // 1. 创建部署对象进行流程的部署,定义一个流程的名字,把 .bpmn 和 .png 部署到数据库中 
        Deployment deployment = repositoryService.createDeployment() .name("请假申请流程") .addClasspathResource("processes/leave.bpmn") .addClasspathResource("processes/leave.png") .deploy(); 
        // 2. 输出部署信息 
        System.out.println("部署ID:" + deployment.getId() ); 
        System.out.println("部署名称:" + deployment.getName() ); 
    } 
}

如果报错如下:

Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'

Cause: java.sql.SQLSyntaxErrorException: Unknown column 'PROJECT_RELEASE_VERSION_' in 'field

解决: ACT_RE_DEPLOYMENT 表缺少 VERSION_ 和 PROJECT_RELEASE_VERSION_ 字段,执行下面添加表字

ALTER TABLE ACT_RE_DEPLOYMENT ADD COLUMN VERSION_ VARCHAR(255); ALTER TABLE ACT_RE_DEPLOYMENT ADD COLUMN PROJECT_RELEASE_VERSION_ VARCHAR(255);

五、整合流程模型设计器Activiti Modeler

为什么要整合

上面我们在 idea 上设计的流程模型,而每次要设计都要打开 idea 或其他设计流程工具来进行操作,这样不太方 便。 而实际上 Activiti 官方提供了 Web 版的流程设计工具 Activiti Modeler,可以直接整合到我们项目中。

在 Activiti 5.10 版本把原本独立的 Activiti Modeler 模块整合到了 Activiti Explorer 模块中,两者相结合使用起来 很方便, 通过 Modeler 设计的流程模型可以直接部署到引擎,也可以把已经部署的流程转换为Model从而在Modeler中编 辑。 在实际应用中也有这样的需求,把 Modeler 整合到业务系统中可以供管理员使用,或者作为BPM流程管理平台的 一部分存在。

但是在 Activiti 官方没有给出如何整合Modeler的文档,要我们自己整合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.1 下载源码

首先需要从 Github下载 Activiti 5.22 版本源码

访问:https://github.com/Activiti/Activiti/releases/tag/activiti-5.22.0

下载 zip 格式的压缩包:https://github.com/Activiti/Activiti/archive/activiti-5.22.0.zip

如果解压过程中出现文件名过程问题可以换一个解压软件,比如7Zip。

5.2 拷贝目标源码

  1. 解压 Activiti-activiti-5.22.0.zip ,然后进入 Activiti-activiti-5.22.0/modules 目录,

  2. 复制 activiti-webapp-explorer2 工程中如下图画红框的文件夹和文件,

粘贴到 activiti-boot 工程的 resources/static 目录下(static 目录创建)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 找到 activiti-modeler 工程下的 3个类,如下:

拷贝到 com.mengxuegu.workflflow.activiti 包下面,如下图:

5.3 修改上下文路径

  1. 找到 static/editor-app/confifiguration/url-confifig.js ,修改文件中的项目上下文路径,这样才能请求到上面的3 个接口

上下文路径对应 application.yml 文件中配置的 server.servlet.context-path=/workflow

在前端请求接口路径配置文件可参见:static/editor-app/confifiguration/url-confifig.js,

ACTIVITI.CONFIG = { 
'contextRoot' : '/workflow' // '/activiti-explorer/service', 
};

5.4 汉化Activiti Modeler

汉化文件为两个json文件stencilset.jsonzh-CN.json

需要的自取:

链接:https://pan.baidu.com/s/1az50zQQ6U-o-owqOfgt3RQ
提取码:1111

  1. 汉化页面文字, resources/static/ 目录下添加 stencilset.json 文件

  2. 需要修改 StencilsetRestResource.java 类中 stencilset.jsonstatic/stencilset.json (最前面不

要有 / );

InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("static/stencilset.json");

  1. 汉化按钮文字,添加zh-CN.json 文件

resources/static/editor-app/i18n 目录下添加 zh-CN.json 文件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

修改 resources/static/editor-app/app.js 文件,将第51行的 $translateProvider.preferredLanguage(‘en’); 替换为以下内容:

// $translateProvider.preferredLanguage('en'); 
// 多语言支持 
if("zh-CN" == navigator.language){ 
    $translateProvider.preferredLanguage('zh-CN'); 
}else { 
    $translateProvider.preferredLanguage('en'); 
}

启动项目时报错:

Error:Kotlin: Module was compiled with an incompatible version of Kotlin. The binary version of

its metadata is 1.5.1, expected version is 1.1.16.

解决:如下图重新编译下,然后再启动项目

5.5 创建空的流程模型

  1. 创建一个 ModelController 模型控制器,用于创建空流程模型和跳转到模型设计页面 modeler.html
package com.mengxuegu.workflow.controller; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.node.ObjectNode; 
import org.activiti.editor.constants.ModelDataJsonConstants; 
import org.activiti.engine.RepositoryService; 
import org.activiti.engine.repository.Model; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.*; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse;
/*** 流程模型管理 */ 
@Controller 
@RequestMapping("/model") 
public class ModelController {
    @Autowired RepositoryService repositoryService;
    @Autowired ObjectMapper objectMapper;
    /*** 创建空模型窗口: 
    * 创建模型对象 
    * 设置对象值 
    * 存储模型对象(表act_re_model) 
    * 存储模型对象基础数据(表act_ge_bytearray) 
    * 跳转到ActivitiModeler,编辑流程图,存储流程图片和流程定义等(表act_ge_bytearray) 
    */ 
    @GetMapping("/create") 
    public void create(HttpServletRequest request, HttpServletResponse response) {
        try {
            String name = "请假流程模型"; 
            String key = "leaveProcess"; 
            String desc = "请输入描述信息~"; 
            int version = 1; 
            //初始化一个空模型 
            Model model = repositoryService.newModel(); 
            model.setName(name); 
            model.setKey(key); 
            model.setVersion(version); 
            // 封裝模型json对象 
            ObjectNode modelObjectNode = objectMapper.createObjectNode();                             modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name);                             modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 0);                           modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, desc);                     model.setMetaInfo(modelObjectNode.toString()); 
            // 存储模型对象(表 ACT_RE_MODEL ) 
            repositoryService.saveModel(model); 
            // 封装模型对象基础数据json串 {"id":"canvas","resourceId":"canvas","stencilset": {"namespace":"http://b3mn.org/stencilset/bpmn2.0#"},"properties":{"process_id":"未定义"}} 
            ObjectNode editorNode = objectMapper.createObjectNode(); 
            //editorNode.put("resourceId", "canvas"); 
            ObjectNode stencilSetNode = objectMapper.createObjectNode();                             stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");                   editorNode.replace("stencilset", stencilSetNode); 
            // 标识key 
            ObjectNode propertiesNode = objectMapper.createObjectNode();                             propertiesNode.put("process_id", key); 
            editorNode.replace("properties", propertiesNode); 
            // 存储模型对象基础数据(表 ACT_GE_BYTEARRAY )                                 
            repositoryService.addModelEditorSource(model.getId(),                                     editorNode.toString().getBytes("utf-8")); 
            // 编辑流程模型时,只需要直接跳转此url并传递上modelId即可                     
            response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + model.getId()); 
        } catch (Exception e) {
            e.printStackTrace(); 
        }
    }
}
  1. 重启mengxuegu-activiti-boot项目,

  2. 访问 http://localhost:8080/workflflow/model/create ,

会重定向到 http://localhost:8080/workflflow/modeler.html?modelId=xxxxxxxx

如果按钮文字是英文,而不是中文,则清除缓存重新打开浏览器访问 。

5.6 绘制请假流程定义模型

绘制流程定义模型涉及表

  • ACT_RE_MODEL 流程模型基本信息表
  • ACT_GE_BYTEARRAY 流程模型描述 json 串(注意不是xml串)和 流程图字节码。

1、绘制请假流程:

领导审批:办理人 meng

总经理审批:办理人 xue

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 点击 保存 按钮,会将绘制的 流程图 提交给后台进行保存操作(当前会报400错误,提交不成功)

保存请求路径:http://localhost:8080/workflflow/model/{modelId}/save

  1. 上面点击保存,会报400错误,

原因: ModelSaveRestResource 类中使用 @RequestBody MultiValueMap 接收参数无法接收到。

解决:将 @RequestBody MultiValueMap 改为 @RequestParam MultiValueMap ,如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 重启项目,再次保存测试 ok

六、流程定义模型管理Model

上面已经整合Web 端Activiti Modeler流程模型设计器,并完成创建和保存流程模型设计图。 下面对流程定义模型进行查询、删除、导出模型zip压缩包、xml 文件、部署流程定义。

6.1 查询已绘制的所有流程模型数据:

package com.mengxuegu.workflow.test; 

import org.activiti.engine.RepositoryService; 
import org.activiti.engine.repository.Model; 
import org.activiti.engine.repository.ModelQuery; 
import org.junit.jupiter.api.Test; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
import java.util.List; 
@SpringBootTest 
public class ActivitiTest02Model { 
    @Autowired RepositoryService repositoryService;
    /*** 查询所有流程模型 ACT_RE_MODEL */ 
    @Test public void modelList() { 
        // 获取模型查询对象 
        ModelQuery query = repositoryService.createModelQuery(); 
        // 按模型创建时间 降序 排列 
        List<Model> list = query.orderByCreateTime() .desc() .list();
        for (Model model : list) {
            System.out.print("模型id:" + model.getId()); 
            System.out.print(",模型名称:" + model.getName()); 
            System.out.print(",模型描述:" + model.getMetaInfo()); 
            System.out.print(",模型标识key:" + model.getKey()); 
            System.out.print(",模型版本号:" + model.getVersion()); 
            System.out.print(",创建时间:" + model.getCreateTime()); 
            System.out.println("更新时间:" + model.getLastUpdateTime()); 
        } 
    } 
}

6.2 删除流程模型

通过模型ID删除模型:

/*** 删除模型: * 涉及表:ACT_RE_MODEL、ACT_GE_BYTEARRAY */ 
@Test public void deleteModel(){ 
    // 模型id 
    String id = "f2cd384f-c826-11eb-bbf0-2abb00fc727d";                                       repositoryService.deleteModel(id);
    System.out.println("删除成功"); 
}

6.3 导出下载模型图zip压缩包

导出下载模型图zip压缩包,压缩包中有 .bpmn20.xml 流程描述和 .png 图片资源, 在流程部署时,可以使用上传流程模型图zip压缩包进行部署.

/*** 导出下载模型图zip压缩包(.bpmn20.xml流程描述和.png图片资源) */ 
@Test public void exportZip() throws Exception{ 
    // 模型id 
    String id = "1c3b7d73-c833-11eb-98fd-ee5b4f08d062"; 
    // 查询模型信息 
    Model model = repositoryService.getModel(id); 
    if(model != null) { 
        // 获取流程图 json 字节码 
        byte[] bpmnJsonBytes = repositoryService.getModelEditorSource(id); 
        // 流程图 json 字节码转 xml 字节码
        byte[] xmlBytes = bpmnJsonToXmlBytes(bpmnJsonBytes); 
            if(xmlBytes == null) { 
                System.out.println("模型数据为空-请先设计完整流程-再导出"); }else 
            { 
                // 压缩包文件名 
                String zipName = model.getName() + "." + model.getKey() + ".zip"; 
                // 文件输出流 
                File file = new File("D:/" + zipName); 
                FileOutputStream outputStream = new FileOutputStream(file); 
                // 实例化zip压缩对象输出流 
                ZipOutputStream zipos = new ZipOutputStream(outputStream); 
                // 指定压缩包里的 name.bpmn20.xml 文件名 
                zipos.putNextEntry(new ZipEntry(model.getName() + ".bpmn20.xml")); 
                // 将xml写入压缩流 
                zipos.write(xmlBytes); 
                // 查询png图片, 
                byte[] pngBytes = repositoryService.getModelEditorSourceExtra(id); if(pngBytes != null) { 
                // 指定压缩包里的 name.key.png 文件名 
                zipos.putNextEntry(new ZipEntry(model.getName() + "." + model.getKey() + ".png")); 
                // 图片文件写到压缩包中 
                zipos.write(pngBytes); 
       }
                zipos.closeEntry(); 
                zipos.close(); 
                System.out.println("导出成功"); 
            } 
    }else  { 
        System.out.println("模型不存在");
    } 
}


    @Autowired ObjectMapper objectMapper; 
/*** 流程图保存的时候是json串,引擎认识的却是符合bpmn2.0规范的xml, 
* json 字节码转 xml 字节码 
* @param jsonBytes * @return 
*/ 
private byte[] bpmnJsonToXmlBytes(byte[] jsonBytes) throws IOException { 
    if(jsonBytes == null) {
        return null; 
    }
    // json转回BpmnModel对象 
    JsonNode modelNode = objectMapper.readTree(jsonBytes); 
    BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(modelNode);            if(bpmnModel.getProcesses().size() == 0) {
        return null;
    }
    // BpmnModel对象转xml字节数组 
    return new BpmnXMLConverter().convertToXML(bpmnModel); 
}

运行后,生成 请假流程模型.leaveProcess.zip 压缩后,解压后如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6.4 导出下载模型 xml 文件

在流程部署时,可以只上传流程模型图 xml 文件进行部署

/*** 导出下载模型 xml 文件 */ 
@Test public void exportXml() throws Exception{
    // 模型id 
    String id = "1c3b7d73-c833-11eb-98fd-ee5b4f08d062"; 
    ByteArrayInputStream in = null; 
    // 获取流程图 json 字节码 
    byte[] bytes = repositoryService.getModelEditorSource(id); 
    // json转xml字节数组 
    String filename = null; 
    if(bytes != null) {
        JsonNode modelNode = objectMapper.readTree(bytes);
        BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(modelNode);                 if(bpmnModel.getProcesses().size() != 0) { 
            // 转xml字节数组 
            byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(bpmnModel); in = new ByteArrayInputStream(bpmnBytes);
            // 如果流程名称为空,则取流程定义key 
            filename = StringUtils.isEmpty(bpmnModel.getMainProcess().getName()) ? bpmnModel.getMainProcess().getId() : bpmnModel.getMainProcess().getName(); 
        } 
    }if(filename == null) {
        filename = "模型数据为空,请先设计流程,再导出"; 
        in = new ByteArrayInputStream(filename.getBytes("UTF-8")); 
    }
    // 文件输出流 
    FileOutputStream out = new FileOutputStream(new File("D:/" + filename + ".bpmn20.xml"));
    // 输入流,输出流的转换 
    IOUtils.copy(in, out); 
    // 关闭流
    out.close(); 
    in.close(); 
    System.out.println("下载模型 xml 文件成功"); 
}

运行后,生成文件: 请假申请流程.bpmn20.xml

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过模型数据 部署 流程定义

注意事项:

每个流程定义模型可以多次流程定义部署,activiti 通过流程定义模型中的标识 key 来判断是否为同一流程模型, 相同标识key则视为同一流程定义模型。

相同的标识key流程定义模型,每部署一次对应的新增一条流程定义数据,对应流程定义版本号会基于之前的加1。

上面注意事项,针对下一章讲解的通过 zip 和 xml 文件进行部署流程定义也是要一样的。

/** 
* 通过流程模型 进行 流程定义部署 
* 流程图保存的时候是json串,引擎认识的却是符合bpmn2.0规范的xml, 
* 所以在首次的部署的时候要将json串转换为BpmnModel, 
* 再将BpmnModel转换成xml保存进数据库,以后每次使用就直接将xml转换成BpmnModel,
* 这套操作确实有点啰嗦,实际项目中如果不用activiti自带的设计器,可以考虑用插件,直接生成的是 xml,
* 或者自己开发设计器,在后端生成节点及其属性,引擎有现成的节点实体,如:开始节点StartEvent, 线SequenceFlow等。
* 涉及表: 
* ACT_RE_PROCDEF 新增数据: 流程定义数据 
* ACT_RE_DEPLOYMENT 新增数据: 流程部署数据 
* ACT_GE_BYTEARRAY 新增数据:将当前流程图绑定到此流程定义部署数据上 
* ACT_RE_MODEL 更新部署id 
*/ 
@Test public void deploy() throws Exception {
    // 模型id 
    String id = "1c3b7d73-c833-11eb-98fd-ee5b4f08d062"; 
    // 获取流程图 json 字节码 
    byte[] jsonBytes = repositoryService.getModelEditorSource(id); 
    if (jsonBytes == null) {
        System.out.println("模型数据为空,请先设计流程并成功保存,再进行发布。");
        return;
    }
    // 转xml字节数组
    byte[] xmlBytes = bpmnJsonToXmlBytes(jsonBytes); 
    if(xmlBytes == null){
        System.out.println("数据模型不符要求,请至少设计一条主线流程。"); 
        return; 
    }
    // 流程图片字节码 
    byte[] pngBytes = repositoryService.getModelEditorSourceExtra(id); 
    // 获取模型
    Model model = repositoryService.getModel(id); 
    // 流程定义xml名称
    String processName = model.getName() + ".bpmn20.xml"; 
    // 流程定义png名称
    String pngName = model.getName() +"." + model.getKey() + ".png"; 
    // 流程部署 
    Deployment deployment = repositoryService.createDeployment() .name(model.getName()) .addString(processName, new String(xmlBytes, "UTF-8"))
        // xml文件 
        .addBytes(pngName, pngBytes ) 
        // 图片
        .deploy(); 
    // 更新 部署id 到模型对象(将模型与部署数据绑定) 
    model.setDeploymentId(deployment.getId()); 
    repositoryService.saveModel(model); 
    System.out.println("部署完成"); 
}

部署流程定义涉及表:

  • ACT_RE_PROCDEF 新增数据: 流程定义数据
  • ACT_RE_DEPLOYMENT 新增数据: 流程部署数据
  • ACT_GE_BYTEARRAY 新增数据:流程定义 xml 和 png 保存下来,对应绑定到此流程定义数据上
  • ACT_RE_MODEL 更新部署id

部署流程报错:

  1. 报错:元素 ‘sequenceFlow’ 中必须包含属性 ‘targetRef’

解决:流程唯一标识 不能以数字开头,以字母开头

  1. 报错:元素’sequenceFlow’ 中必须包含属性’sourceRef’

解决:两个图标箭头连线,箭头来源和目标多拉一点到图标上。

(Ctrl+A全选流程设计图,移动一下哪根连线没动说明这根有问题)

七、流程定义部署管理 Deployment

概要

通过流程定义模型,进行部署流程定义,部署后会生成流程定义数据(相当于java类),此时生成的流程定义数据

主要用于生成流程实例(相当于java对象),一个流程定义 Java 类对应的可以创建无数个 java 流程实例对象。

7.1 通过 .zip 压缩包 部署 流程定义

package com.mengxuegu.workflow.test;
import org.activiti.engine.RepositoryService; 
import org.activiti.engine.repository.DeploymentBuilder; 
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
import java.io.*; 
import java.util.zip.ZipInputStream; 
@SpringBootTest 
public class ActivitiTest03Deployment { 
    @Autowired RepositoryService repositoryService;
    /*** 通过 .zip 流程压缩包进行部署的流程定义 */ 
    @Test public void deployByZip() throws Exception { 
        File file = new File("D:/请假流程模型.leaveProcess.zip"); 
        String filename = file.getName();
        // 压缩包输入流
        ZipInputStream zipis = new ZipInputStream(new FileInputStream(file));
        // 创建部署实例 
        DeploymentBuilder deployment = repositoryService.createDeployment(); 
        // 添加zip流 
        deployment.addZipInputStream(zipis); 
        // 部署名称 
        deployment.name(filename.substring(0, filename.indexOf(".")));
        // 执行部署流程定义
        deployment.deploy(); 
        System.out.println("zip压缩包方式部署流程定义完成"); 
    }

部署流程定义涉及表:

ACT_RE_PROCDEF 新增数据: 流程定义数据
ACT_RE_DEPLOYMENT 新增数据: 流程部署数据 
ACT_GE_BYTEARRAY 新增数据:将当前流程图绑定到此流程定义部署数据上 
ACT_RE_MODEL 更新部署id

7.2 通过 .bpmn 或 .bpmn.xml 文件 部署 流程定义

/**
* 通过 .bpmn 或 .bpmn20.xml 流程文件进行部署的流程定义 
* 缺陷:没有png流程图 
*/ 
@Test
public void deployByBpmnFile() throws Exception { 
    // .bpmn 文件 
    File file = new File("D:/leave.bpmn"); 
    // .bpmn20.xml 文件 
    //File file = new File("D:/请假流程模型.bpmn20.xml"); 
    String filename = file.getName(); 
    // 输入流 
    FileInputStream input = new FileInputStream(file); 
    // 创建部署实例
    DeploymentBuilder deployment = repositoryService.createDeployment(); 
    // bpmn20.xml 或 .bpmn (activiti5.10版本以上支持) 
    deployment.addInputStream(filename, input); 
    // 部署名称
    //deployment.name(filename.substring(0, filename.indexOf("."))); 
    // 执行流程定义部署 
    deployment.deploy(); System.out.println("通过 .bpmn 或 .bpmn20.xml 部署完成"); 
}

7.3 删除流程定义部署信息

/**
* 根据部署ID删除流程定义部署信息:
* ACT_GE_BYTEARRAY、
* ACT_RE_DEPLOYMENT、
* ACT_RU_IDENTITYLINK、 
* ACT_RE_PROCDEF、 
* ACT_RU_EVENT_SUBSCR 
*/ 
@Test 
public void delete() {
    try {
        // 部署ID 
        String deploymentId = "9a14702d-c996-11eb-8eef-02466359b284"; 
        // 不带级联的删除:如果有正在执行的流程,则删除失败抛出异常;不会删除 ACT_HI_和 历史表数据  
        repositoryService.deleteDeployment(deploymentId); 
        // 级联删除:不管流程是否启动,都能可以删除;并删除历史表数据。                            
        //repositoryService.deleteDeployment(deploymentId, true);
        System.out.println("删除流程定义部署信息成功"); 
    } catch (Exception e) {
        e.printStackTrace(); 
        if(e.getMessage().indexOf("a foreign key constraint fails") > 0) {                             System.out.println("有正在执行的流程,不允许删除"); 
       }else { 
            System.out.println("删除失败,原因:" + e.getMessage());
            }
    } 
}

八、流程定义管理 ProcessDefifinition

概要

部署好流程定义后,则可以进行查询、激活(启动)、挂起(暂停)、删除流程定义数据(上面讲的删除流程定义 部署信息就是),下载流程定义对应的 xml文件和 png 文件。

8.1 分页条件查询流程定义

package com.mengxuegu.workflow.test;
import org.activiti.engine.RepositoryService; 
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.junit.jupiter.api.Test; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List; 
@SpringBootTest 
public class ActivitiTest04ProcessDefinition {
    @Autowired RepositoryService repositoryService;
    /**
    * 查询部署的流程定义数据 ACT_RE_PROCDEF
    * 需求:如果有多个相同流程定义标识key的流程时,只查询其最新版本 
    */ 
    @Test 
    public void getProcessDefinitionList() { 
        // 1. 获取 ProcessDefinitionQuery 
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); 
        // 条件查询 
        query.processDefinitionNameLike("%请假%"); 
        // 有多个相同标识key的流程时,只查询其最新版本
        query.latestVersion(); 
        // 按流程定义key升序排列
        query.orderByProcessDefinitionKey()
            .asc();
        // 当前查询第几页 
        int current = 1; 
        // 每页显示多少条数据 
        int size = 5; 
        // 当前页第1条数据下标 
        int firstResult = (current-1) * size; 
        // 开始分页查询
        List<ProcessDefinition> definitionList = query.listPage(firstResult, size); 
        for (ProcessDefinition pd : definitionList) {
            System.out.print("流程部署ID:" + pd.getDeploymentId());
            System.out.print(",流程定义ID:" + pd.getId()); 
            System.out.print(",流程定义Key:" + pd.getKey()); 
            System.out.print(",流程定义名称:" + pd.getName());
            System.out.print(",流程定义版本号:" + pd.getVersion());
            System.out.println(",状态:" + (pd.isSuspended() ? "挂起(暂停)": "激活(开启)") );
        }
        // 用于前端显示页面,总记录数
        long total = query.count(); 
        System.out.println("满足条件的流程定义总记录数:" + total); 
    } 
}

8.2 激活或挂起流程定义

  • 流程定义被挂起:此流程定义下的所有流程实例不允许继续往后流转了,就被停止了。

  • 流程定义被激活:此流程定义下的所有流程实例允许继续往后流转。

  • 为什么会被挂起?

    可能当前公司的请假流程发现了一些不合理的地方,然后就把此流程定义挂起。

流程不合理解决办法:

  • **方式一:**可以先挂起流程定义,然后更新流程定义,然后激活流程定义。
  • **方式二:**挂起了就不激活了,重新创建一个新的请假流程定义。
/**
* 通过流程定义id,挂起或激活流程定义
*/ 
@Test 
public void updateProcessDefinitionState() { 
    // 流程定义ID
    String definitionId = "leaveProcess:2:b9227310-c8f4-11eb-acbf-aa2e2e85fc05"; 
    // 流程定义对象
    ProcessDefinition processDefinition =repositoryService.createProcessDefinitionQuery()
        .processDefinitionId(definitionId) 
        .singleResult();
    // 获取当前状态是否为:挂起 
    boolean suspended = processDefinition.isSuspended(); 
    if (suspended) { 
        // 如果状态是:挂起,将状态更新为:激活, 
        // 参数1: 流程定义id;参数2:是否级联激活该流程定义下的流程实例;参考3:设置什么时间激活这 个流程定义,如果 null 则立即激活) 
        repositoryService.activateProcessDefinitionById(definitionId, true, null);
    } else { 
        // 如果状态是:激活,将状态更新为:挂起 
        // 参数 (流程定义id,是否挂起,激活时间) 
        repositoryService.suspendProcessDefinitionById(definitionId, true,null); 
    } 
}

对应 act_re_procdef 表中的 SUSPENSION_STATE_ 字段,1是激活,2是挂起

8.3 下载流程定义的 xml 和 png 文件

下载流程定义的 xml 和 png 文件,方便用户浏览当前流程定义是怎样的。

/**
* 导出下载流程定义想着文件(.bpmn20.xml流程描述或.png图片资源) 
*/ 
@Test 
public void exportProcessDefinitionFile() throws Exception{ 
    // 流程定义ID 
    String definitionId = "leaveProcess:2:b9227310-c8f4-11eb-acbf-aa2e2e85fc05"; 
    // 查询流程定义数据
    ProcessDefinition processDefinition = repositoryService.getProcessDefinition(definitionId); 
    // xml 文件名
    //String filename = processDefinition.getResourceName(); 
    // png 图片名
    String filename = processDefinition.getDiagramResourceName(); 
    // 获取对应文件输入流 
    InputStream input = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), filename);
    // 创建输出流
    File file = new File("/Users/mengxuegu/" + filename); 
    FileOutputStream output = new FileOutputStream(file); 
    // 流拷贝
    IOUtils.copy(input, output); 
    // 关闭流 
    input.close(); 
    output.close(); 
    System.out.println("流程定义文件导出成功:" + filename);
}

由于文章字数限制,后续会有继续的更新,请关注订阅专栏~

### 回答1: Spring Boot Activity是个开源的流程引擎,可以用来设计、执行和监控各种业务流程。下面是使用Spring Boot Activity进行工作流程建模的般步骤: 1. 定义流程模型 使用Activiti Modeler或Eclipse插件Activiti Designer来设计流程模型,可以使用BPMN 2.0规范中的图形符号来描述活动、事件、网关和流程顺序等。 2. 部署流程定义 将流程模型部署到Activiti引擎中,这可以通过Activiti REST API或Java API来完成。 3. 开始流程实例 当需要启动个新的流程实例时,可以使用Activiti REST API或Java API调用引擎,启动新的流程实例。 4. 执行任务 在流程中定义的任务将自动分配给相应的参与者或组,他们可以通过Activiti Task App或自定义的前端应用程序来完成任务。 5. 监控流程实例 可以使用Activiti Admin App或自定义的监控应用程序来跟踪流程实例的状态,查看运行时数据和日志。 6. 终止流程实例 当流程执行完成或需要终止时,可以使用Activiti REST API或Java API调用引擎,终止流程实例。 以上是使用Spring Boot Activity进行工作流程建模的般步骤。具体的实现过程可能会因应用场景和需求而有所不同。 ### 回答2: Spring Boot Activity是个开源的工作流引擎,它能够处理业务流程和任务流程,帮助用户高效地管理工作流程。Spring Boot Activity结合了Spring BootActiviti两个框架,提供了高效的工作流解决方案。下面从以下四个方面介绍Spring Boot Activity工作流。 1. 优点 Spring Boot Activity工作流具有以下优点: a. 基于开源的Activiti,免费且广受欢迎。 b. 结合Spring Boot,可以更好地实现开发者的快速开发和部署需求。 c. 采用Spring的约定配置和开发模式,使得开发者可以专注于业务逻辑的实现。 d. 支持多种流程定义及部署方式,包括BPMN、XML等方式,同时也支持流程图和流程模型的设计。 e. 提供了丰富的API和事件,方便开发者二次开发。 2. 核心概念 Spring Boot Activity工作流有几个重要的核心概念,这些概念构成了整个工作流系统的基础。包括: a. 流程定义(Process Definition):工作流的定义、流程图设计等。 b. 流程实例(Process Instance):根据流程定义,生成的具体的实例,用于执行具体的业务逻辑。 c. 任务(Task):流程的基本单位,个流程由多个任务组成。 d. 执行人(Assignee):任务的执行者,可以是个人或组。 3. 工作流引擎 Spring Boot Activity工作流引擎是整个系统的核心,它负责管理流程定义、流程实例、任务的创建、分配和执行。其中包括以下几个重要的模块: a. 引擎配置(Engine Configuration):引擎的配置信息,包括数据源、数据库方言等。 b. 流程定义存储(Process Definition Repository):负责持久化流程定义信息。 c. 流程实例引擎(Process Instance Engine):用于创建和管理流程实例。 d. 任务引擎(Task Engine):用于创建和管理任务的创建、分配和执行。 4. 实现步骤 Spring Boot Activity工作流的实现步骤包括: a. 添加Spring BootSpring Boot Activity的依赖。 b. 在应用程序的配置文件中配置工作流引擎,包括数据源、数据库方言等。 c. 设计工作流程图并导入到工作流引擎。 d. 实现业务逻辑并与工作流引擎进行交互,包括创建和管理流程实例、任务分配和执行等。 总之,Spring Boot Activity是个简单易用的工作流框架,基于Spring BootActiviti两个框架开发而成。它可以很好地解决工作流的需求,提高工作效率和业务运营效益。 ### 回答3: Spring Boot Activity工作流框架是Spring BootActiviti的结合,是种基于Java语言实现的工作流管理系统。该框架以Activiti为核心组件,通过Spring Boot提供的便捷的Spring框架支持,提供了快速构建流程管理系统的能力。因此,Spring Boot Activity工作流在企业应用领域有着广泛的应用价值。 工作流是个由各种不同的业务流程、规则和机制构成的自动化过程,通过使用工作流提高业务的过程化效率,减少时间和成本,从而提高企业的生产效率和质量。使用工作流管理系统可以使企业管理变得更加透明化,方便了业务流程的管理和优化。 Spring Boot Activity工作流提供了个简单易用的开发工具,可以通过XML(或Java),定义和管理业务模型、规则和流程。同时,该框架实现了绝大部分工作流功能,如流程起始、结束、任务分配、自动流转、异常处理、流程跳过等。 此外,Spring Boot Activity工作流也提供了个完整的工具包,包括Web设计器、任务列表、用户组管理、报表等,方便用户快速构建自定义的工作流应用。通过使用该框架,企业可以快速地完成业务系统的集成、部署和维护。 总之,Spring Boot Activity工作流不仅具有强大的组件和工具支持,同时也具有高度的可扩展性和灵活性,能够适应不同规模、不同领域的企业管理需求。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

厌世小晨宇yu.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值