• 《Flowable流程引擎从零到壹》引入日志框架和部署流程定义


    14天学习训练营导师课程:
    邓澎波《Flowable流程引擎-基础篇【2022版】》
    邓澎波《Flowable流程引擎-高级篇【2022版】》

    学习笔记《Flowable流程引擎从零到壹》回城传送

    ❤️作者主页:小虚竹

    ❤️作者简介:大家好,我是小虚竹。Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作者🏆,阿里云专家博主🏆,51CTO专家博主🏆

    ❤️技术活,该赏

    ❤️点赞 👍 收藏 ⭐再看,养成习惯

    PC端左侧加我微信,进社群,有送书等更多活动!

    零:前言

      今天学习的内容是引入日志框架和部署流程定义,和虚竹哥一起学习吧。

    一、引入日志框架

      上一篇文章初始化ProcessEngine流程引擎实例后,控制台没什么日志内容输出,只有提示日志没有正确配置。
    在这里插入图片描述
      从提示内容可知Flowable使用SLF4J作为内部日志框架。
      本文使用log4j作为SLF4J的实现。因此在pom.xml文件中添加下列依赖:

    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-apiartifactId>
        <version>1.7.21version>
    dependency>
    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-log4j12artifactId>
        <version>1.7.21version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

      增加配置文件:log4j.properties文件

    log4j.rootLogger=DEBUG, CA
    
    log4j.appender.CA=org.apache.log4j.ConsoleAppender
    log4j.appender.CA.layout=org.apache.log4j.PatternLayout
    log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n
    
    • 1
    • 2
    • 3
    • 4
    • 5

      重新运行应用,控制台就有日志出现了。
    在这里插入图片描述
    在这里插入图片描述

    二、部署流程定义

      构建一个简单的请假流程,Flowable引擎需要流程定义为BPMN 2.0格式 ,这是一个业界广泛接受的XML标准。
      定义一个请假流程的流程步骤图,我们称为一个流程定义(process definition)。 一个流程定义可以启动多个流程实例(process instance)

    以请假流程为例,流程定义定义了请假的各个步骤要做的事情;
    一个流程实例是每个员工可以发起一个请假申请,直到这个请假申请的流程走完,这个流程实例才结束。

      BPMN 2.0存储为XML,并包含可视化的部分:使用标准方式定义了每个步骤类型(人工任务,自动服务调用,等等)如何呈现,以及如何互相连接。这样BPMN 2.0标准使技术人员与业务人员能用双方都能理解的方式交流业务流程。

    本次请假流程的流程定义为:
    在这里插入图片描述
    说明:

    • 左侧的圆圈叫做启动事件(start event)。这是一个流程实例的起点。
    • 第一个矩形是一个用户任务(user task)。这是流程中用户操作的步骤。在这个例子中,经理需要批准或驳回申请
    • 取决于经理的决定,排他网关(exclusive gateway) (带叉的菱形)会将流程实例路由至批准或驳回路径
    • 如果批准,则需要将申请注册至某个外部系统,并跟着另一个用户任务,将经理的决定通知给申请人。当然也可以改为发送邮件。
    • 如果驳回,则为雇员发送一封邮件通知他。

      实际的业务场景,流程定义步骤图是用可视化建模工具的,如Flowable Designer(Eclipse)Flowable Web Modeler(Web应用)
      本文直接写XML,新手刚入门要熟悉下BPMN2.0及其概念。
      将下面的XML保存在src/main/resources文件夹下名为holiday-request.bpmn20.xml的文件中。

    注意:*.bpmn20.xml 这个后缀是固定的

    
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
                 xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
                 xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
                 xmlns:flowable="http://flowable.org/bpmn"
                 typeLanguage="http://www.w3.org/2001/XMLSchema"
                 expressionLanguage="http://www.w3.org/1999/XPath"
                 targetNamespace="http://www.flowable.org/processdef">
    
        <process id="holidayRequest" name="请假流程" isExecutable="true">
    
            <startEvent id="startEvent"/>
            <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>
    
            <userTask id="approveTask" name="同意或拒绝请假"/>
            <sequenceFlow sourceRef="approveTask" targetRef="decision"/>
    
            <exclusiveGateway id="decision"/>
            <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
                <conditionExpression xsi:type="tFormalExpression">
                    
                conditionExpression>
            sequenceFlow>
            <sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail">
                <conditionExpression xsi:type="tFormalExpression">
                    
                conditionExpression>
            sequenceFlow>
    
            <serviceTask id="externalSystemCall" name="Enter holidays in external system"
                         flowable:class="org.flowable.CallExternalSystemDelegate"/>
            <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>
    
            <userTask id="holidayApprovedTask" name="Holiday approved"/>
            <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>
    
            <serviceTask id="sendRejectionMail" name="Send out rejection email"
                         flowable:class="org.flowable.SendRejectionMail"/>
            <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>
    
            <endEvent id="approveEnd"/>
    
            <endEvent id="rejectEnd"/>
        process>
    
    definitions>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    现在我们已经有了流程BPMN 2.0 XML文件,现在需要将它部署到引擎中。

    下面简单介绍下bpmn20.xml的几个重要的点

    2.1、bpmn20.xml介绍

    2.1.1、流对象(Flow Objects):包括事件、活动、网关,是BPMN中的核心元素。

    2.1.1.1、事件

    作用:用于对流程生命周期中发生的事件进行建模。

    分类
    开始事件:开始事件指示流程从何处开始。

    定义:
    没有启动事件,需要调用startProcessInstanceByXXX方法执行该空开始事件。

    图形表示:
    在这里插入图片描述
    XML表示:

    <startEvent id="startEvent"/>
    
    • 1
    中间事件:

    正常是任务和网关的混合体

    结束事件:标志着流程的结束。

    定义:
    没有结束事件,当流程引擎检测到执行到该空结束事件时会自动执行,已结束整个流程。
    图形表示:
    在这里插入图片描述
    xml表示:

    <endEvent id="approveEnd"/>
    
    • 1
    2.1.1.2、任务(活动)

    定义:
    任务表示流程中具体要做的事情,通常一个任务表示工作需要被外部实体完成,比如人工任务和自动服务。
    图形表示:
    任务通常有圆角矩形表示,内部文字为任务名称或描述,左上角的图标表示任务类型。

    分类
    人工任务(user task)

    定义:
    最典型的任务。需要由人工来完成的任务,比如请假审批、财务审核等。
    图形表示:
    在这里插入图片描述
    xml表示:
    id是必须的,name是可选的,通过documentation元素对任务进行描述。任何bpmn2.0元素都可用documentation元素进行描述。

    <userTask id="theTask" name="Schedule meeting" > <documentation> Schedule an engineering meeting for next week with the new hire. documentation> userTask>
    
    • 1

    到期日:
    可通过dueDate字段设置任务的到期时间。

    用户分配:
    人工任务可分配给三种人:assignee(办理人、受让人),candidate(候选人),candidateGroup(候选人组)

    • assignee是任务的实际办理人,任务只能同时有一个办理人。

    • 任务可以有多个候选人,每个候选人都能看到该任务,候选人需要claim(拾取)任务成为assignee后,才能进行任务的办理,任务被拾取后其他候选人就看不到该任务了。候选人在拾取任务后可以unclaim,将任务归还,此时其他候选人可以看到并claim任务。

    • 不想单独指定多个候选人,可以指定一个候选人组,一般为角色ID。

    分配方式有三种:

    • 画图时写死。

    • 通过UEL表达式动态设置。

    • 通过TaskListener监听器指定。

    java服务任务(service task)

    定义:
    用于调用外部Java代码。

    图形表示:
    在这里插入图片描述
    xml表示:

    <serviceTask id="javaService" name="My Java Service Task" activiti:class="org.activiti.MyJavaDelegate" />
    
    • 1
    脚本任务(script task)

    定义:

    用于执行脚本文件(如javascript)

    图形表示:
    在这里插入图片描述
    xml表示:

    <scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy"> 
        <script> 
            sum = 0 
            for ( i in inputArray ) { 
                sum += i 
            } 
        script> 
    scriptTask>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    web服务任务

    用于调用外部web接口服务。

    邮件任务(非BPMN2.0规范)

    用于发送邮件。

    还有手工任务、java接收任务、shell任务等。

    2.1.1.3、网关(节点)

    作用:
    用来控制流程的流向。

    图形表示:
    网关通常以菱形图形表示,内部带有一个图标。该图标显示网关的类型。

    分类:
    排他网关(exclusiveGateway)

    定义:
    也叫XOR网关,对所有的传出分支进行条件判断,仅选择一个条件为true的分支执行,当有多个分支条件满足时,默认执行xml中定义的第一个。若多个分支条件都不满足时,就走默认顺序流。如果没有默认顺序流,将抛出异常。

    图形表示:
    在这里插入图片描述
    xml表示:

    <exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" />
    
    • 1
    并行网关(parallelGateway)

    定义:

    并行网关模拟多个同时并行执行的流程这种情况。两个特点:

    • 具有fork-join行为(发散和汇聚,想起了java中的fork-join线程框架),即从并行网关传出的流程会并行执行,传入并行网关的流程会进入里面等待,知道并行的流程都进入到并行网关后,再一起发散出去。
    • 并行网关忽略分支的条件判断。
      图形表示:
      在这里插入图片描述
      xml表示:
    <parallelGateway id="myParallelGateway" />
    
    • 1
    包含网关(inclusiveGateway)

    定义:
    看作是排他网关和并行网关的组合,包含网关既能进行条件判断,又能并行执行多个分支。

    图形:
    在这里插入图片描述
    xml表示:

    <inclusiveGateway id="myInclusiveGateway" />
    
    • 1

    还是事件网关等。

    2.1.2、顺序流

    定义:
    顺序流就是事件,活动和网关之间的连线,显示为一条实线 带有箭头,在BPMN图形中每个顺序流都有一个源头和一个 目标引用,包含了 活动,事件或网关的id。

    <sequenceFlow id="myFlow" name="MyFlow" sourceRef="sourceId" targetRef="targetId" />
    
    • 1
    分类:
    条件顺序流

    定义:
    给顺序流添加表达式条件,当条件判断为true时,该顺序流将会被执行。这意味着如果多个顺序流的条件都为true时,会有多个顺序流并行执行。

    图形表示:
    在这里插入图片描述
    XML表示:
    条件序列流在XML中表现为常规序列流,其中包含conditionExpression子元素。当前conditionalExpression仅可与UEL一起使用。

    <sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask"> 
        <conditionExpression xsi:type="tFormalExpression"> 
             100 && order.price < 250}]]> 
        conditionExpression>
    sequenceFlow>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    默认顺序流

    定义:
    所有BPMN 2.0任务和网关都可以具有默认序列流。当且仅当其他条件顺序流都为false时,才选择执行默认顺序流。默认序列流的条件总是被忽略。

    图形表示:
    默认序列流是开始处带有斜杠标记的常规顺序流。
    在这里插入图片描述
    xml表示:
    通过default属性执行默认顺序流。flow2为排他网关的默认顺序流。

    <exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" default="flow2" />         
          <sequenceFlow id="flow1" sourceRef="exclusiveGw" targetRef="task1">     
              <conditionExpression xsi:type="tFormalExpression">
                ${conditionA}    
              conditionExpression> 
           sequenceFlow> 
          <sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="task2"/> 
          <sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="task3"> 
             <conditionExpression xsi:type="tFormalExpression">
                ${conditionB}
             conditionExpression> 
          sequenceFlow>
    exclusiveGateway>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.2、部署流程定义

    先了解下ProcessEngine下提供了哪些主要的服务:
    在这里插入图片描述

    • RepositoryService:资源管理的一些服务
    • RuntimeService:流程运行时的服务
    • TaskService:任务处理的服务
    • HistoryService:历史信息,历史流转的服务

    实现部署:

    • 获取流程引擎对象
    • 将流程定义部署至Flowable引擎
    • 需要使用RepositoryService,其可以从ProcessEngine对象获取
    • 使用RepositoryService,可以通过XML文件的路径创建一个新的部署(Deployment)
    • 并调用*deploy()*方法实际执行
    • 输出deployment对象的id和名称。
    package com.xiaoxuzhu.flowable.test;
    
    import org.flowable.engine.ProcessEngine;
    import org.flowable.engine.ProcessEngineConfiguration;
    import org.flowable.engine.RepositoryService;
    import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
    import org.flowable.engine.repository.Deployment;
    import org.junit.Test;
    
    public class Test03 {
    
        /**
         * 部署流程
         */
        @Test
        public void testDeploy() {
            ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();
            //数据库配置
            configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
            configuration.setJdbcUsername("root");
            configuration.setJdbcPassword("123456");
            configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
            //自动创建表结构-表不存在时
            configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            ProcessEngine processEngine = configuration.buildProcessEngine();
            // 部署流程 获取RepositoryService对象
            RepositoryService repositoryService = processEngine.getRepositoryService();
            Deployment deployment = repositoryService.createDeployment()// 创建Deployment对象
                    .addClasspathResource("holiday-request.bpmn20.xml") // 添加流程部署文件
                    .name("流程名称:请假流程") // 设置部署流程的名称
                    .deploy(); // 执行部署操作
            System.out.println("deployment.getId() = " + deployment.getId());
            System.out.println("deployment.getName() = " + deployment.getName());
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    执行日志成功的截图:
    在这里插入图片描述

    成功后会在表结构插入数据:
    act_re_deployment: 流程定义部署表,每部署一次就增加一条记录
    在这里插入图片描述

    act_re_procdef :流程定义表,部署每个新的流程定义都会在这张表中增加一条记录
    在这里插入图片描述
    在这里插入图片描述
    act_ge_bytearray :流程资源表,流程部署的 bpmn xml文件会保存在该表中
    在这里插入图片描述

    2.3、查询流程定义

        @Test
        public void testDeployQuery() {
            // 配置数据库相关信息 获取 ProcessEngineConfiguration
            ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();
            //数据库配置
            configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
            configuration.setJdbcUsername("root");
            configuration.setJdbcPassword("123456");
            configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
            //自动创建表结构-表不存在时
            configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            // 获取流程引擎对象
            ProcessEngine processEngine = configuration.buildProcessEngine();
            // 部署流程 获取RepositoryService对象
            RepositoryService repositoryService = processEngine.getRepositoryService();
            // 获取流程定义对象
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId("1")
                    .singleResult();
            System.out.println("processDefinition.getId() = " + processDefinition.getId());
            System.out.println("processDefinition.getName() = " + processDefinition.getName());
            System.out.println("processDefinition.getDeploymentId() = " + processDefinition.getDeploymentId());
            System.out.println("processDefinition.getDescription() = " + processDefinition.getDescription());
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    2.4、删除流程定义

    通过idea下载源码
    在这里插入图片描述

        @Test
        public void testDeployDelete() {
            // 配置数据库相关信息 获取 ProcessEngineConfiguration
            ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();
            //数据库配置
            configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
            configuration.setJdbcUsername("root");
            configuration.setJdbcPassword("123456");
            configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true");
            //自动创建表结构-表不存在时
            configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            // 获取流程引擎对象
            ProcessEngine processEngine = configuration.buildProcessEngine();
            // 部署流程 获取RepositoryService对象
            RepositoryService repositoryService = processEngine.getRepositoryService();
            //从注释可知 通过部署ID,删除流程部署定义 id值不为空。 如果部署的流程启动了,就会抛出RuntimeException 异常。不执行删除
            repositoryService.deleteDeployment("1");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    如图删除成功
    在这里插入图片描述
    数据库的值也没了
    在这里插入图片描述

    //级联删除 如果流程启动了,此方法也能删除相关任务。
     repositoryService.deleteDeployment("1",true);
    
    • 1
    • 2

    从注释可知
    在这里插入图片描述

    总结

    今天学会了如何引入log4j日志框架,在控制台顺利输出日志。同时也掌握了部署一个流程定义,查询流程定义和删除流程定义。
    一定要懂得bpmn20.xml的结构,虽然后面可以用可视化配置生成,但只有先懂得结构是什么意思,后面心里才有底,整个脉络了然于胸。

    参考

    java Log4j日志配置详解大全
    bpmn20.xml结构介绍
    activiti7(一):思想指导实践——BPMN2.0规范

    我是虚竹哥,我们下文见~

  • 相关阅读:
    TF卡格式化了怎么办?tf卡数据恢复,看这3个方法
    HTML+PHP+MySQL实现新闻列表模块(1+X Web前端开发中级 例题)——初稿
    list分组成map这样做更简单
    About OushuDB (Oushu Database)
    JavaScript基础07——变量拓展-数组
    得失权衡、主体信任与危机感知:“健康码”常态化使用的影响因素研究
    Flutter真机运行及模拟器运行
    C/C++输出整数部分 2021年12月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析
    Harbor企业级Registry基础镜像仓库的详细安装使用教程(保姆级)
    如何利用React和Flutter构建跨平台移动应用
  • 原文地址:https://blog.csdn.net/shi_hong_fei_hei/article/details/128066407