前言
上文中已经对模型进行了高度的笼统,本文将对模型行为进行进一步阐明。这里以发问的方式开场:
怎么让流程从开端节点按箭头指向走到完毕节点?
StartModel(start)->TaskModel(apply)->TaskModel(deptApprove)->EndModel(end)
履行进程分析
目标图:
时序图:
履行进程阐明:
- 开端节点调用输出边t1的履行办法
- t1输出边调用请假请求节点的履行办法
- 请假节点调用输出边t2的履行办法
- t2输出边调用部分领导批阅的履行办法
- 部分领导批阅调用输出边t3的履行办法
- t3调用完毕节点的履行办法
代码完成进程
节点模型的execute办法添加打印当时目标的编码和称号。
public abstract class NodeModel extends BaseModel implements Action {
private String layout;// 布局属性(x,y,w,h)
// 输入边调集
private List<TransitionModel> inputs = new ArrayList<TransitionModel>();
// 输出边调集
private List<TransitionModel> outputs = new ArrayList<TransitionModel>();
private String preInterceptors; // 节点前置拦截器
private String postInterceptors; // 节点后置拦截器
/**
* 由子类自界说履行办法
* @param execution
*/
abstract void exec(Execution execution);
@Override
public void execute(Execution execution) {
// 1. 调用前置拦截器
// 2. 调用子类的exec办法
// 3. 调用后置拦截器
System.out.println(StrUtil.format("model:{},name:{},displayName:{}", this.getClass().getSimpleName(), getName(),getDisplayName()));
exec(execution);
}
}
流程模型添加获取开端节点办法
public class ProcessModel extends BaseModel {
private String type; // 流程界说分类
private String instanceUrl; // 启动实例要填写的表单key
private String expireTime; // 期待完成时刻变量key
private String instanceNoClass; // 实例编号生成器完成类
// 流程界说的一切节点
private List<NodeModel> nodes = new ArrayList<NodeModel>();
// 流程界说的一切使命节点
private List<TaskModel> tasks = new ArrayList<TaskModel>();
/**
* 获取开端节点
* @return
*/
public StartModel getStart() {
StartModel startModel = null;
for (int i = 0; i < nodes.size(); i++) {
NodeModel nodeModel = nodes.get(i);
if(nodeModel instanceof StartModel) {
startModel = (StartModel) nodeModel;
break;
}
}
return startModel;
}
}
流程模型拿到开端节点目标并调用履行办法
processModel.getStart().execute(new Execution());
此刻只打印开端节点信息
model:StartModel,name:start,displayName:开端
节点模型目标的execute办法添加遍历调用下一个节点履行办法的
public abstract class NodeModel extends BaseModel implements Action {
private String layout;// 布局属性(x,y,w,h)
// 输入边调集
private List<TransitionModel> inputs = new ArrayList<TransitionModel>();
// 输出边调集
private List<TransitionModel> outputs = new ArrayList<TransitionModel>();
private String preInterceptors; // 节点前置拦截器
private String postInterceptors; // 节点后置拦截器
/**
* 由子类自界说履行办法
* @param execution
*/
abstract void exec(Execution execution);
@Override
public void execute(Execution execution) {
// 1. 调用前置拦截器
// 2. 调用子类的exec办法
// 3. 调用后置拦截器
System.out.println(StrUtil.format("model:{},name:{},displayName:{}", this.getClass().getSimpleName(), getName(),getDisplayName()));
outputs.forEach(tr->{
tr.getTarget().execute(execution);
});
exec(execution);
}
}
成果:
model:StartModel,name:start,displayName:开端
model:TaskModel,name:apply,displayName:请假请求
model:TaskModel,name:deptApprove,displayName:部分领导批阅
model:EndModel,name:end,displayName:完毕
为了突显边的作用,咱们能够完成边的履行办法:
public class TransitionModel extends BaseModel implements Action {
private NodeModel source; // 边源节点引证
private NodeModel target; // 边目标节点引证
private String to; // 目标节点称号
private String expr; // 边表达式
private String g; // 边点坐标调集(x1,y1;x2,y2,x3,y3……)开端、拐角、完毕
private boolean enabled; // 是否可履行
@Override
public void execute(Execution execution) {
if(!enabled) return;
target.execute(execution);
}
}
然后改造节点模型添加runOutTransition办法
public abstract class NodeModel extends BaseModel implements Action {
private String layout;// 布局属性(x,y,w,h)
// 输入边调集
private List<TransitionModel> inputs = new ArrayList<TransitionModel>();
// 输出边调集
private List<TransitionModel> outputs = new ArrayList<TransitionModel>();
private String preInterceptors; // 节点前置拦截器
private String postInterceptors; // 节点后置拦截器
/**
* 由子类自界说履行办法
* @param execution
*/
abstract void exec(Execution execution);
@Override
public void execute(Execution execution) {
// 1. 调用前置拦截器
// 2. 调用子类的exec办法
// 3. 调用后置拦截器
System.out.println(StrUtil.format("model:{},name:{},displayName:{}", this.getClass().getSimpleName(), getName(),getDisplayName()));
// 履行输出边
runOutTransition(execution);
exec(execution);
}
/**
* 履行输出边
*/
protected void runOutTransition(Execution execution) {
outputs.forEach(tr->{
tr.setEnabled(true);
tr.execute(execution);
});
}
}
最终作用为:
model:StartModel,name:start,displayName:开端
model:TaskModel,name:apply,displayName:请假请求
model:TaskModel,name:deptApprove,displayName:部分领导批阅
model:EndModel,name:end,displayName:完毕
怎么让流程发生堵塞?
上面的例子履行进程太顺利了,真实的工作流场景会存在一些堵塞使命,发生堵塞的意思是,即调用节点履行办法,如果条件不满足,仍然不能驱动流程往下一个节点进行。那咱们怎么使用程序去模仿这一进程呢?
首要改造节点模型
并不是每个节点的履行方式都一样,咱们需要对不同节点进行不同的输出处理,所以这里
- 暂时去掉原来节点模型的打印句子和调用履行边的办法
- 重写toString()办法
public abstract class NodeModel extends BaseModel implements Action {
private String layout;// 布局属性(x,y,w,h)
// 输入边调集
private List<TransitionModel> inputs = new ArrayList<TransitionModel>();
// 输出边调集
private List<TransitionModel> outputs = new ArrayList<TransitionModel>();
private String preInterceptors; // 节点前置拦截器
private String postInterceptors; // 节点后置拦截器
/**
* 由子类自界说履行办法
* @param execution
*/
abstract void exec(Execution execution);
@Override
public void execute(Execution execution) {
// 1. 调用前置拦截器
// 2. 调用子类的exec办法
// 3. 调用后置拦截器
exec(execution);
}
/**
* 履行输出边
*/
protected void runOutTransition(Execution execution) {
outputs.forEach(tr->{
tr.setEnabled(true);
tr.execute(execution);
});
}
@Override
public String toString() {
return StrUtil.format("model:{},name:{},displayName:{},time:{}", this.getClass().getSimpleName(), getName(),getDisplayName(), DateUtil.dateSecond());
}
}
完成开端节点的exec办法
开端节点的exec首要履行如下逻辑:
- 输出super.toString()
- 调用runOutTransition
public class StartModel extends NodeModel {
@Override
void exec(Execution execution) {
System.out.println(super.toString());
runOutTransition(execution);
}
}
完成完毕节点的exec办法
完毕节点是没有输出边的,所以只输出super.toString()
public class EndModel extends NodeModel {
@Override
public void exec(Execution execution) {
System.out.println(super.toString());
}
}
完成使命节点的exec办法
使命节点的比较特殊,咱们能够做如下处理让其发生临时的堵塞:
public class TaskModel extends NodeModel {
private String form; // 表单标识
private String assignee; // 参与人
private String assignmentHandler; // 参与人处理类
private TaskTypeEnum taskType; // 使命类型(主办/协办)
private TaskPerformTypeEnum performType; // 参与类型(一般参与/会签参与)
private String reminderTime; // 提醒时刻
private String reminderRepeat; // 重复提醒距离
private String expireTime; // 期待使命完成时刻变量key
private String autoExecute; // 到期是否主动履行Y/N
private String callback; // 主动履行回调类
private Dict ext = Dict.create(); // 自界说扩展属性
@Override
public void exec(Execution execution) {
// 履行使命节点自界说履行逻辑
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(super.toString());
runOutTransition(execution);
}
}
此刻打印成果如下:
model:StartModel,name:start,displayName:开端,time:2023-04-25 22:27:45
model:TaskModel,name:apply,displayName:请假请求,time:2023-04-25 22:27:48
model:TaskModel,name:deptApprove,displayName:部分领导批阅,time:2023-04-25 22:27:51
model:EndModel,name:end,displayName:完毕,time:2023-04-25 22:27:51
参加安排
请在微信中打开: 《立东和他的朋友们》
相关源码
mldong-flow-demo-02
流程设计器
在线体验