Java学习笔记-day01-Flowable工作流入门

课程来源B站大佬波哥的课程
本文仅做笔记,课件需要的联系B站大佬获取

0.前置

相关话术

  1. 流程定义(Process Definition): 描述业务流程的定义,通常使用BPMN(Business Process Model and Notation)进行建模。流程定义包括流程中的任务、网关、事件等元素,以及它们之间的顺序和关系。

  2. 流程实例(Process Instance): 在运行时由流程定义创建的具体流程执行实例。每个流程实例代表了一个特定的业务流程执行过程。

  3. 任务(Task): 流程中需要执行的工作单元,可以是用户任务、服务任务等。任务需要被分配给具体的角色或用户来执行。

  4. 用户任务(User Task): 需要人类参与的任务,通常与特定用户或用户组相关联,需要用户手动完成。

  5. 服务任务(Service Task): 由系统或服务执行的任务,通常是自动化的,不需要人工干预。

  6. 网关(Gateway): 用于控制流程中的分支和合并,决定流程的走向。Flowable支持各种类型的网关,如排他网关、并行网关等。

  7. 流程变量(Process Variable): 在流程实例中传递和存储数据的机制。流程变量可以在不同的任务之间传递信息,用于控制流程的行为。

  8. 部署(Deployment): 将流程定义部署到Flowable引擎中,使其可以被实例化和执行。一个部署可以包含一个或多个流程定义。

  9. 执行(Execution): 表示流程实例中的一个执行状态,包含当前执行到的节点、流程变量等信息。

  10. 历史数据(Historic Data): 记录流程实例的历史信息,包括已完成的任务、执行时间等。Flowable提供了历史数据查询的功能。

  11. 流程引擎(Process Engine): 是flowable的核心,或者说是flowable本身,它提供了执行、控制和管理流程实例的功能。

工作过程

  1. 流程建模: 首先,业务分析师或流程设计者使用流程建模工具,如Flowable提供的图形化建模工具,创建业务流程模型。这个模型包括流程定义、任务、网关、事件等元素,以及它们之间的流程顺序和条件。

  2. 部署流程定义: 将创建好的流程模型进行部署。部署是将流程定义加载到流程引擎中的一个过程,使其可以被实例化和执行。部署可以包括一个或多个流程定义,并在流程引擎中分配唯一的标识符。

  3. 流程实例化: 当需要执行业务流程时,流程引擎根据已部署的流程定义创建流程实例。每个流程实例都是特定业务流程的一个具体执行过程。

  4. 流程执行: 流程引擎根据流程定义中的逻辑,按照事先定义的流程顺序和条件执行各个任务和活动。这可能涉及到用户任务(等待人工处理)、服务任务(自动化任务)、网关(流程控制)等。

  5. 任务分配和处理: 当流程中涉及到用户任务时,流程引擎将任务分配给具体的用户或用户组。这个过程可以包括通知相关人员,提醒他们有任务需要处理。

  6. 流程控制: 流程引擎根据流程中的网关来控制流程的走向,例如,并行网关允许多个路径同时执行,排他网关根据条件选择一个路径。

  7. 流程变量: 在流程实例执行过程中,流程引擎可以使用和传递流程变量,这些变量可以在不同的任务之间传递数据,影响流程的行为。

  8. 历史记录: 流程引擎记录流程实例的历史数据,包括已完成的任务、执行时间、流程变量等。这些历史数据对于监控和报告业务流程的执行情况非常重要。

  9. 流程结束: 当流程中的所有任务和活动都完成时,流程实例结束。此时,可以进行一些收尾工作,如记录最终状态、生成报告等。

引入flowable时pom所需依赖

    <dependencies>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-engine</artifactId>
            <version>6.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-json-converter</artifactId>
            <version>6.3.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>
    </dependencies>

log4j配置文件

在resource目录下创建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
准备一个空mysql数据库,库名:flowable-learn

1.创建ProcessEngine

ProcessEngineFlowable的核心组件之一,主要功能如下

  • 流程执行
  • 任务分配和处理
  • 流程监控和报告
  • 流程建模
  • 自动化

创建ProcessEngine代码如下:

public static void main(String[] args) {
    ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
        .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC")
        .setJdbcUsername("root")
        .setJdbcPassword("123456")
        .setJdbcDriver("com.mysql.cj.jdbc.Driver")
        .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    ProcessEngine processEngine = cfg.buildProcessEngine();
}
  • setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE):
    这行代码会为数据库初始化flowable的表。

flowable表说明

相关表
  1. ACT_RE_*: 这些表存储着流程引擎的元数据,包括流程定义、用户任务、服务任务等。常见的表包括:

    • ACT_RE_PROCDEF: 存储流程定义信息。
    • ACT_RE_DEPLOYMENT: 存储流程部署信息。
    • ACT_RE_MODEL: 存储模型信息。
  2. ACT_RU_*: 这些表存储流程引擎的运行时数据,包括运行时的流程实例、任务实例等。常见的表包括:

    • ACT_RU_EXECUTION: 存储流程实例的执行信息。
    • ACT_RU_TASK: 存储任务实例信息。
    • ACT_RU_VARIABLE: 存储运行时的流程变量。
  3. ACT_HI_*: 这些表存储流程引擎的历史数据,包括已完成的流程实例、任务实例等。常见的表包括:

    • ACT_HI_PROCINST: 存储已完成的流程实例信息。
    • ACT_HI_TASKINST: 存储已完成的任务实例信息。
    • ACT_HI_ACTINST: 存储流程实例中已执行的活动信息。
  4. ACT_ID_*: 这些表存储身份和权限相关的数据,用于用户、用户组、成员关系等。常见的表包括:

    • ACT_ID_USER: 存储用户信息。
    • ACT_ID_GROUP: 存储用户组信息。
    • ACT_ID_MEMBERSHIP: 存储用户与用户组的关系。
所有表

这是 Flowable 数据库中的一组表,每个表都有特定的用途,用于存储流程引擎的不同方面的信息。以下是这些表的简要说明:

  1. act_evt_log: 存储引擎的事件日志,记录流程引擎执行过程中的事件。

  2. act_ge_bytearray: 存储字节数组,通常用于存储流程定义文件(如 BPMN 文件)和流程图。

  3. act_ge_property: 存储全局引擎属性,用于存储引擎的一些全局配置信息。

  4. act_hi_actinst: 存储历史活动实例数据,包括已完成的活动(节点)的详细信息。

  5. act_hi_attachment: 存储历史附件数据,记录与流程实例、任务实例相关的附件信息。

  6. act_hi_comment: 存储历史评论/备注数据,记录用户对流程实例或任务实例的评论。

  7. act_hi_detail: 存储历史详情数据,用于存储与历史流程实例和任务实例相关的详细信息。

  8. act_hi_identitylink: 存储历史身份链接数据,记录与历史流程实例和任务实例相关的身份链接信息。

  9. act_hi_procinst: 存储已完成的流程实例的详细信息。

  10. act_hi_taskinst: 存储已完成的任务实例的详细信息。

  11. act_hi_varinst: 存储历史变量实例数据,记录历史流程变量的信息。

  12. act_id_bytearray: 存储字节数组,通常用于存储用户头像等信息。

  13. act_id_group: 存储用户组信息。

  14. act_id_info: 存储用户附加信息。

  15. act_id_membership: 存储用户与用户组的关系。

  16. act_id_priv: 存储用户特权信息。

  17. act_id_priv_mapping: 存储用户特权映射关系。

  18. act_id_property: 存储用户属性信息。

  19. act_id_token: 存储用户身份验证令牌信息。

  20. act_id_user: 存储用户信息。

  21. act_procdef_info: 存储流程定义的信息。

  22. act_re_deployment: 存储流程部署信息。

  23. act_re_model: 存储模型信息。

  24. act_re_procdef: 存储流程定义信息。

  25. act_ru_deadletter_job: 存储运行时死信作业(失败的异步任务)信息。

  26. act_ru_event_subscr: 存储运行时事件订阅信息。

  27. act_ru_execution: 存储运行时流程执行实例信息。

  28. act_ru_history_job: 存储运行时历史作业信息。

  29. act_ru_identitylink: 存储运行时身份链接信息,与运行时流程实例和任务实例相关。

  30. act_ru_job: 存储运行时作业信息,用于异步任务等。

  31. act_ru_suspended_job: 存储运行时挂起的作业信息。

  32. act_ru_task: 存储运行时任务实例信息。

  33. act_ru_timer_job: 存储运行时定时作业信息。

  34. act_ru_variable: 存储运行时变量信息。

2.部署流程定义

  • 流程引擎会将XML文件存储在数据库中,这样可以在需要的时候获取它
  • 流程定义转换为内部的、可执行的对象模型,这样使用它就可以启动流程实例

2.1.创建流程定义bpmn2.0文件

将下面的XML保存在src/main/resources文件夹下名为holiday-request.bpmn20.xml的文件中。
流程定义的内容

<?xml version="1.0" encoding="UTF-8"?>
<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">
                <![CDATA[
          ${approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>
        <sequenceFlow sourceRef="decision" targetRef="sendRejectionMail">
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${!approved}
        ]]>
            </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="com.mushfish.flowable.SendRejectionMail"/>
        <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>

        <endEvent id="approveEnd"/>

        <endEvent id="rejectEnd"/>
    </process>

</definitions>

2.2.将流程定义部署至Flowable引擎

2.2.0.前置知识-Flowable提供的service
  1. RepositoryService: 用于管理流程定义的服务。可以通过该服务进行流程定义的部署、查询和删除等操作。

  2. RuntimeService: 提供对运行时流程实例和执行流程任务的访问。可以用于启动、查询、操作流程实例,以及处理流程任务。

  3. TaskService: 用于管理流程任务的服务。可以通过该服务进行任务的查询、领取、完成等操作。

  4. HistoryService: 提供对历史数据的访问,包括已完成的流程实例、任务、变量等的查询。

  5. IdentityService: 提供对流程引擎中的用户和组的管理。可以用于查询和管理用户、组、用户组关系等。

  6. ManagementService: 提供对引擎的管理和监控功能,例如获取引擎信息、执行数据库操作等。

  7. FormService: 提供对表单数据的访问和处理,用于处理用户任务表单的提交和查询。

  8. DynamicBpmnService: 提供对动态BPMN(Business Process Model and Notation)的支持,允许在运行时对流程进行动态修改。

2.2.1.部署流程定义

将流程定义部署至Flowable引擎,需要使用RepositoryService,其可以从ProcessEngine对象获取。使用RepositoryService,可以通过XML文件的路径创建一个新的部署(Deployment),并调用*deploy()*方法实际执行:

    /**
     * 部署流程
     */
    @Test
    public void testDeploy(){
        // 配置数据库相关信息 获取 ProcessEngineConfiguration
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
                .setJdbcUsername("root")
                .setJdbcPassword("123456")
                .setJdbcDriver("com.mysql.cj.jdbc.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 获取流程引擎对象
        ProcessEngine processEngine = cfg.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());

    }

执行成功后,数据库相关表会发生变化
act_re_deployment: 流程定义部署表,每部署一次就增加一条记录
act_re_procdef :流程定义表,部署每个新的流程定义都会在这张表中增加一条记录
act_ge_bytearray :流程资源表,流程部署的 bpmn文件和png图片会保存在该表中

2.2.2.查看流程定义

通过API查询并验证流程定义已经部署在引擎中。通过RepositoryService创建的ProcessDefinitionQuery对象实现。

/**
     * 查看流程定义
     */
    @Test
    public void testDeployQuery(){
        // 配置数据库相关信息 获取 ProcessEngineConfiguration
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
                .setJdbcUsername("root")
                .setJdbcPassword("123456")
                .setJdbcDriver("com.mysql.cj.jdbc.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 获取流程引擎对象
        ProcessEngine processEngine = cfg.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());

    }

3.启动流程实例

现在已经在流程引擎中部署了流程定义,因此可以使用这个流程定义作为“模板”启动流程实例

要启动流程实例,需要提供一些初始化流程变量。一般来说,可以通过呈现给用户的表单,或者在流程由其他系统自动触发时通过REST API,来获取这些变量。在这个例子里,我们简化直接在代码中定义了,我们使用RuntimeService启动一个流程实例

    /**
     * 启动流程实例
     */
    @Test
    public void testRunProcess(){
        // 配置数据库相关信息 获取 ProcessEngineConfiguration
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
                .setJdbcUsername("root")
                .setJdbcPassword("123456")
                .setJdbcDriver("com.mysql.cj.jdbc.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 获取流程引擎对象
        ProcessEngine processEngine = cfg.buildProcessEngine();
        // 启动流程实例通过 RuntimeService 对象
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 构建流程变量
        Map<String,Object> variables = new HashMap<>();
        variables.put("employee","张三") ;// 谁申请请假
        variables.put("nrOfHolidays",3); // 请几天假
        variables.put("description","工作累了,想出去玩玩"); // 请假的原因
        // 启动流程实例,第一个参数是流程定义的id
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey("holidayRequest", variables);// 启动流程实例
        // 输出相关的流程实例信息
        System.out.println("流程定义的ID:" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例的ID:" + processInstance.getId());
        System.out.println("当前活动的ID:" + processInstance.getActivityId());
    }

启动流程实例涉及到的表结构:

  • act_hi_actinst 流程实例执行历史
  • act_hi_identitylink 流程的参与用户的历史信息
  • act_hi_procinst 流程实例历史信息
  • act_hi_taskinst 流程任务历史信息
  • act_ru_execution 流程执行信息
  • act_ru_identitylink 流程的参与用户信息
  • act_ru_task 任务信息

4.查看任务

上面员工发起了一个请假流程,接下来就会流转到总经理这儿来处理,之前我们没有指定经理这的处理人,我们可以加一个

  1. 添加任务执行人
    修改holiday-request.bpmn20.xml文件,增加任务执行人flowable:assignee="lisi"
    <userTask id="approveTask" name="Approve or reject request" flowable:assignee="lisi"/>
    
  2. 查看任务
    因修改了流程定义,需先依次执行部署流程启动流程实例,才能查看到lisi的任务
        /**
    * 查看任务
    */
    @Test
    public void testQueryTask(){
       // 配置数据库相关信息 获取 ProcessEngineConfiguration
       ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
               .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
               .setJdbcUsername("root")
               .setJdbcPassword("123456")
               .setJdbcDriver("com.mysql.cj.jdbc.Driver")
               .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
       // 获取流程引擎对象
       ProcessEngine processEngine = cfg.buildProcessEngine();
       TaskService taskService = processEngine.getTaskService();
       List<Task> list = taskService.createTaskQuery()
               .processDefinitionKey("holidayRequest")
               .taskAssignee("lisi")
               .list();
       for (Task task : list) {
           System.out.println("task.getProcessDefinitionId() = " + task.getProcessDefinitionId());
           System.out.println("task.getId() = " + task.getId());
           System.out.println("task.getAssignee() = " + task.getAssignee());
           System.out.println("task.getName() = " + task.getName());
       }
    }
    

输出结果

task.getProcessDefinitionId() = holidayRequest:4:15003
task.getId() = 17508
task.getAssignee() = lisi
task.getName() = Approve or reject request
task.getProcessDefinitionId() = holidayRequest:4:15003
task.getId() = 20008
task.getAssignee() = lisi
task.getName() = Approve or reject request
task.getProcessDefinitionId() = holidayRequest:7:30003
task.getId() = 32508
task.getAssignee() = lisi
task.getName() = Approve or reject request
task.getProcessDefinitionId() = holidayRequest:8:35003
task.getId() = 37508
task.getAssignee() = lisi
task.getName() = Approve or reject request
task.getProcessDefinitionId() = holidayRequest:9:40003
task.getId() = 42508
task.getAssignee() = lisi
task.getName() = Approve or reject request
task.getProcessDefinitionId() = holidayRequest:9:40003
task.getId() = 45008
task.getAssignee() = lisi
task.getName() = Approve or reject request

解释结果:
task.getProcessDefinitionId() 是 Flowable 任务对象中的一个方法,用于获取与当前任务相关的流程定义的标识符(ID)。在上述例子中,holidayRequest:4:15003 是一个具体的流程定义的标识符。

具体解释如下:

  • holidayRequest: 这部分是流程定义的 Key,通常表示该流程的业务标识。在 BPMN 模型中,Key 是流程定义的一个属性,用于唯一标识一个流程。

  • 4: 这部分是流程定义的版本号。在 Flowable 中,每次对流程定义进行修改并重新部署时,版本号会递增。

  • 15003: 这部分是流程定义的数据库主键(ID)。每个流程定义在数据库中都有一个唯一的主键。

  • holidayRequest:4:15003 为act_re_procdef表主键值

  • 执行一次部署流程会增加版本号,执行一次启动流程实例会增加task

5.完成任务

现在lisi这个角色可以来完成当前的任务了

前置知识-接口JavaDelegate

org.flowable.engine.delegate.JavaDelegate
org.flowable.engine.delegate.JavaDelegate 是 Flowable 中的一个接口,用于在流程执行过程中执行自定义的 Java 代码。这个接口是 Flowable 中的一个任务监听器类型,通常被用于在流程的特定节点或任务中执行业务逻辑。

具体来说,JavaDelegate 接口定义了一个方法:

void execute(DelegateExecution execution);

在这个方法中,你可以编写自己的 Java 代码,用于处理与特定任务或节点相关的业务逻辑。DelegateExecution 对象提供了访问流程执行上下文的方法,允许你获取和设置流程变量、操作任务等。

一个典型的使用场景是将 JavaDelegate 用作用户任务节点的任务监听器。当流程引擎到达一个用户任务时,JavaDelegate 可以被触发,执行与该用户任务相关的自定义逻辑,例如发送通知、调用其他系统、更新数据等。

以下是一个简单的示例,演示如何实现 JavaDelegate

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

public class MyJavaDelegate implements JavaDelegate {

    @Override
    public void execute(DelegateExecution execution) {
        // 从流程执行上下文中获取信息
        String processInstanceId = execution.getProcessInstanceId();
        String currentActivityId = execution.getCurrentActivityId();

        // 执行自定义的业务逻辑
        System.out.println("Executing JavaDelegate for process instance " + processInstanceId +
                ", current activity: " + currentActivityId);

        // 可以进行更复杂的业务逻辑处理
        // ...
    }
}

在 BPMN 文件中,你可以将这个 JavaDelegate 配置为任务的监听器,如下所示:

<serviceTask id="myServiceTask" name="My Service Task" flowable:class="com.example.MyJavaDelegate" />

这样,当流程执行到这个任务时,MyJavaDelegate 中的 execute 方法将被调用,允许你执行自定义的业务逻辑。

自定义JavaDelegate

holiday-request.bpmn20.xml中有


<serviceTask id="sendRejectionMail" name="Send out rejection email"
             flowable:class="com.mushfish.flowable.SendRejectionMail"/>

因此,在org.flowable包下创建SendRejectionMail

public class SendRejectionMail implements JavaDelegate {
    /**
     * 这个一个Flowable中的触发器
     * @param execution
     */
    @Override
    public void execute(DelegateExecution execution) {
        // 触发执行的逻辑  按照我们在流程中的定义应该给被拒绝的员工发送通知的邮件
        System.out.println("不好意思,你的请假申请被拒绝了....安心工作");
    }
}
完成任务
    /**
     * 完成任务
     */
    @Test
    public void testCompleteTask(){
        // 配置数据库相关信息 获取 ProcessEngineConfiguration
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
                .setJdbcUsername("root")
                .setJdbcPassword("123456")
                .setJdbcDriver("com.mysql.cj.jdbc.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 获取流程引擎对象
        ProcessEngine processEngine = cfg.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("holidayRequest")
                .taskAssignee("lisi")
                .list();
        // 添加流程变量
        Map<String,Object> variables = new HashMap<>();
        variables.put("approved",false); // 拒绝请假
        // 完成任务
        for (Task task : list) {
            taskService.complete(task.getId(),variables);
        }

    }

6.流程删除

    /**
     * 删除流程
     */
    @Test
    public void testDeleteProcess(){
        // 配置数据库相关信息 获取 ProcessEngineConfiguration
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
                .setJdbcUsername("root")
                .setJdbcPassword("123456")
                .setJdbcDriver("com.mysql.cj.jdbc.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 获取流程引擎对象
        ProcessEngine processEngine = cfg.buildProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 删除流程定义,如果该流程定义已经有了流程实例启动则删除时报错
        // repositoryService.deleteDeployment("1");
        // 设置为true 级联删除流程定义,即使流程有实例启动,也可以删除;
        // 设置为false 非级联删除操作。
        repositoryService.deleteDeployment("2501",true);//库中act_re_deployment表的主键值

    }

7.查看历史信息

- 查看历史任务执行时间
/**
     * 查看历史
     */
    @Test
    public void testQueryHistory(){
        // 配置数据库相关信息 获取 ProcessEngineConfiguration
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
                .setJdbcUsername("root")
                .setJdbcPassword("123456")
                .setJdbcDriver("com.mysql.cj.jdbc.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 获取流程引擎对象
        ProcessEngine processEngine = cfg.buildProcessEngine();
        HistoryService historyService = processEngine.getHistoryService();
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processDefinitionId("holidayRequest:3:5003") //act_re_procdef主键值
                .finished()
                .orderByHistoricActivityInstanceEndTime().asc()
                .list();
        for (HistoricActivityInstance historicActivityInstance : list) {
            System.out.println(historicActivityInstance.getActivityId() + " took "
                    + historicActivityInstance.getDurationInMillis() + " milliseconds");
        }

    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/304740.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

没有货源是不是就没办法在家做抖店?打包发货怎么完成?解答如下

我是王路飞。 有人问了我一个问题&#xff1a;无货源模式的抖店&#xff0c;自己一个人在家里做不了是吧&#xff1f;毕竟打包发货这些问题怎么解决呢&#xff1f; 店铺要是发货不及时被平台罚款怎么办&#xff1f;产品有质量问题怎么解决呢&#xff1f;店铺一直不出单怎么办…

并发程序设计--D5~D7线程的创建、回收和取消清理

一个进程中的多个线程共享以下资源 可执行指令 静态数据 进程中打开的文件描述符 当前工作目录 用户ID 用户组ID 每个线程私有的资源 线程ID PC&#xff08;程序计数器&#xff09;和相关寄存器 堆区和栈区 错误号&#xff08;errno&#xff09; 优先级 执行状态和属性 线程的…

2024阿里云服务器ECS实例全方位介绍_优缺点大全

阿里云服务器ECS英文全程Elastic Compute Service&#xff0c;云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务&#xff0c;阿里云提供多种云服务器ECS实例规格&#xff0c;如经济型e实例、通用算力型u1、ECS计算型c7、通用型g7、GPU实例等&#xff0c;阿里云服务器网aliyu…

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -用户信息修改实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…

数字化解决方案在市政交通大显身手

Bentley 应用程序促进了创新设计解决方案&#xff0c;预计可在 25 年内节省 3,200 万美元 大规模现代化计划 大学大道位于爱荷华州锡达福尔斯市繁忙的社区&#xff0c;是一条重要的六车道高速公路&#xff0c;长约两英里&#xff0c;每天通行的车辆有 2 万多辆。该道路已有 60…

java编程中,保证接口幂等性的实现方案讨论

一、什么是幂等性 数学中的幂等是指f(x) f(f(x))&#xff0c;编程领域的术语是指同一个操作&#xff0c;在重复提交的情况下&#xff0c;最终产生的影响是不变的。举例说&#xff1a; 提交订单时&#xff0c;用户在购物车界面&#xff0c;重复点击“下单”&#xff0c;服务端…

vxe-树形结构层级过多横向滚动条设置

一. 问题 在使用vxe-table中的树形结构的时候&#xff0c;如果树形结构的层级过多的话的会导致层级很深的层级&#xff0c;鼠标点击无法选中&#xff0c;对应的内容显示不完全。 层级过多后 二. 解决 方法1&#xff1a;动态的计算所占行的宽度&#xff0c;选取最大宽度给表格列…

统信UOS虚拟机安装VirtualBox扩展使用USB功能

为什么要安装VirtualBox扩展包&#xff1f; 安装 Oracle VM VirtualBox 扩展包的原因是&#xff0c;它提供了对 USB 2.0、USB 3.0、远程桌面协议 VRDP&#xff08;VirtualBox Remote Desktop Protocol&#xff09;等实用功能的支持&#xff0c;以增强 VirtualBox 的功能。这些…

MIT_线性代数笔记:第 25 讲 对称矩阵和正定性

目录 对称矩阵 Symmetric matrices实特征值 Real eigenvalues正定矩阵 Positive definite matrices 对称矩阵是最重要的矩阵之一&#xff0c;其特征值为实数并且拥有一套正交特征向量。正定矩阵的性质则更好。 对称矩阵 Symmetric matrices 包含特殊性质的矩阵&#xff0c;例如…

CCF模拟题 202309-1 坐标变换(其一)

问题描述 试题编号&#xff1a; 202309-1 试题名称&#xff1a; 坐标变换&#xff08;其一&#xff09; 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 问题描述&#xff1a; 对于平面直角坐标系上的坐标&#xff08;x,y&#xff09;&#xff0c;小P定义了一个包含…

【Flutter 开发实战】Dart 基础篇:常用运算符

在Dart中&#xff0c;运算符是编写任何程序的基本构建块之一。本文将详细介绍Dart中常用的运算符&#xff0c;以帮助初学者更好地理解和运用这些概念。 1. 算术运算符 算术运算符用于执行基本的数学运算。Dart支持常见的加、减、乘、除、整除以及取余运算。常见的算数运算符如…

从虚拟到现实:数字孪生驱动智慧城市可持续发展

随着科技的飞速发展&#xff0c;智慧城市已经成为未来城市发展的重要趋势。数字孪生技术作为智慧城市建设中的关键技术之一&#xff0c;正在发挥着越来越重要的作用。本文将探讨数字孪生如何从虚拟走向现实&#xff0c;驱动智慧城市的可持续发展。 一、数字孪生技术&#xff1…

【CV】计算两个向量的夹角,并使用 OpenCV 可视化弧线

背景 基于人体/动物,骨骼点数据,计算关节角度 1. 原理 计算两个向量的夹角,我们已三个点为例,BA 向量和BC向量,求 B 的角度。若为四个点,延长交叉即可。 2. 效果 效果图如下 3. 核心代码 def compute_vector_angle(a, b, c):"""计算两个向量 ba 和…

Unity中BRP下的深度图

文章目录 前言一、在Shader中使用1、在使用深度图前申明2、在片元着色器中 二、在C#脚本中开启摄像机深度图三、最终效果 前言 在之前的文章中&#xff0c;我们实现了URP下的深度图使用。 Unity中URP下使用屏幕坐标采样深度图 在这篇文章中&#xff0c;我们来看一下BRP下深度…

【PB续命07】JDBC连接达梦数据库

JDBC(Java DataBase Connectivity) 称为Java数据库连接&#xff0c;它是一种用于数据库访问的应用程序API&#xff0c;由一组用Java语言编写的类和接口组成&#xff0c;有了JDBC就可以用同一的语法对多种关系数据库进行访问&#xff0c;而不用担心其数据库操作语言的差异。 有了…

无线网卡怎么连接台式电脑?正确操作步骤分享!

“我在使用电脑时经常都需要用到网络&#xff0c;请问大家在使用无线网卡时怎么将它与台式电脑进行连接的呢&#xff1f;” 使用电脑的用户在进行网上冲浪时都需要先连接网络。如果不想使用网线&#xff0c;无线网卡不仅可以为用户提供网络服务&#xff0c;在使用时该更加灵活和…

实战:低代码表单引擎助力文件上传与数据处理

在当今的信息化时代&#xff0c;数据已成为企业的重要资产。为了更好地管理和利用这些数据&#xff0c;许多企业开始采用表单上传组件来导入和处理数据。通过使用表单上传组件&#xff0c;用户可以方便地将文件上传至系统中&#xff0c;然后进行后续的数据处理和分析。这种方式…

Java零基础教学文档第一篇:JavaSE(3)

接上期后续 本期继续分享尚未结束的JavaSE章节 JavaSE属于初入门阶段&#xff0c;内容很多~ 但很基础&#xff0c; 大家需保持耐心&#xff0c;慢慢的学~ 争取你们学习的速度&#xff01; 跟上我更新的速度哦~ 今日新篇章 流程控制语句 【主要内容】 if单选结构 if双选结构…

适合培训协会搭建的培训机构管理系统开发方案

一、项目背景与目标 &#xff08;一&#xff09;项目背景 培训学校教务管理系统是培训机构数字化管理的必备系统&#xff0c;该系统功能大大提升机构办学的管理效率、提升机构在家长心中的专业度&#xff0c;市面上的培训机构管理系统收费越来越贵&#xff0c;为了给协会内培…

什么情况?DDD 中的每个任务都执行了两次?

最近在使用 COLA 框架自带的异步任务时&#xff0c;发现每次执行异步都执行了两次&#xff0c;如果一些没有做幂等的接口&#xff0c;这样是会有问题的&#xff0c;比如入库操作之类的&#xff0c;就会造成数据重复入库&#xff0c;造成严重 bug。 带着疑惑&#xff0c;开始了…