前面讲到的条件流程履行是经过调整决策节点的履行逻辑来完结的,那分支与兼并流程呢?咱们又应该怎么去处理其履行逻辑呢?下面咱们来看一条存在有分支与兼并的简单流程。如下图: 请假请求->部分领导批阅(多领导并行)->公司领导批阅
流程界说
src/test/resources/leave_06.json
注:以下json并非悉数,短少位置信息。
{
"name": "leave",
"displayName": "请假",
"instanceUrl": "leaveForm",
"nodes": [
{
"id": "start",
"type": "snaker:start",
"properties": {
"width": "120",
"height": "80"
},
"text": {
"value": "开端"
}
},
{
"id": "apply",
"type": "snaker:task",
"properties": {
"assignee": "approve.operator",
"taskType": "Major",
"performType": "ANY",
"autoExecute": "N",
"width": "120",
"height": "80",
"field": {
"userKey": "1"
}
},
"text": {
"value": "请假请求"
}
},
{
"id": "approveDept_a1",
"type": "snaker:task",
"properties": {
"assignmentHandler": "com.mldong.config.FlowAssignmentHandler",
"taskType": "Major",
"performType": "ANY",
"autoExecute": "N",
"width": 120,
"height": 80,
"field": {}
},
"text": {
"value": "部分领导批阅A1"
}
},
{
"id": "approveBoss",
"type": "snaker:task",
"x": 1400,
"y": 340,
"properties": {
"assignmentHandler": "com.mldong.config.FlowAssignmentHandler",
"taskType": "Major",
"performType": "ANY",
"autoExecute": "N",
"width": "120",
"height": "80"
},
"text": {
"value": "公司领导批阅"
}
},
{
"id": "end",
"type": "snaker:end",
"properties": {
"width": "120",
"height": "80"
},
"text": {
"value": "完毕"
}
},
{
"id": "be5429b2-b9f6-4ae7-ae3c-dbc2c4dae947",
"type": "snaker:fork",
"properties": {}
},
{
"id": "approveDept_a2",
"type": "snaker:task",
"properties": {
"height": 80,
"width": 120,
"field": {}
},
"text": {
"value": "部分领导批阅A2"
}
},
{
"id": "approveDept_b1",
"type": "snaker:task",
"x": 1020,
"y": 160,
"properties": {
"height": 80,
"width": 120,
"field": {},
"taskType": "Major",
"performType": "ANY"
},
"text": {
"value": "部分领导批阅B1"
}
},
{
"id": "approveDept_b2",
"type": "snaker:task",
"x": 1020,
"y": 500,
"properties": {
"height": 80,
"width": 120,
"field": {}
},
"text": {
"value": "部分领导批阅B2"
}
},
{
"id": "a4fccb9c-0146-4b20-929f-fed681a37173",
"type": "snaker:join",
"properties": {}
}
],
"edges": [
{
"id": "3037be41-5682-4344-b94a-9faf5c3e62ba",
"type": "snaker:transition",
"sourceNodeId": "start",
"targetNodeId": "apply",
"properties": {}
},
{
"id": "0ea009ea-d48e-4d69-95bf-de64fc0fc84b",
"type": "snaker:transition",
"sourceNodeId": "apply",
"targetNodeId": "be5429b2-b9f6-4ae7-ae3c-dbc2c4dae947",
"properties": {}
},
{
"id": "88854f27-0781-4dd0-8dfa-d44f27550519",
"type": "snaker:transition",
"sourceNodeId": "be5429b2-b9f6-4ae7-ae3c-dbc2c4dae947",
"targetNodeId": "approveDept_a1",
"properties": {}
},
{
"id": "4aa89dd3-90b5-415d-9853-2b25507e7e3f",
"type": "snaker:transition",
"sourceNodeId": "be5429b2-b9f6-4ae7-ae3c-dbc2c4dae947",
"targetNodeId": "approveDept_a2",
"properties": {}
},
{
"id": "7620a4e0-d147-4ca4-a140-a14003c0d9cd",
"type": "snaker:transition",
"sourceNodeId": "approveDept_a1",
"targetNodeId": "approveDept_b1",
"properties": {}
},
{
"id": "4f1b1351-e9fb-42f2-a2a5-e820a71d41c6",
"type": "snaker:transition",
"sourceNodeId": "approveDept_a2",
"targetNodeId": "approveDept_b2",
"properties": {}
},
{
"id": "a1dee2c8-c505-4a8d-abae-c1f0710dd70a",
"type": "snaker:transition",
"sourceNodeId": "approveDept_b1",
"targetNodeId": "a4fccb9c-0146-4b20-929f-fed681a37173",
"properties": {}
},
{
"id": "f132dfe3-fd3a-4c88-b8f7-7c89fba602fe",
"type": "snaker:transition",
"sourceNodeId": "approveDept_b2",
"targetNodeId": "a4fccb9c-0146-4b20-929f-fed681a37173",
"properties": {}
},
{
"id": "11e10610-576b-4965-a16b-23712ddb9d94",
"type": "snaker:transition",
"sourceNodeId": "a4fccb9c-0146-4b20-929f-fed681a37173",
"targetNodeId": "approveBoss",
"properties": {}
},
{
"id": "1575853c-878b-49e6-bfd8-db21c986bd0b",
"type": "snaker:transition",
"sourceNodeId": "approveBoss",
"targetNodeId": "end",
"properties": {}
}
]
}
旧的代码逻辑
JoinModel.java
和ForkModel.java
调用输入变迁办法runOutTransition(...)
package com.mldong.flow.engine.model;
import com.mldong.flow.engine.core.Execution;
/**
*
* 分支模型
* @author mldong
* @date 2023/4/25
*/
public class ForkModel extends NodeModel {
@Override
public void exec(Execution execution) {
// 履行分支节点自界说履行逻辑
runOutTransition(execution);
}
}
package com.mldong.flow.engine.model;
import com.mldong.flow.engine.core.Execution;
import lombok.Data;
/**
*
* 兼并模型
* @author mldong
* @date 2023/4/25
*/
@Data
public class JoinModel extends NodeModel {
@Override
public void exec(Execution execution) {
// 履行兼并节点自界说履行逻辑
runOutTransition(execution);
}
}
修正src/test/java/com/mldong/flow/ExecuteTest.java
办法executeLeave_06,履行逻辑和之前的相同,就是解析的流程界说文件修正为leave_06.json。
- 加载配置
- 解析流程界说文件
- 履行流程
package com.mldong.flow;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Dict;
import com.mldong.flow.engine.MockExecuteTask;
import com.mldong.flow.engine.cfg.Configuration;
import com.mldong.flow.engine.core.Execution;
import com.mldong.flow.engine.model.ProcessModel;
import com.mldong.flow.engine.parser.ModelParser;
import org.junit.Test;
/**
*
* 履行测验
* @author mldong
* @date 2023/5/1
*/
public class ExecuteTest {
@Test
public void executeLeave_06() {
new Configuration();
// 将流程界说文件解析成流程模型
ProcessModel processModel = ModelParser.parse(IoUtil.readBytes(this.getClass().getResourceAsStream("/leave_06.json")));
// 结构履行参数
Execution execution = new Execution();
// 设置当时流程模型
execution.setProcessModel(processModel);
// 设置扩展特点
execution.setArgs(Dict.create());
// 拿到开端节点调用履行办法
processModel.getStart().execute(execution);
// 履行模仿履行使命办法
new MockExecuteTask(execution).run();
}
}
履行成果如下:
调用模型节点履行办法:model:StartModel,name:start,displayName:开端
创立使命:apply,请假请求
设置使命状况为已完结:apply,请假请求
调用模型节点履行办法:model:TaskModel,name:apply,displayName:请假请求
创立使命:approveDept_a1,部分领导批阅A1
创立使命:approveDept_a2,部分领导批阅A2
设置使命状况为已完结:approveDept_a1,部分领导批阅A1
调用模型节点履行办法:model:TaskModel,name:approveDept_a1,displayName:部分领导批阅A1
创立使命:approveDept_b1,部分领导批阅B1
设置使命状况为已完结:approveDept_a2,部分领导批阅A2
调用模型节点履行办法:model:TaskModel,name:approveDept_a2,displayName:部分领导批阅A2
创立使命:approveDept_b2,部分领导批阅B2
设置使命状况为已完结:approveDept_b1,部分领导批阅B1
调用模型节点履行办法:model:TaskModel,name:approveDept_b1,displayName:部分领导批阅B1
创立使命:approveBoss,公司领导批阅
设置使命状况为已完结:approveDept_b2,部分领导批阅B2
调用模型节点履行办法:model:TaskModel,name:approveDept_b2,displayName:部分领导批阅B2
创立使命:approveBoss,公司领导批阅
设置使命状况为已完结:approveBoss,公司领导批阅
调用模型节点履行办法:model:TaskModel,name:approveBoss,displayName:公司领导批阅
调用模型节点履行办法:model:EndModel,name:end,displayName:完毕
设置使命状况为已完结:approveBoss,公司领导批阅
调用模型节点履行办法:model:TaskModel,name:approveBoss,displayName:公司领导批阅
调用模型节点履行办法:model:EndModel,name:end,displayName:完毕
咱们会看到,executeLeave_06的履行也呈现两个公司领导批阅和完毕,由于咱们对分支节点和兼并节点进行处理是默认的处理办法,即直接调用runOutTransition(...)
办法。下面咱们要重新调整节点的处理办法,使其完好且正确的从开端节点走向完毕节点。
分支与兼并节点分析
分支节点
分支节点和开端节点相同,没有什么特别履行过程,只需求调用输出边履行办法,驱动流程往下一个节点履行。
public class ForkModel extends NodeModel {
@Override
public void exec(Execution execution) {
// 履行分支节点自界说履行逻辑
runOutTransition(execution);
}
}
兼并节点
兼并节点需求判别是否到达兼并条件,假如到达兼并条件,则能够继续调用输出边履行办法,驱动流程往下一个节点履行。
履行流程图
履行流程说明
- 是否到达兼并条件,首要判别前面节点产生的使命是否完结
- 假如到达兼并条件,则调用输出边履行办法
- 假如未到达兼并条件,则继续阻塞,不往前进行
如下,咱们能够经过给Execution目标添加是否可兼并特点来判别是否调用输出边履行办法
public class JoinModel extends NodeModel {
@Override
public void exec(Execution execution) {
// 履行兼并节点自界说履行逻辑
if(execution.isMerged()) {
runOutTransition(execution);
}
}
}
当然,仅上面一步仍是不足以完结触发的,由于isMerged永远为false,下面咱们画类图重新安排代码。
类图
尽管判别是否到达兼并条件可直接在JoinModel的exec中完结,可是为了通用性,咱们能够按如下办法来安排代码。即在上文的基础上添加MergeBranchHandler完结类,经过完结类去修正Execution 的isMerged特点。
代码完结
流程履行参数core/Execution.java添加isMerged特点
package com.mldong.flow.engine.core;
import cn.hutool.core.lang.Dict;
import com.mldong.flow.engine.entity.ProcessTask;
import com.mldong.flow.engine.enums.TaskStateEnum;
import com.mldong.flow.engine.model.ProcessModel;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
*
* 履行目标参数
* @author mldong
* @date 2023/4/25
*/
@Data
public class Execution {
// 流程实例ID
private String processInstanceId;
// 当时流程使命ID
private String processTaskId;
// 履行目标扩展参数
private Dict args;
// 当时流程模型
private ProcessModel processModel;
// 当时使命
private ProcessTask processTask;
// 一切使命调集
private List<ProcessTask> processTaskList = new ArrayList<>();
// 是否可兼并
private boolean isMerged;
/**
* 添加使命到使命调集
* @param processTask
*/
public void addTask(ProcessTask processTask) {
this.processTaskList.add(processTask);
}
/**
* 获取正在进行中的使命列表
* @return
*/
public List<ProcessTask> getDoingTaskList() {
return this.processTaskList.stream().filter(item->{
return TaskStateEnum.DOING.getCode().equals(item.getTaskState());
}).collect(Collectors.toList());
}
}
添加兼并分支操作的处理器,handlers/impl/MergeBranchHandler.java
package com.mldong.flow.engine.handlers.impl;
import com.mldong.flow.engine.core.Execution;
import com.mldong.flow.engine.handlers.IHandler;
import com.mldong.flow.engine.model.JoinModel;
/**
* 兼并分支操作的处理器
* @author mldong
* @date 2023/5/21
*/
public class MergeBranchHandler implements IHandler {
private JoinModel joinModel;
public MergeBranchHandler(JoinModel joinModel) {
this.joinModel = joinModel;
}
@Override
public void handle(Execution execution) {
// 判别是否存在正在履行的使命,存在则不答应兼并
execution.setMerged(execution.getDoingTaskList().isEmpty());
}
}
model/JoinModel.java兼并节点类添加调用分支处理类办法fire(new MergeBranchHandler(this),execution)
package com.mldong.flow.engine.model;
import com.mldong.flow.engine.core.Execution;
import com.mldong.flow.engine.handlers.impl.MergeBranchHandler;
import lombok.Data;
/**
*
* 兼并模型
* @author mldong
* @date 2023/4/25
*/
@Data
public class JoinModel extends NodeModel {
@Override
public void exec(Execution execution) {
// 履行兼并节点自界说履行逻辑
fire(new MergeBranchHandler(this),execution);
if(execution.isMerged()) {
runOutTransition(execution);
}
}
}
调用测验类,最终履行成果如下:
调用模型节点履行办法:model:StartModel,name:start,displayName:开端
创立使命:apply,请假请求
设置使命状况为已完结:apply,请假请求
调用模型节点履行办法:model:TaskModel,name:apply,displayName:请假请求
创立使命:approveDept_a1,部分领导批阅A1
创立使命:approveDept_a2,部分领导批阅A2
设置使命状况为已完结:approveDept_a1,部分领导批阅A1
调用模型节点履行办法:model:TaskModel,name:approveDept_a1,displayName:部分领导批阅A1
创立使命:approveDept_b1,部分领导批阅B1
设置使命状况为已完结:approveDept_a2,部分领导批阅A2
调用模型节点履行办法:model:TaskModel,name:approveDept_a2,displayName:部分领导批阅A2
创立使命:approveDept_b2,部分领导批阅B2
设置使命状况为已完结:approveDept_b1,部分领导批阅B1
调用模型节点履行办法:model:TaskModel,name:approveDept_b1,displayName:部分领导批阅B1
设置使命状况为已完结:approveDept_b2,部分领导批阅B2
调用模型节点履行办法:model:TaskModel,name:approveDept_b2,displayName:部分领导批阅B2
创立使命:approveBoss,公司领导批阅
设置使命状况为已完结:approveBoss,公司领导批阅
调用模型节点履行办法:model:TaskModel,name:approveBoss,displayName:公司领导批阅
调用模型节点履行办法:model:EndModel,name:end,displayName:完毕
小结
本文经过调整兼并节点的兼并处理逻辑来完结分支与兼并流程,要害点其实就是判别是否能兼并。从履行成果中咱们能够看出,当咱们完结approveDept_b1节点使命时,其会触发一次兼并处理,此时使命approveDept_b2未完结,所以不能兼并。当履行完approveDept_b2时,会再一次触发兼并处理,此时一切使命都已完结,所以答应兼并,即答应流程往下一个节点跋涉。由于这里仅仅简单模仿,真实的场景approveDept_b1和approveDept_b2是不分先后的,可是这并不影响判别。最终只要是最终一个使命完结,才会真正的触发兼并节兼并动作,答应流程往下一个节点跋涉。
参加安排
请在微信中翻开: 《立东和他的朋友们》
注:最近发现有些CSDN账号将作者的工作流系列文章搬运曩昔然后标为原创(猜想是用程序自动抓取的)。为了添加一些限制,作者决议把该系列文章更新至《立东和他的朋友们》这个圈子上,对此感兴趣的小伙伴能够扫描二维码参加,谢谢我们的支持!
相关源码
mldong-flow-demo-06
流程规划器
在线体验