• Flowable工作流实战


    1. 工作流入门介绍

    1.1 什么是工作流?

    实际生活中有一些例如办公类流程需要多个环节人员进行审批,以达到对整个工作流程的控制与掌握。为提高效率,借助计算机对业务流程自动化执行管理,而Flowable框架就可以帮助我们进行工作流程进行管理工作。而Flowable可以帮助我们即是业务流程发送了变更,我们的业务流程代码也无需进行更新。

    1.2 工作流的原理

    如何做到我们在业务流程发生变更后,我们的业务系统代码可以不发生改变?原理如下:
    在这里插入图片描述

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

    1.3 BPM

    • BPM(Business Process Management),即业务流程管理,是一种以规范化的构造端到端的卓越业务流程为中心,以持续的提高组织业务绩效为目的的系统化方法,常见商业管理教育如EMBA、MBA等均将BPM包含在内。
    • 企业流程管理主要是对企业内部改革,改变企业只能管理机构重叠、中间层次多、流程不闭环等,做到机构不重叠、业务不复杂,达到缩短流程周期、节约运作资本、提高企业效益的作用。

    1.4 BPMN

    BPMN(Business Process Model And Notation),业务流程模型和符号,是由BPMI(Business Process Management Initiative)开发的一套的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。2004年5月发布了BPMN1.0规范。BPMI于2005年9月并入OMG(The Object Management Group,对象管理组织)组织。OMG于2011年1月发布BPMN2.0的最终版本。

    1.5 Activiti 还是flowable?

    下表是Activiti7 与flowable的相关功能特性对比说明。

    对比项\引擎Activiti-7.xFlowable-6.x
    商业化
    路线(Roadmap)工具型
    PVM引擎××
    BPMN2引擎
    CMMN引擎×
    DMN引擎×√(开源版支持不太好)
    [建模工具选型√(AngularJS)√(AngularJS)
    建模工具内容BPMN2BPMN2/CMMN/DMN
    扩展节点(Mule\Http等)×
    Spring Boot
    Spring Cloud×
    Web控制台
    Rest接口
    历史异步归档×
    异步任务全局锁×
    • Activiti

    Activiti在目前来看有点不思进取,核心功能和内核的优化并没有太大进步,着力点全在商业版和云上面,核心只支持BPMN2协议,跟6版本没有什么区别。如果你是一个老的Activiti使用者,并且只是用BPMN2协议,可以选用Activiti(非Cloud版本)。

    • Flowable

    Flowable不管是功能层面还是在代码层面来讲,都是这2个中最重的,当初跟Activiti分道扬镳的原因也是因为理念不一样,Flowable更注重其功能性、和性能。在上面表格中,历史异步归档和全局锁都是对性能的极大优化,特别是异步任务这一项,当年在使用Activiti的使用是一个极大的困扰,因为异步任务的吞吐反而会随着实例数的增加而加速恶化。Flowable比较臃肿,它支持了太多的东西,以致于如果想做POC或者Demo,环境搭建这一步都够呛。但是如果你本身就想做一个扩展性强的,性能高的工作流平台(SaaS\PaaS),Flowable是不二的选择。
    而且flowable和activiti6是同一个团队开发的,activiti先开发,flowable后开发,所以flowable 算是 activiti6的升级版。

    2. flowable入门helloWorld

    2.1 导入依赖

    首先导入Flowable相关Pom依赖如下所示:

      <properties>
            <maven.compiler.source>8maven.compiler.source>
            <maven.compiler.target>8maven.compiler.target>
             <logback.version>1.2.3logback.version>
        properties>
        <dependencies>
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>8.0.19version>
            dependency>
            <dependency>
                <groupId>org.flowablegroupId>
                <artifactId>flowable-engineartifactId>
                <version>6.3.0version>
            dependency>
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
            dependency>
            <dependency>
                <groupId>commons-dbcpgroupId>
                <artifactId>commons-dbcpartifactId>
                <version>1.4version>
            dependency>
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>slf4j-apiartifactId>
                <version>${slf4j.version}version>
            dependency>
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-accessartifactId>
                <version>${logback.version}version>
            dependency>
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-classicartifactId>
                <version>${logback.version}version>
            dependency>
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-coreartifactId>
                <version>${logback.version}version>
            dependency>
        dependencies>
    
    • 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

    2.2 初始化数据库表结构

    新增测试类初始化Flowable数据库表的配置类如下:

      private ProcessEngineConfiguration processEngineConfiguration;
    
        public DataSource initDataSource() {
            BasicDataSource dataSource = new BasicDataSource();
            dataSource.setUrl("jdbc:mysql://1.14.49.145:23306/flowable6?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true");
            dataSource.setUsername("root");
            dataSource.setPassword("Xxxxx");
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setMaxActive(3);
            dataSource.setMinIdle(1);
            return dataSource;
        }
    
    
        /**
         * 初始化数据库表34张表
         */
        @Before
        public void initDataBaseTables() {
            processEngineConfiguration = new StandaloneProcessEngineConfiguration();
            processEngineConfiguration.setDataSource(initDataSource());
            processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            processEngineConfiguration.buildProcessEngine();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    运行测试类输出如下结果:同时查看Flowable数据库,发现新增了34张表如下所示:
    在这里插入图片描述

    2.4 flowable表命名规则

    Flowable的表都是以ACT_开头。第二部分是表示表的用途的两个字母标识。用途也和服务的API对应。
    ACT_RE_:'RE’表示Repository。这个前缀的表包含了流程定义和流程静态资源(图片、规则等等)。
    ACT_RU_
    :'RU’表示Runtime。这些运行时的表,包含流程实例,任务、变量,异步任务等运行中的数据。Flowable只在流程实例执行过程中保存这些数据,在流程结束时就会删除这些记录。这些运行时表可以一直很小并且速度很快。
    ACT_HI_:'HI’表示History。这些表包含历史数据,比如历史流程实例,变量,任务等等。
    ACT_GE_
    :'GE’表示General。通用数据,用于不同场景下。
    ACT_ID_*:'ID’表示Identity。组织结构,包含标识的信息,如用户,用户组,等等。

    3. Flowable服务

    flowable 默认重要服务体系图如下所示:
    在这里插入图片描述

    3.1 重要Service类介绍

    • RepositoryService

    Flowable的资源管理类,提供了管理和控制流程发布包和流程定义的操作。除了部署定义流程之外,此服务还支持查询引擎的发布包和流程定义。

    • RuntimeService

    Flowable的流程运行管理类,可以从这个服务类中获取很多关于流程执行的相关信息。

    • TaskService

    Flowable的任务管理类,可以获取当前任务信息。

    • HistoryService

    Flowable历史管理类,可以查询历史信息,执行流程时,引擎会保存很多数据,比如流程实例启动时间,任务参与者等等。

    • ManagementService

    Flowable引擎管理类,提供了Flowable流程引擎管理的管理和维护功能,主要用于Activity系统的日常维护。
    下面我们将使用Flowable提供的相关service实现一个简单流程入门。

    3.2 定义并流程

    Flowable官网给我们提供了一个请假流程图如下所示:
    在这里插入图片描述

    首先这个流程开启了一个请假流程,此请求会被通过或拒绝,若请求通过,就进入外部系统去通过假期请求并结束整个流程。若请求拒绝就发送拒绝邮件然后结束整个流程。
    Flowable支持BPMN2,0,所以整个流程可以用xml进行表示,所以上面的流程图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="Holiday Request" isExecutable="true">
    
        <startEvent id="startEvent"/>
        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>
    
        <userTask id="approveTask" name="Approve or reject request"/>
        <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
    • 54

    现在我们可借助于RepositoryService 完成流程部署,首先将上面流程图片与流程XML保存在resource目录下如下所示:
    在这里插入图片描述

    然后将此流程发布到Flowable引擎代码如下所示:

        /**
         * 部署请假流程
         */
        @Test
        public void deployWorkflow() {
            // 部署流程
            RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();
            // 关联resource下xml文件与图片
            Deployment deployment = repositoryService.createDeployment().addClasspathResource("diagram/holiday-request.png")
                    .addClasspathResource("diagram/holiday-request.bpmn20.xml")
                    // 命名并部署
                    .name("请假流程").category("人事流程管理").key("holiday-request").deploy();
            System.out.println("部署id:" + deployment.getId());
            System.out.println("部署名称:" + deployment.getName());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    运行结果如下所示:
    在这里插入图片描述

    可以在表 act_re_deployment 中 查看到此次流程部署信息入下图所示:
    在这里插入图片描述

    xml流程定义的内容被解析并将相关信息保存在 act_re_procdef 中如下所示:
    在这里插入图片描述

    Xml文档与流程图片直接保存在 act_ge_bytearray 中如下所示:
    在这里插入图片描述

    3.3 查询流程信息

    Flowable提供了相关API可以让我们查询流程部署的相关信息,我们同样可借助RepositoryService构建_ProcessDefinitionQuery_ 对象,我们可以通过act_re_deployment 部署id为1的记录关联查询流程定义信息,act_re_deployment 表记录如下所示:
    在这里插入图片描述
    流程定义表内容如下所示:
    在这里插入图片描述

    查询代码如下所示:

        /**
         * 查询部署信息与请假流程信息
         */
        @Test
        public void queryDeployWorkflow() {
            // 部署流程
            RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId("1")
                    .singleResult();
    
            System.out.println("Found process definition : " + processDefinition.getName());
            System.out.println("Found process definition : " + processDefinition.getKey());
            System.out.println("Found process definition : " + processDefinition.getCategory());
            System.out.println("--------------------------------------------------------------");
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId("1").singleResult();
            System.out.println("Found deployment : " + deployment.getName());
            System.out.println("Found deployment : " + deployment.getCategory());
            System.out.println("Found deployment : " + deployment.getKey());
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行结果如下:
    在这里插入图片描述

    3.4 删除流程

    当定义的流程并发布到Flowable引擎上时,我们使用RepositoryService提供 deleteDeployment 删除流程定义的相关内容信息,具体代码如下:

        /**
         * 删除流程
         */
        @Test
        public void removeWorkflow() {
            RepositoryService repositoryService = processEngineConfiguration.getRepositoryService();
            // 第一个指定删除的流程id信息,第二参数若为true,不管流程是否已经启动都会进行强制删除,一般不推荐使用
            repositoryService.deleteDeployment("1",false);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我们检查相关的三个表act_ge_bytearray、act_re_deployment、act_re_procdef 定义的内容都为空了。需要注意的是 deleteDeployment 方法如果为true,不管流程是否已经启动都会进行强制删除,一般不推荐使用。

    4.3 启动流程实例

    在上面的代码中我们已经将流程定义并发布到Flowable引擎上了,下面就可以启动定义的流程了,所以我们修改一下流程定义的xml并将流程重新部署发布到Flowable引擎上。
    在这里插入图片描述
    在这里插入图片描述

    具体修改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="Holiday Request" isExecutable="true">
    
        <startEvent id="startEvent"/>
        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>
    
        <userTask id="approveTask" name="Approve or reject request" flowable:assignee="zhangsan"/>
        <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" flowable:assignee="lisi"/>
        <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>
    
        <serviceTask id="sendRejectionMail" name="Send out rejection email"
            flowable:class="com.galengao.SendRejectMail"/>
        <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
    • 54

    再次运行发布流程的代码,运行结果如下所示:
    在这里插入图片描述

    下面我们使用Flowable提供的RuntimeService提供的startProcessInstanceByKey方法开启一个流程实例,此方法可接收流程变量,具体代码如下所示:

        /**
         * 开启一个流程实例
         */
        @Test
        public void startProcessInstance() {
            RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
    
            Map<String, Object> variables = new HashMap<String, Object>();
            variables.put("employee", "zhangsan");
            variables.put("duration", 5);
            variables.put("description", "go climbing");
            ProcessInstance processInstance =
                    // 开启流程实例
                    runtimeService.startProcessInstanceByKey("holidayRequest", variables);
            String deploymentId = processInstance.getDeploymentId();
            String activityId = processInstance.getActivityId();
            System.out.println("Deployment Id: "+ deploymentId+" Activity Id: "+ activityId);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果如下:
    在这里插入图片描述

    此次开启的流程实例可在act_ru_task 表查看如下所示;
    在这里插入图片描述

    而刚刚我们传入的Map参数保存在了act_ru_variable表中如下所示:
    在这里插入图片描述

    此次流程节点从开始流转到网关节点,一共经历了2个流程节点,我们可通过act_ru_execution 查看相关信息如下:
    在这里插入图片描述

    4.4 查询流程

    流程任务信息可通过TaskService的createTaskQuery方法进行查询,具体实现代码如下所示:

        /**
         * 查询流程任务
         */
        @Test
        public void queryProcessInstance(){
            TaskService taskService = processEngineConfiguration.getTaskService();
            List<Task> list = taskService.createTaskQuery().processDefinitionKey("holidayRequest")
                    .taskAssignee("zhangsan").list();
            for (Task task : list) {
                String processInstanceId = task.getProcessInstanceId();
                String name = task.getName();
                String assignee = task.getAssignee();
                String description = task.getDescription();
                String id = task.getId();
                System.out.println("processInstanceId: "+processInstanceId+" name: "+name+" assignee: "+assignee+" description: "+description+" id: "+id);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    输出结果如下所示:
    在这里插入图片描述

    4.5 同意与拒绝流程

    • 拒绝流程

    在流程xml定义文件中我们可以查看到如下内容:
    在这里插入图片描述

    Flowable提供了JavaDelegate接口,通过此接口可以做额外业务逻辑处理,例如当审批拒绝后实现发送拒绝邮件的逻辑,我们的发送邮件代码可以这样实现:

    public class SendRejectMail implements JavaDelegate {
    
        /**
         * Flowable的触发器
         */
        @Override
        public void execute(DelegateExecution delegateExecution) {
            // TODO 此处省略真实发送邮件逻辑
            System.out.println("发送拒绝邮件通知------");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    然后再来编写拒绝流程的相关代码如下所示:

        /**
         * 拒绝流程,发送拒绝邮件
         */
        @Test
        public void completeProcessInstanceTask() {
            TaskService taskService = processEngineConfiguration.getTaskService();
            Task task = taskService.createTaskQuery().processDefinitionKey("holidayRequest")
                    .taskAssignee("zhangsan").singleResult();
            Map<String, Object> variables = new HashMap<String, Object>();
            variables.put("approved",false);
            taskService.complete(task.getId(),variables);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行结果如下所示:
    在这里插入图片描述

    同意流程与拒绝流程类似,只需要将上面变量Map **variables 的 **approved 设置为true即可。
    JavaDelegate 接口是个非常有用的接口,我们可以通过此接口在审批通过或者拒绝时,额外进行相关业务处理。

    4.6 查询流程历史信息

    选择使用Flowable这样的流程引擎的众多原因之一是,它自动存储所有流程实例的审计数据或历史数据,这对我们进行后续进行工作汇总、报告提供前期的相关数据支持,例如我们想看到流程运行的时长,我们可借助HistoryService实现我们的需求,具体代码如下所示:

        /**
         * 查询流程历史信息
         */
        @Test
        public void queryHistoryProcessInstance(){
            HistoryService historyService = processEngineConfiguration.getHistoryService();
            // 查询流程历史激活信息
            HistoricActivityInstanceQuery activityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
            // 查询结束的流程信息
            List<HistoricActivityInstance> activityInstances = activityInstanceQuery.processDefinitionId("holidayRequest:1:4").finished()
                    // 按照流程结束时间倒排查询
                    .orderByHistoricActivityInstanceEndTime().desc().list();
            for (HistoricActivityInstance instance : activityInstances) {
                String activityName = instance.getActivityName();
                String activityId = instance.getActivityId();
                Long durationInMillis = instance.getDurationInMillis();
                System.out.println("Activity: " + activityName + " activityId:" + activityId + " durationInMillis:" + durationInMillis);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4. 总结

    本文Flowable和BPMN 2.0的概念和术语,同时借助与Flowable 提供的各种Service完成如下内容:

    • 流程定义
    • 流程定义查询
    • 删除流程定义
    • 启动流程实例
    • 查询流程实例
    • 查询流程相关历史信息

    后面我们将继续更新Flowable相关内容,敬请期待。

    5. 代码仓库

    https://gitee.com/codegeekgao/frameworks-learn/tree/master/flowable-element

  • 相关阅读:
    武汉站--ChatGPT/GPT4科研技术应用与AI绘图及论文高效写作
    mysql 添加limit,sql 语句执行时间变长的问题
    【题解】JZOJ7879 escape from whk 3
    Ubuntu系统下使用docker容器配置nginx并部署前端项目
    JAVA毕业设计好物网站计算机源码+lw文档+系统+调试部署+数据库
    # Spring MVC与RESTful API:如何设计高效的Web接口
    李迟2022年8月工作生活总结
    Python实现线性判别分析教程
    Oracle SQL优化概念之集群因子解析
    将数据库中的数据接入Echarts图表
  • 原文地址:https://blog.csdn.net/javaee_gao/article/details/126772999