在绘制流程图时或在流程文件中通过Assignee来指定的方式。
Flowable使用UEL(Unified Expression Language)进行表达式解析。Flowable支持两种UEL表达式:UEL-value和UEL-method。
解析为一个值,默认情况下,所有流程变量都可以使用。所有的SpringBean也可以使用在表达式里。eg:${myVar}
、${myBean.myProperty}
创建流程文件
启动一个流程实例
/**
* 启动流程实例
*/
@Test
public void test2_run_proc() {Map 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 processVariables = processInstance.getProcessVariables();for (String key : processVariables.keySet()) {System.out.println("params => " + key + "~" + processVariables.get(key));}
}
通过查看表数据变动,可以看到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|
完成流程实例
/*** 完成任务*/
@Test
public void test2_complete_proc() {TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processInstanceId("7501").taskAssignee("whx").singleResult();taskService.complete(task.getId());
}
查看数据库ACT_RU_TASK表(可见节点名称与任务指派人已变化)
调用一个方法,可以带参或者不带。当调用无参方法的时候,要确保方法名后面添加空括号(避免与值表达式混淆)。传递的参数可以是字面值,也可以是表达式,会进行自动解析。eg:
${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.do(myvar, execution)}
myBean是spring容器中的一个Bean对象,表示调用bean的addNewOrder方法。
可以使用监听器来完成很多flowable的流程业务。
我们在此处使用监听器来完成负责人的指定,那么我们在流程设计的时候就不需要指定assignee。
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*/@Overridepublic void notify(DelegateTask delegateTask) {System.out.println("==》MyTaskListener监听器触发");System.out.println("delegateTask.getName() = " + delegateTask.getName());// 当满足条件则设置任务分配人为huathy否则为whxif ("提交请假申请".equals(delegateTask.getName()) && "create".equalsIgnoreCase(delegateTask.getEventName())) {delegateTask.setAssignee("huathy");} else {delegateTask.setAssignee("whx");}}
}
@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());
}
流程实例按步骤执行时,需要使用一些数据。在Flowable中,这些数据称作变量(variable),并存储到数据库中。变量可以用在表达式中(例如在排他网关中用于选择正确的出口路径),也可以在Java服务任务(service task)中用于调用外部服务(例如为服务提供输入或结果存储),等等。
咯iu成实例可以持有变量(称作流程变量process variables),用户任务以执行(excutions)——流程当前活动节点的指针——也可以持有变量。流程实例可以持有任意数量的变量,每个变量存储为ACT_RU_VARIABLE数据库表的一行记录。
所有的startProcessInstanceXXX方法都有一个可选参数,用于在流程实例创建及启动时设置变量。eg:在RuntimeService中:
ProcessInstance startProcessInstanceById(String processDefinitionId, Map variables);
也可以在流程执行中加入变量,eg:RuntimeService
void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map variables);
void setVariablesLocal(String executionId, Map variables);
实例关系:通常情况下没有子流程的,流程实例与执行实例一一对应。
流程变量的默认作用域是流程实例。当一个流程变量的作用域为流程实例的时候,可以称为global变量。eg:userId。
global变量中变量名不可重复,设置相同名称的变量,新值会覆盖旧值。
任务和执行实例仅仅是针对要给任务和一个执行实例的范围,范围没有流程实例大,成为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;@Beforepublic void before() {// 通过 ProcessEngineConfiguration 构建我们需要的 ProcessEngineconfiguration = 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();}@Testpublic void test_deploy() {// 2. 获取 RepositoryServiceRepositoryService 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());}@Testpublic void test_run_proc() {RuntimeService runtimeService = processEngine.getRuntimeService();Map 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);}@Testpublic void test_complete_task1() {TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();// 获取当前流程实例的所有变量Map processVariables = task.getProcessVariables();processVariables.put("num", 2);taskService.complete(task.getId(), processVariables);}/*** 根据taskID来更新本地(实例)变量*/@Testpublic void test_update_variables_local() {TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();// 获取当前流程实例的所有变量Map processVariables = task.getProcessVariables();processVariables.put("num", 6);taskService.setVariablesLocal(task.getId(), processVariables);}/*** 根据taskID来更新流程变量*/@Testpublic void test_update_variables() {TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();// 获取当前流程实例的所有变量。当局部变量和全局变量都存在的时候,取出来的是局部变量。Map processVariables = task.getProcessVariables();processVariables.put("num", 5);taskService.setVariables(task.getId(), processVariables);}/*** 完成上级审批*/@Testpublic void test_complete_task2() {TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processInstanceId("2501").singleResult();taskService.complete(task.getId());}
}
每次完成任务后,查看数据库中的运行时变量表的变化。可以观察到局部变量在任务完成后被删除存入了历史变量表。随后再进行任务流转。
在完成上级领导审批节点后,观察ACT_RU_TASK表,也可以看到节点流转到了财务审批。说明这里使用的是全局变量进行判断。局部变量已经在上一任务完成时被删除。