业务场景实战(三)工作流引擎

思维导图

思维导图.png

系列总目录

  • 业务场景实战汇总

背景

  • 简单解释:请假,离职多个节点审批,多个流程,不同场景(请假,离职)流程不一样,这时候工作流引擎能够很好的承接


    请假流程.png
  • 应用:

  1. 内部OA系统
  2. 一些内容设计比如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
使用
  1. Spring-activiti使用的springboot版本比较低,而且pom文件也没有使用parent标签,所以很多依赖包版需要自己改
  2. 由于我本地是使用mysql8版本所以我把pom的mysql-connector-java的version改为8.0.15
  3. 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
  1. 执行activiti.sql

  2. 启动

  3. http://localhost:8888/login 账号xiaomi 密码 1234

  4. 将resource下两个bpmn例子上传


    上传1.png

    上传2.png
  5. 然后就可以开始愉快的熟悉了

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参数
流程设计.png
  • 我们可以在这里面加段代码,输入xml文件,这边我们编辑的流程图就可以在别的地方使用了


    xml.png

xml设计以及解释

  • 拿Spring-activiti的采购流程图解释


    采购流程图.png
  • xml图示例


  
    
    
      
        
          
            
          
        
        
          
            
          
        
      
    
    
    
    
    
    
      ${purchaseauditi=='false'}
    
    
    
    
    
      ${updateapply=='false'}
    
    
      ${updateapply=='true'}
    
    
      
      
      
      
      
      
      
        ${finance=='true'}
      
      
      
        ${money>10000}
      
      
      
        ${money<10000}
      
      
      
      
      
      
        
      
      
        ${manager=='true'}
      
      
        
      
      
        ${finance=='false'}
      
      
        ${manager=='false'}
      
    
    
      
    
    
    
      ${purchaseauditi=='true'}
    
    
    
    
    
  
  
  
  

  1. process标签定义了整体流程的id name

  1. startEvent标签定义了开始事件

  1. userTask用户事件, 表示用户事件节点,比如图示的采购经理审批,用户事件节点可以有表单信息承接,表单信息处理一般都是放在应用侧,流程引擎底层服务只是存储应用侧定义的表单信息
  2. sequenceFlow标签就是图示的箭头,节点流程箭头

  1. exclusiveGateway排他网关, 根据不同条件进入不同流程


    排他网关.png
  2. endEvent结束事件
  3. subProcess标签标示子流程


    image.png
  • 还有一些常用标签
  1. boundaryEvent边界事件可以定义timerEventDefinition超时时间


    超时提醒.png
  2. userTask中multiInstanceLoopCharacteristics标签可以设置会签规则,会签表示多人审批规则定义

原理

  • 将业务流程的每个节点读取到数据库中,这样每个节点(包括开始节点和结束节点)就是数据库中的一条记录,当发生业务流程的时候,不断的从业务流程图中读取下一个节点,其实就相当于操作节点对应的数据库记录,这样就实现流程管理和状态字段无关

数据库

  • activiti7流程引擎主要是跟25张表打交道, Activiti 数据库表结构中介绍了activiti6中各个表结构中字段,对于activiti7有参考意义

通用数据表

  • act_ge ge表示 general 全局通用数据及设置,各种情况都使用的数据
  1. act_ge_bytearray: 二进制数据表,存储通用的流程定义和流程资源
  2. 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只在流程实例执行过程中保存这些数据,在流程结束时就会删除这些记录
  1. act_ru_deadletter_job 作业死亡信息表,作业失败超过重试次数
  2. act_ru_event_subscr 运行时事件表
  3. act_ru_execution 运行时流程执行实例表
  4. act_ru_identitylink 运行时用户信息表
  5. act_ru_integration 运行时积分表
  6. act_ru_job 运行时作业信息表
  7. act_ru_suspended_job 运行时作业暂停表
  8. act_ru_task 运行时任务信息表
  9. act_ru_timer_job 运行时定时器作业表
  10. act_ru_variable 运行时变量信息表

历史数据表

  • act_hi:'hi’表示 history,此前缀的表包含历史数据,如历史(结束)流程实例,变量,任务等等
  1. act_hi_actinst 历史节点表
  2. act_hi_attachment 历史附件表
  3. act_hi_comment 历史意见表
  4. act_hi_detail 历史详情表,提供历史变量的查询
  5. act_hi_identitylink 历史流程用户信息表
  6. act_hi_procinst 历史流程实例表
  7. act_hi_taskinst 历史任务实例表
  8. act_hi_varinst 历史变量表

其他表

  1. act_evt_log 流程引擎的通用事件日志记录表
  2. act_procdef_info 流程定义的动态变更信息

拓展UserTask

  • 使用activiti流程引擎时,有时候不能满足我们的需求,比如没有处理人时自动跳过任务,任务处理人是任务发起人时自动跳过任务等这种自定义需求时,需要拓展BPMN
  • 拓展方式
  1. 在bpmn流程图的usertask属性中增加自定义标签,比如无处理人自动跳过skipNoProcess
 
  1. ProcessEngineConfigurationConfigurer中增加 BpmnXMLConverter.addConverter(继承UserTaskXMLConverter,拓展bpmn文件需要拓展转换能力)
  2. 增加后置处理器能力继承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的表结构

你可能感兴趣的:(业务场景实战(三)工作流引擎)