这里写自定义目录标题
- 1、固定分配
- 2、表达式分配
- 在此流程部署了之后,在流程定义信息表中可以看到此流程的相关信息
- 启动流程
- 查看我们设置的变量
- 在task表中,可以看到当前分配人是张三,说明值表达式被解析了
- 完成任务
- 在张三完成任务之后,task表中的分配人变成了李四
- 方法表达式 Method expression:
- 3、监听器分配 -- 本篇重点,动态指定审批人为发起人的部门经理,原理需要结合 dept表#leader_id,获其他辅助表
1、固定分配
在绘制流程图或者直接在流程文件中通过Assignee来指定的方式。直接是写死的。
2、表达式分配
Flowable使用UEL进行表达式解析。UEL代表Unified Expression Language,是EE6规范的一部分(查看EE6规范了解更多信息)。
表达式可以用于Java服务任务(Java Service task)、执行监听器(Execution Listener)、任务监听器(Task Listener) 与 条件顺序流(Conditional sequence flow)等。尽管有值表达式与方法表达式这两种不同的表达式,Flowable通过抽象,使它们都可以在需要表达式的地方使用。
值表达式 Value expression: 解析为一个值。默认情况下,所有流程变量都可以使用。(若使用Spring)所有的Spring bean也可以用在表达式里。例如:
${myVar}
${myBean.myProperty}
myBean是Spring容器中的个Bean对象,表示调用的是bean的addNewOrder方法
首先新建一个值表达式的例子
可视编辑器–>分配用户–>固定值—>${assignee1}
在此流程部署了之后,在流程定义信息表中可以看到此流程的相关信息
启动流程
/*** 启动流程实例*/@Testpublic void TestDeploymentRun() {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();RuntimeService runtimeService = processEngine.getRuntimeService();// 流程变量Map<String, Object> variables = new HashMap<String, Object>();variables.put("assignee0", "张三");variables.put("assignee1", "李四");// 启动流程实例// ProcessInstance processInstance = runtimeService.startProcessInstanceById("holidayRequest:1:37504", variables);ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("MyHolidayUI001", variables);System.out.println("processInstance.getProcessDefinitionId() = " + processInstance.getProcessDefinitionId()); // MyHolidayUI001:1:37504System.out.println("processInstance.getProcessDefinitionKey() = " + processInstance.getProcessDefinitionKey());// MyHolidayUI001System.out.println("processInstance.getActivityId() = " + processInstance.getActivityId());System.out.println("processInstance.getId()" + processInstance.getId());// 40001}
查看我们设置的变量
在task表中,可以看到当前分配人是张三,说明值表达式被解析了
完成任务
/*** 完成任务*/@Testpublic void TestCompleteTask() {ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();TaskService taskService = processEngine.getTaskService();Task task = taskService.createTaskQuery().processInstanceId("40001") //根据流程实例编号查找.taskAssignee("张三").singleResult();taskService.complete(task.getId());}
在张三完成任务之后,task表中的分配人变成了李四
方法表达式 Method expression:
调用一个方法,可以带或不带参数。当调用不带参数的方法时,要确保在方法名后添加空括号(以避免与值表达式混淆)
传递的参数可以是字面值(literal value),也可以是表达式,它们会被自动解析。例如:
${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.doSomething(myVar, execution)}
请注意,表达式支持解析(及比较)原始类型(primitive)、bean、list、array与map。
3、监听器分配 – 本篇重点,动态指定审批人为发起人的部门经理,原理需要结合 dept表#leader_id,获其他辅助表
任务监听器(Task Listener)
我们在此处使用监听器来完成审批人的动态指定,那么我们在流程设计的时候就不需要指定assignee。但是需要指定任务监听器。
创建自定义监听器:
/*** 动态指定部门经理审批监听器** @return* @author wangl* @date 2023-12-15*/
public class DeptLeaderTaskListener implements TaskListener {private static final Logger LOGGER = LoggerFactory.getLogger(DeptLeaderTaskListener.class);/*** 注入字段(名称与流程设计时字段名称一致) 参数 多个的话用分号隔开 实例 userCode:00004737;status:1*/private FixedValue level;private static final long serialVersionUID = 1L;private TaskService taskService = SpringUtils.getBean(TaskService.class);private ISysDeptService flowThirdService = SpringUtils.getBean(ISysDeptService.class);RuntimeService runtimeService = SpringUtils.getBean(RuntimeService.class);@Overridepublic void notify(DelegateTask delegateTask) {String taskId = delegateTask.getId();// 获取流程发起人ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(delegateTask.getProcessInstanceId()).singleResult();String startUserId = processInstance.getStartUserId();// 获取部门负责人列表List<String> depIds = flowThirdService.getLeaderByUserId(Long.valueOf(startUserId));if (CollectionUtil.isEmpty(depIds)) {LOGGER.warn("申请人[{}] 未指定部门领导人", startUserId);return;}int level_int = Integer.parseInt(level.toString());String leaderId = "";for (int i = 0; i < depIds.size(); i++) {if (i == level_int - 1) {leaderId = depIds.get(i);}}Map<String, Object> variables = taskService.getVariables(taskId);delegateTask.setAssignee(leaderId);variables.put("DeptLeaderTaskListener", leaderId);taskService.setVariables(taskId, variables);}}