工作流activiti(1)
文章目录
- 工作流概述
- 什么是工作流
- 工作流有哪些开源框架
- OsWorkFlow
- JBPM
- Activiti
- Flowable
- Camunda(推荐)
- 什么是BPMN
- activiti执行流程
- 具体案例
- 创建数据库
- 新建项目
- 导入包
- activiti初始化数据库
- 方法一:读取xml配置生成数据库(过时不推荐)
- 方法二:读取yml文件
- 在线流程设置器
- 常见的流程设置器
- Activiti BPMN visualizer使用
- 读取生成的文件(流程部署)
- 查询部署表和流程定义表的信息
- 发起流程
- 待办任务查询
- 完成审批操作
- 未完待续....
工作流概述
什么是工作流
工作流就是类似于请假的流程需要谁审批
工作流有哪些开源框架
OsWorkFlow
对于比较简单的流程,OsWorkFlow会是一个比较好的选择,对于复杂的流程就不推荐了,OsWorkFlow是一个轻量化的流程引擎,基于状态机机制,数据库表很少,Osworkflow提供的工作流构成元素有:步骤(step)、条件(conditions)、循环(loops)、分支(spilts)、合并(joins)等,但不支持会签、跳转、退回、加签等这些操作,需要自己扩展开发,有一定难度。而且OsWorkFlow组件已过时,长时间没有版本升级了。
JBPM
JBPM由JBoSS公司开发,目前最高版本JPBM7,不过从JBPM5开始已经跟之前不是同一个产品了,JBPM5的代码基础不是JBPM4,而是从DroolsFlow重新开始,基于Drools Flow技术在国内市场上用的很少,所有不建议选择jBPM5以后版本,jBPM4诞生的比较早。
后来JBPM4创建者TomBaeyens离开JBoss后,加入Alfresco后很快推出了新的基于jBPM4的开源工作流系统Activiti,另外JBPM以hibernate作为数据持久化ORM也已不是主流技术,现在时间节点选择流程引擎,JBPM不是最佳选择。
Activiti
官网地址:https://www.activiti.org/
Activiti由Alfresco软件开发,目前最高版本Activiti7。Activiti的版本比较复杂,有Activiti5、Activiti6、Activiti7几个主流版本,选型时让人晕头转向,有必要先了解一下Activiti这几个版本的发展历史。Activiti5和Activiti6的核心领导者是TijsRademakers
,由于团队内部分歧,在2017年时TijsRademakers离开团队,创建了后来的Flowable,
Activiti6以及Activitis代码已经交接给了Salaboy团队,Activiti6以及Activitis的代码官方已经暂停维护了,Salaboy团队目前在开发Activiti7框架,activiti7内核使用的还是Activiti6,并没有为引擎注入更多的新特性,只是在Activiti之外的上层封装了一些应用。结论是activiti谨慎选择。
Flowable
Flowable基于activiti6衍生出来的版本,flowable目前最新版本是v6.7.2,开发团队是从Activiti中分裂出来的,修复了一众Activiti6的bug,并在其基础上研发了DMN支持,BPEL支持等等,相对开源版,其商业版的功能会更强大。以flowable6.4.1版本为分水岭,大力发展其商业版产品,开源版本维护不及时,部分功能已经不再开源版发
布,比如表单生成器(表单引擎)、历史数据同步至其他数据源、ES等。
Flowable是一个使用Java编写的轻量级业务流程引擎,使用ApacheV2license协议开源。2016年10月,Activiti工作流引擎的主要开发者离开Alfresco公司并在Activiti分支基础上开启了Flowable开源项目。基于Activiti v6 beta4发布的第一个Flowable release版本为6.0。Flowable项目中包括BPMN(BusinessProcessModeland
Notation)引擎、CMMN(Case Management Model and Notation)引擎、DMN(Decision Model and Notation)引擎、表单引擎(FormEngine)等模块。
中文用户手册:https://tkjohn.github.io/flowable-userguide/#_conclusion
Camunda(推荐)
中文站点:https://camunda-cn.shaochenfeng.com/
Camunda基于Activiti5,所以其保留了PVM,最新版本Camunda7.17,保持每年发布2个小版本的节奏,开发团队也是从activiti中分裂出来的,发展轨迹与flowable相似,同时也提供了商业版,不过对于一般企业应用,开源版本也足够了,强烈推荐camunda流程引擎,功能和性能表现稳定。
什么是BPMN
BPMN(Business Process Model and Notation,业务流程模型与标记法)是一套国际标准的图形化建模语言,主要用于描绘业务流程的各个步骤、决策顺序和逻辑关系。它的核心目标是为业务分析人员、技术开发和管理人员提供一种通用的可视化语言,从而减少沟通障碍,确保大家对业务流程有统一的理解。
activiti执行流程
所有的工作流大概流程都是这个。
具体案例
创建数据库
我使用navicat为例
选择utf8mb4字符集
新建项目
导入包
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>
<!-- 添加jdbc依赖 用于获取连接信息 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 添加activiti依赖 -->
<dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter</artifactId><version>7.0.0.GA</version>
</dependency>
activiti初始化数据库
我们有两种方式,第一种了解即可不需要使用。
方法一:读取xml配置生成数据库(过时不推荐)
在工作流引擎框架中,ProcessEngine是一个非常核心的对象,我们需要首先解决这个对象的获取。获取方式很多。先来看最简单的一个基于activiti.cfg.xml
的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"class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"><!-- nullCatalogMeansCurrent参数是在指定的数据库(activiti)进行检查是否表重复 --><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti?nullCatalogMeansCurrent=true"/><property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/><property name="jdbcUsername" value="root"/><!-- 这个数据库密码换成你的数据库密码 --><property name="jdbcPassword" value="root"/><property name="databaseSchemaUpdate" value="true"/><property name="asyncExecutorActivate" value="false"/><property name="mailServerHost" value="mail.my-corp.com"/><property name="mailServerPort" value="5022"/></bean>
</beans>
新建测试类编写代码读取activiti.cfg.xml
文件
package com.hsh.activitidemo01;import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class Activiti7Test01 {/*** 获取ProcessEngine对象的第一种方式*/@Testpublic void test01() {//通过getDefauLtProcessEngine()方法获取流程引擎对象会加载resources目录下的activit.cfg.xmlProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();System.out.println(processEngine);}
}
方法二:读取yml文件
将application.properties文件重命名为application.yml文件
spring:datasource:# 在高版本的MySQL驱动(6.x以上)中,如果连接URL里不指定 nullCatalogMeansCurrent=true参数,# 可能会遇到类似 Table 'activiti.act_ge_property' doesn't exist的错误,即使表实际存在。设置此参数可避免此问题url: jdbc:mysql://localhost:3306/activiti?nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghaiusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driveractiviti:database-schema-update: true # 设置为 true时,Activiti启动时会自动创建或更新数据库表结构history-level: audit # 历史数据记录级别,可选 'none', 'activity', 'audit', 'full'
在com/hsh/activitidemo01
文件下新建properties文件夹
在com/hsh/activitidemo01/properties
文件夹下创建ActivitiProperties文件
package com.hsh.activitidemo01.properties;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "spring.activiti")
public class ActivitiProperties {private String databaseSchemaUpdate;private String historyLevel;// getter和setter方法public String getDatabaseSchemaUpdate() { return databaseSchemaUpdate; }public void setDatabaseSchemaUpdate(String databaseSchemaUpdate) { this.databaseSchemaUpdate = databaseSchemaUpdate; }public String getHistoryLevel() { return historyLevel; }public void setHistoryLevel(String historyLevel) { this.historyLevel = historyLevel; }
}
在com/hsh/activitidemo01/properties
文件夹下创建DataSourceProperties文件
package com.hsh.activitidemo01.properties;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** @author xrkhy* @date 2025/10/22 19:57* @description*/
@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {private String url;private String username;private String password;private String driverClassName;// getter和setter方法public String getUrl() { return url; }public void setUrl(String url) { this.url = url; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getPassword() { return password; }public void setPassword(String password) { this.password = password; }public String getDriverClassName() { return driverClassName; }public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; }
}
编写测试代码
@Testpublic void test02() {ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration().setJdbcDriver(dataSourceProperties.getDriverClassName()).setJdbcUrl(dataSourceProperties.getUrl()).setJdbcUsername(dataSourceProperties.getUsername()).setJdbcPassword(dataSourceProperties.getPassword()).setDatabaseSchemaUpdate(activitiProperties.getDatabaseSchemaUpdate()).setHistory(activitiProperties.getHistoryLevel()).buildProcessEngine();System.out.println("流程引擎创建成功: " + processEngine);}
运行后查看数据库,会生成
查看数据发现除了act_ge_property
数据库表之外的所有数据库表全是空的。act_ge_property
数据库表中存放的是activiti的版本
在线流程设置器
我们这些流程的设计其实就是xml文件,但是我们自己编写xml太麻烦了,这个时候就需要在线流程设置器,我们只需要拖动图标就可以生成对应的流程xml文件。
常见的流程设置器
activiti-6.0.0
:这是activiti的官方提供的流程设置器,下载地址==>https://www.activiti.org/get-started
actiBPM
:idea的插件中可以自动绘制,但是只支持到idea的2019版本(不推荐
)。Activiti BPMN visualizer
:这个是官方推荐继承者,专为新版 IDEA 设计,与开发环境无缝集成。下载地址==>https://plugins.jetbrains.com/plugin/15222-activiti-bpmn-visualizer/versions要选择和你的idea版本一致的Activiti BPMN visualizer版本下载。Camunda Modeler
:独立桌面应用,本身用于Camunda工作流,但兼容 Activiti和Flowable。下载地址==>https://camunda.com/download/modeler/,但是需要对产生的xml文件进行修改,也就是将 camunda:命名空间和属性(如 camunda:assignee)替换为 activiti:
(不推荐,如果不在乎每次都要修改文件的话这个也不错)。
Activiti BPMN visualizer使用
在idea插件市场下载
下载完毕后,在你的resource下面新建一个bpm的包,然后右击新建选择New Activiti 6.x BPMN 2.0 file
给你的xml起个名字。
生成好的文件如下
打开图形化界面
右击开始start event开始
将箭头指向生成的User Task
重复上面动作生成经理审批并连接
结束按钮
添加审批人
如下
读取生成的文件(流程部署)
我们下面使用java代码读取上面生成的xml文件
@Test
public void test03() {//1.获取ProcessEngine对象ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//2.完成流程的部署操作需要通过RepositoryService来完成RepositoryService repositoryService = processEngine.getRepositoryService();//3.完成部署操作Deployment deploy =repositoryService.createDeployment().addClasspathResource("bpmn/test01.bpmn20.xml").name("第一个流程").deploy();System.out.println("流程部署ID: " + deploy.getId());System.out.println("流程部署名称: " + deploy.getName());
}
查看数据,发现给三个数据库表插入了数据,这三张表的作用如下
act_ge_bytearray
:二进制数据表
act_re_deployment
:部署表
act_re_procdef
:流程定义表
部署表和流程定义表的区别
对比维度 | act_re_deployment(部署表) | act_re_procdef(流程定义表) |
---|---|---|
核心职责 | 记录部署操作的元数据 | 记录流程定义本身的详细信息 |
主要记录内容 | 部署ID、部署名称、部署时间、租户信息等 | 流程定义ID、流程Key、版本号、流程名称、关联的部署ID等 |
形象比喻 | 软件安装包或书籍采购记录 | 安装好的软件程序或图书馆中具体的书籍信息 |
关系 | 一个部署可以包含多个流程定义文件 | 一个流程定义必须属于一次部署 |
这两个表是一对多的关系。一次部署(在 act_re_deployment中产生一条记录)可以同时部署多个BPMN文件。每个BPMN文件都会在 act_re_procdef表中解析成一条独立的流程定义记录。
查询部署表和流程定义表的信息
/*** 查询当前部署表和定义表的信息*/
@Test
public void test04() {ProcessEngine engine =ProcessEngines.getDefaultProcessEngine();RepositoryService repositoryService = engine.getRepositoryService();// 查询有哪些部署的流程--》查询相关的流程定义信息//repositoryService.createDepLoymentQueryO)查询流程部署的相关信息//repositoryService.createProcessDefinitionQueryO)查询部署的流程的相关的定义List<Deployment> list = repositoryService.createDeploymentQuery().list();// 查询有所的部署信息for (Deployment deployment : list) {System.out.println("流程部署ID: " + deployment.getId());System.out.println("流程部署名称: " + deployment.getName());}// 获取所有的流程定义信息List<ProcessDefinition>list1 = repositoryService.createProcessDefinitionQuery().list();for (ProcessDefinition processDefinition :list1){System.out.println(processDefinition.getId());System.out.println(processDefinition.getName());System.out.println(processDefinition.getDescription());}
}
发起流程
/*** 发起一个流程*/
@Test
public void test05() {ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();// 发起流程的操作需要通过RuntimeService来完成RuntimeService runtimeService = engine.getRuntimeService();// runtimeService.startProcessInstanceByKey("test01");// 通过流程定义的ID启动流程实例,这个ID是act_re_procdef表中的IDProcessInstance processInstance = runtimeService.startProcessInstanceById("test01:1:31be88df-af45-11f0-8c6d-2cdb0731427d");System.out.println("流程实例ID: " + processInstance.getId());System.out.println("部署ID: " + processInstance.getDeploymentId());System.out.println("描述信息: " + processInstance.getDescription());
}
这个会生成很多表的数据
act_hi_actinst
实例对象
act_hi_identitylink
:谁去做审批
act_ru_task
(重点看这个表):这个表是 Activiti 工作流引擎中非常核心的一张运行时任务表,它专门用来存储流程运行过程中所有正在活动、尚未完成的人工任务信息。一旦任务完成,相应的记录就会从该表中删除,并转移到历史任务表(act_hi_taskinst)中。
发起流程成功后。在对应的act_ru_task
中就有一条对应的待办记录。
对应流程状态如下:
待办任务查询
如果某个审批人登录系统想要还有多少请假条没有批就可以用这个
/*** 待办查询*/
@Test
public void test06() {ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();//待办查询执行中的任务处理通过TaskService来实现TaskService taskService =engine.getTaskService();//Task对象对应的其实就是act_ru_task这张表的记录 可以把zhangsan换成lisi看看是什么结果List<Task> list = taskService.createTaskQuery().taskAssignee("zhangsan").list();if (list != null && list.size() > 0){for (Task task : list) {System.out.println("任务ID: " + task.getId());System.out.println("任务名称: " + task.getName());System.out.println("任务审批人: " + task.getAssignee());}}else {System.out.println("没有待办任务");}
}
完成审批操作
当审批人允许请假就可以用complete()
完成审批。
/*** 任务审批*/
@Test
public void test07() {ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();//做任务申请也需要通过TaskService来实现TaskService taskService = engine.getTaskService();//做任务申请也需要通过TaskService来实现 这个id是act_ru_task表对应的IDtaskService.complete("632e7dcc-af49-11f0-9520-2cdb0731427d");
}
一旦任务完成,相应的记录就会从该表中删除,并转移到历史任务表(act_hi_taskinst)中,这个表就会进行下一个节点。