思维导图
系列总目录
- 业务场景实战汇总
背景
-
简单解释:请假,离职多个节点审批,多个流程,不同场景(请假,离职)流程不一样,这时候工作流引擎能够很好的承接
应用:
- 内部OA系统
- 一些内容设计比如PPT,海报模板设计时提供下载功能,下载时需要审批,不同租户审批的流程可设置成不一样
技术选型
对比项 | Activiti | Flowable | JBMP | Camunda |
---|---|---|---|---|
语言 | Java | Java | Java | Java |
活跃度 | 很高github 8.3K | 高4.9K | 一般 | 比较高2.3K |
优势 | 易上手,功能全面,文档丰富,支持云原生 | 基于activiti6,拓展一些新特性,有商业版 | 近年来新的文档少一些,应用和二次开发可能会比较吃力 | 基于activiti5,有商业版 |
- 从成熟度,活跃度,github标星,易上手,以及对云原生的支持,结合公司自身业务发展选择activiti
入门
Spring-activiti项目
- 参考gitee推荐的项目 https://gitee.com/shenzhanwang/Spring-activiti?_from=gitee_search,Spring-activiti项目被gitee推荐,目前star 2.4k
- Spring-activiti项目可以作为练手项目,熟悉并入门Activiti
使用
- Spring-activiti使用的springboot版本比较低,而且pom文件也没有使用parent标签,所以很多依赖包版需要自己改
- 由于我本地是使用mysql8版本所以我把pom的mysql-connector-java的version改为8.0.15
- application.yml中spring相关的配置改成
spring:
datasource:
url: jdbc:mysql://localhost:3306/activiti5?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&nullCatalogMeansCurrent=true
driver-class-name: com.mysql.jdbc.Driver
username: root
password: ****
activiti:
check-process-definitions: false
#Activiti记录历史任务数据级别,full是最全的,方便日后查询使用
history-level: full
#创建数据库历史数据表
db-history-used: true
database-schema-update: true
process-definition-location-prefix: classpath:/process/
thymeleaf :
mode: LEGACYHTML5
执行activiti.sql
启动
http://localhost:8888/login 账号xiaomi 密码 1234
-
将resource下两个bpmn例子上传
然后就可以开始愉快的熟悉了
BPMN设计说明,流程图在线工具
- github开源项目 https://github.com/juzhizhang/springboot2-activiti-design
- 修改application.yml的spring配置
spring:
datasource: # 数据源的相关配置 注意加上nullCatalogMeansCurrent=true配置才能自动生成表
type: com.zaxxer.hikari.HikariDataSource # 数据源类型:HikariCP
driver-class-name: com.mysql.jdbc.Driver # mysql驱动
url: jdbc:mysql://localhost:3306/activiti6?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&nullCatalogMeansCurrent=true
username: root
password: 3876556+0
hikari:
connection-timeout: 30000 # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 默认:30秒
minimum-idle: 5 # 最小连接数
maximum-pool-size: 20 # 最大连接数
auto-commit: true # 自动提交
idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
pool-name: DateSourceHikariCP # 连接池名字
max-lifetime: 1800000 # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms
thymeleaf:
cache: false
activiti:
check-process-definitions: false
#Activiti记录历史任务数据级别,full是最全的,方便日后查询使用
history-level: full
#创建数据库历史数据表
db-history-used: true
database-schema-update: true
- 启动
- 浏览器输入http://localhost:8002 这边使用google打不开,使用safari能正常打开,不知道为啥
- 可以愉快地编辑了,编辑完之后浏览器请求路径上有modelId参数
-
我们可以在这里面加段代码,输入xml文件,这边我们编辑的流程图就可以在别的地方使用了
xml设计以及解释
-
拿Spring-activiti的采购流程图解释
- xml图示例
${purchaseauditi=='false'}
${updateapply=='false'}
${updateapply=='true'}
${finance=='true'}
${money>10000}
${money<10000}
${manager=='true'}
${finance=='false'}
${manager=='false'}
${purchaseauditi=='true'}
- process标签定义了整体流程的id name
- startEvent标签定义了开始事件
- userTask用户事件, 表示用户事件节点,比如图示的采购经理审批,用户事件节点可以有表单信息承接,表单信息处理一般都是放在应用侧,流程引擎底层服务只是存储应用侧定义的表单信息
- sequenceFlow标签就是图示的箭头,节点流程箭头
-
exclusiveGateway排他网关, 根据不同条件进入不同流程
- endEvent结束事件
-
subProcess标签标示子流程
- 还有一些常用标签
-
boundaryEvent边界事件可以定义timerEventDefinition超时时间
- userTask中multiInstanceLoopCharacteristics标签可以设置会签规则,会签表示多人审批规则定义
原理
- 将业务流程的每个节点读取到数据库中,这样每个节点(包括开始节点和结束节点)就是数据库中的一条记录,当发生业务流程的时候,不断的从业务流程图中读取下一个节点,其实就相当于操作节点对应的数据库记录,这样就实现流程管理和状态字段无关
数据库
- activiti7流程引擎主要是跟25张表打交道, Activiti 数据库表结构中介绍了activiti6中各个表结构中字段,对于activiti7有参考意义
通用数据表
- act_ge ge表示 general 全局通用数据及设置,各种情况都使用的数据
- act_ge_bytearray: 二进制数据表,存储通用的流程定义和流程资源
- act_ge_property: 属性数据表。存储整个流程引擎级别的数据
流程存储表
- act_re re表示 repository 存储,包含的是静态信息,如,流程定义,流程的资源
- act_re_deployment : 部署流程定义时需要被持久化保存下来的信息
- act_re_model: 流程设计器设计流程后,保存数据到该表
- act_re_procdef: 业务流程定义数据表。此表和 ACT_RE_DEPLOYMENT 是多对一的关系,即,一个部署的bar包里可能包含多个流程定义文件,每个流程定义文件都会有一条记录在 ACT_REPROCDEF 表内,每个流程定义的数据,都会对于 ACT_GE_BYTEARRAY 表内的一个资源文件和 PNG 图片文件
运行数据表
- act_ru:'ru’表示 runtime,此前缀的表是记录运行时的数据,包含流程实例,任务,变量,异步任务等运行中的数据。Activiti只在流程实例执行过程中保存这些数据,在流程结束时就会删除这些记录
- act_ru_deadletter_job 作业死亡信息表,作业失败超过重试次数
- act_ru_event_subscr 运行时事件表
- 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_hi:'hi’表示 history,此前缀的表包含历史数据,如历史(结束)流程实例,变量,任务等等
- 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_evt_log 流程引擎的通用事件日志记录表
- act_procdef_info 流程定义的动态变更信息
拓展UserTask
- 使用activiti流程引擎时,有时候不能满足我们的需求,比如没有处理人时自动跳过任务,任务处理人是任务发起人时自动跳过任务等这种自定义需求时,需要拓展BPMN
- 拓展方式
- 在bpmn流程图的usertask属性中增加自定义标签,比如无处理人自动跳过skipNoProcess
- ProcessEngineConfigurationConfigurer中增加 BpmnXMLConverter.addConverter(继承UserTaskXMLConverter,拓展bpmn文件需要拓展转换能力)
- 增加后置处理器能力继承AbstractActivityBpmnParseHandler,ProcessEngineConfigurationConfigurer增加handler
功能
部署流程
- 例子
String fileName = "***".bpmn";
File file = new File("***".bpmn");
InputStream inputStream = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), inputStream);
//实现流程部署
Deployment deployment = processEngine.getRepositoryService().createDeployment().addBytes(fileName, multipartFile.getBytes()).name("测试子流程加assignee测试" + RandomUtil.createRandomCharData(10)).key("test_" + RandomUtil.createRandomCharData(10)).deploy();
启动流程
// 开始流程 -------------------
Map variables = new HashMap<>();
variables.put("purchaseManager", "seeger");
ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(deployment.getKey(), variables);
完成/转办/回退/审批/取消/改派/任务
完成
processEngine.getTaskService().complete(task.getId())
转办
- 有些时候需要将节点的assign换成其他人, 重新set aasign即可
task.setAssignee(assigneeId)
表单
- 参考开始流程的variables设置
会签
- 涉及到多个审批人时会用到
超时任务
- 可监听ExecutionListener, 在bpmn设计流程时增加TimeoutListener
代码:
public class TimeoutListener implements ExecutionListener {
@Override
public void notify(final DelegateExecution execution) {
}
}
bpmn流程
10
****
业务场景分层
- 工作流引擎底层只封装activiti能力,具体拓展还需要在工作流引擎架一层应用层
各个数据查询
- 可通过ManagementService查询各个表数据
private ManagementService managementService;
@Test
public void testInsertQueryTimeOutingTask() throws InterruptedException {
List jobs = managementService.executeCommand(new QueryTimeJobQueryCmd());
Thread.sleep(60000);
System.out.println("jobs");
}
public static class QueryTimeJobQueryCmd implements Command> {
@SneakyThrows
@Override
public List execute(CommandContext commandContext) {
TimerJobQueryImpl timerJobQuery = new TimerJobQueryImpl();
DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
Date date = dateFormat.parse("20220125");
Date date1 = dateFormat.parse("20220126");
return commandContext.getTimerJobEntityManager().findJobsByQueryCriteria(timerJobQuery, new org.activiti.engine.impl.Page(0, 10));
}
}
历史数据查询
- 查询act_hi_*表数据
参考文章
- 工作流选型专项,Camunda or flowable or?
- 工作流引擎技术介绍-Flowable与Activiti7
- 工作流程引擎技术选型:Activiti、jBPM5+
- Activiti7的基本原理和使用
- Activiti 数据库表结构
- activiti7的表结构