Flowable进阶学习(四)任务分配与流程变量

一、任务分配

1. 固定分配

在绘制流程图时或在流程文件中通过Assignee来指定的方式。
在这里插入图片描述在这里插入图片描述

2. 表达式分配

Flowable使用UEL(Unified Expression Language)进行表达式解析。Flowable支持两种UEL表达式:UEL-value和UEL-method。

值表达式:Value expression

解析为一个值,默认情况下,所有流程变量都可以使用。所有的SpringBean也可以使用在表达式里。eg:${myVar}${myBean.myProperty}

  1. 创建流程文件
    在这里插入图片描述在这里插入图片描述

  2. 启动一个流程实例

    /**
    * 启动流程实例
    */
    @Test
    public void test2_run_proc() {
       Map<String, Object> params = new HashMap<>();
       params.put("assignee0", "whx");
       params.put("assignee1", "huathy");
       ProcessInstance processInstance = processEngine.getRuntimeService()
               .startProcessInstanceById("qjlc23:1:4", params);
       System.out.println("processInstance.getName() = " + processInstance.getName());
       Map<String, Object> processVariables = processInstance.getProcessVariables();
       for (String key : processVariables.keySet()) {
           System.out.println("params => " + key + "~" + processVariables.get(key));
       }
    }
    
  3. 通过查看表数据变动,可以看到ASSIGNEE_的值为whx,可见表达式已经被解析。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    -- ACT_RU_TASK
    ID_ |REV_|EXECUTION_ID_|PROC_INST_ID_|PROC_DEF_ID_|TASK_DEF_ID_|SCOPE_ID_|SUB_SCOPE_ID_|SCOPE_TYPE_|SCOPE_DEFINITION_ID_|NAME_ |PARENT_TASK_ID_|DESCRIPTION_|TASK_DEF_KEY_                           |OWNER_|ASSIGNEE_|DELEGATION_|PRIORITY_|CREATE_TIME_           |DUE_DATE_|CATEGORY_|SUSPENSION_STATE_|TENANT_ID_|FORM_KEY_|CLAIM_TIME_|IS_COUNT_ENABLED_|VAR_COUNT_|ID_LINK_COUNT_|SUB_TASK_COUNT_|
    ----+----+-------------+-------------+------------+------------+---------+-------------+-----------+--------------------+------+---------------+------------+----------------------------------------+------+---------+-----------+---------+-----------------------+---------+---------+-----------------+----------+---------+-----------+-----------------+----------+--------------+---------------+
    7507|   1|7504         |7501         |qjlc23:1:4  |            |         |             |           |                    |提交请假申请|               |            |sid-04330515-D69E-4BA7-94FE-492984A4E5A0|      |whx      |           |       50|2023-01-21 23:41:58.912|         |         |                1|          |         |           |                1|         0|             0|              0|
    
  4. 完成流程实例

    /**
     * 完成任务
     */
    @Test
    public void test2_complete_proc() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processInstanceId("7501")
                .taskAssignee("whx").singleResult();
        taskService.complete(task.getId());
    }
    
  5. 查看数据库ACT_RU_TASK表(可见节点名称与任务指派人已变化) 在这里插入图片描述

方法表达式:Method expression

调用一个方法,可以带参或者不带。当调用无参方法的时候,要确保方法名后面添加空括号(避免与值表达式混淆)。传递的参数可以是字面值,也可以是表达式,会进行自动解析。eg:

${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.do(myvar, execution)}

myBean是spring容器中的一个Bean对象,表示调用bean的addNewOrder方法。

3. 监听器分配

可以使用监听器来完成很多flowable的流程业务。
我们在此处使用监听器来完成负责人的指定,那么我们在流程设计的时候就不需要指定assignee。

  1. 创建一个监听器类
package org.flowable.listener;

import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;

/**
 * @author Huathy
 * @date 2023-01-22 12:28
 * @description 自定义监听器
 */
public class MyTaskListener implements TaskListener {

    /**
     * 监听器触发的方法
     *
     * @param delegateTask
     */
    @Override
    public void notify(DelegateTask delegateTask) {
        System.out.println("==》MyTaskListener监听器触发");
        System.out.println("delegateTask.getName() = " + delegateTask.getName());
        // 当满足条件则设置任务分配人为huathy否则为whx
        if ("提交请假申请".equals(delegateTask.getName()) && "create".equalsIgnoreCase(delegateTask.getEventName())) {
            delegateTask.setAssignee("huathy");
        } else {
            delegateTask.setAssignee("whx");
        }
    }
}
  1. 设计流程,导出流程文件
    在这里插入图片描述3. 部署流程
    @Test
    public void test1_deploy() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("请假流程23-02.bpmn20.xml")
                .name("测试请假流程2023-02").deploy();
        System.out.println("deploy.getName() = " + deploy.getName());
        System.out.println("deploy.getId() = " + deploy.getId());
    }
    

4. 发起人处理

在这里插入图片描述
在这里插入图片描述

案例

  1. 部署流程
@Test
void deploy() {
    Deployment deployment = repositoryService.createDeployment()
            .addClasspathResource("process/发起人处理任务.bpmn20.xml")
            .name("ReceiveTask").deploy();
    logger.info("deployment.getId() = " + deployment.getId());
    logger.info("deployment.getName() = " + deployment.getName());
}
  1. 启动流程 与 查询任务
/** 启动流程 */
@Test
void startFlow() {
    // 设置发起人
    Authentication.setAuthenticatedUserId("Huathy");
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(PROC_KEY);
    logger.info("processInstance.getId() = " + processInstance.getId());
}

/** 获取执行任务 */
@Test
void getTask() {
    List<Task> list = taskService.createTaskQuery()
            .processDefinitionKey(PROC_KEY).list();
    list.forEach(task -> {
        String msg = String.format("tId: %s,tName: %s, Assignee: %s", task.getId(), task.getName(),task.getAssignee());
        logger.info(msg);
    });
}

二、流程变量

流程实例按步骤执行时,需要使用一些数据。在Flowable中,这些数据称作变量(variable),并存储到数据库中。变量可以用在表达式中(例如在排他网关中用于选择正确的出口路径),也可以在Java服务任务(service task)中用于调用外部服务(例如为服务提供输入或结果存储),等等。
咯iu成实例可以持有变量(称作流程变量process variables),用户任务以执行(excutions)——流程当前活动节点的指针——也可以持有变量。流程实例可以持有任意数量的变量,每个变量存储为ACT_RU_VARIABLE数据库表的一行记录。
所有的startProcessInstanceXXX方法都有一个可选参数,用于在流程实例创建及启动时设置变量。eg:在RuntimeService中:

ProcessInstance startProcessInstanceById(String processDefinitionId, Map<String, Object> variables);

也可以在流程执行中加入变量,eg:RuntimeService

void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);

实例关系:通常情况下没有子流程的,流程实例与执行实例一一对应。
实例关系

1. 全局变量

流程变量的默认作用域是流程实例。当一个流程变量的作用域为流程实例的时候,可以称为global变量。eg:userId。
global变量中变量名不可重复,设置相同名称的变量,新值会覆盖旧值。

2. 局部变量

任务和执行实例仅仅是针对要给任务和一个执行实例的范围,范围没有流程实例大,成为local变量。
local变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同。local变量名也可以与global变量名相同。

案例:

员工创建出差申请单,由上级领导审批通过后,根据天数判断,3天内可由财务审批通过,3天以上需要流转到总经理审批,再由财务审批。

员工出差流程图

package com.hx;

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Huathy
 * @date 2022-05-12 23:40
 * @description
 * 1.首先部署流程   2.运行流程实例   3.提交出差申请   4.更新流程变量
 * 5.完成上级审批   6.观察数据库变化
 */
public class Test6_Demo1_Evection {
    ProcessEngineConfiguration configuration = null;
    ProcessEngine processEngine = null;

    @Before
    public void before() {
        // 通过 ProcessEngineConfiguration 构建我们需要的 ProcessEngine
        configuration = new StandaloneInMemProcessEngineConfiguration();
        // 配置相关数据库连接
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("admin");
        configuration.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flowable1?serverTimeZone=UTC&nullCatalogMeansCurrent=true");
        // 如果数据库中的表结构不存在则新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        processEngine = configuration.buildProcessEngine();
    }

    @Test
    public void test_deploy() {
        // 2. 获取 RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3. 完成流程部署操作
        Deployment deploy = repositoryService.createDeployment()
                // 关联要部署的流程文件
                .addClasspathResource("出差申请流程.bpmn20.xml")
                .name("出差申请流程2023")
                .deploy();  // 部署流程
        System.out.println("deploy.getId() => " + deploy.getId());
        System.out.println("deploy.getName() => " + deploy.getName());
    }

    @Test
    public void test_run_proc() {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String, Object> params = new HashMap<>();
        params.put("assignee0", "whx");
        params.put("assignee1", "hx1");
        params.put("assignee2", "hx2");
        params.put("assignee3", "huathy");
        runtimeService.startProcessInstanceById("CCSQLC:1:4", params);
    }

    @Test
    public void test_complete_task1() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();
        // 获取当前流程实例的所有变量
        Map<String, Object> processVariables = task.getProcessVariables();
        processVariables.put("num", 2);
        taskService.complete(task.getId(), processVariables);
    }

    /**
     * 根据taskID来更新本地(实例)变量
     */
    @Test
    public void test_update_variables_local() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();
        // 获取当前流程实例的所有变量
        Map<String, Object> processVariables = task.getProcessVariables();
        processVariables.put("num", 6);
        taskService.setVariablesLocal(task.getId(), processVariables);
    }

    /**
     * 根据taskID来更新流程变量
     */
    @Test
    public void test_update_variables() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();
        // 获取当前流程实例的所有变量。当局部变量和全局变量都存在的时候,取出来的是局部变量。
        Map<String, Object> processVariables = task.getProcessVariables();
        processVariables.put("num", 5);
        taskService.setVariables(task.getId(), processVariables);
    }

    /**
     * 完成上级审批
     */
    @Test
    public void test_complete_task2() {
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();
        taskService.complete(task.getId());
    }
}

每次完成任务后,查看数据库中的运行时变量表的变化。可以观察到局部变量在任务完成后被删除存入了历史变量表。随后再进行任务流转。
在这里插入图片描述在完成上级领导审批节点后,观察ACT_RU_TASK表,也可以看到节点流转到了财务审批。说明这里使用的是全局变量进行判断。局部变量已经在上一任务完成时被删除。
在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Flowable动态任务分配是指根据不同的业务规则或条件,在运行时动态地分配任务给不同的用户或角色。通过集成Flowable,我们可以与系统的用户角色进行绑定,并非常方便地设置任务的办理人与办理角色。这样可以根据具体的需求,灵活地决定任务的分配方式。 在使用Flowable进行动态任务分配时,可以使用以下方法: 1. 完成流程实例:通过任务服务(TaskService)的complete方法,可以完成当前任务,并自动触发下一个任务的创建与分配。可以根据具体的业务逻辑来决定任务的完成条件和下一个任务的办理人或角色。 2. 部署流程:使用Flowable流程引擎(ProcessEngine)提供的部署方法,可以将定义好的流程模型部署到Flowable引擎中,以便后续启动流程实例。 3. 启动流程:通过运行时服务(RuntimeService)的startProcessInstanceByKey方法,可以启动一个流程实例,并指定流程定义的关键字。在启动流程时,可以设置发起人的身份信息,以便在后续任务分配中进行参考。 4. 查询任务:通过任务服务的createTaskQuery方法可以查询符合条件的任务列表,可以根据流程定义的关键字、任务名称等条件进行过滤。查询到的任务列表中包含任务的ID、名称、办理人等信息,可以用于后续的任务处理。 使用Flowable的动态任务分配功能,可以根据具体的业务需求,灵活地设置任务的办理人与办理角色。这样可以提高任务分配的灵活性和效率,使流程执行更加符合实际情况。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [开源OA协同办公系统,集成Flowable流程引擎 可拖拽创建个性表单](https://download.csdn.net/download/weixin_36643308/88202749)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Flowable进阶学习任务分配流程变量](https://blog.csdn.net/qq_40366738/article/details/128746821)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Huathy-雨落江南,浮生若梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值