java 工作流引擎设计实现解析流程定义文件

2023-05-30 0 4,991

目录

引言

在上一篇我们手动构建了一个流程对象简单打印执行,其构建流程对象的方式并不是很友好。为了更方便的构建流程对象,我们采用全新的方式,即解析基础篇提到的流程定义文件,并将其转成流程模型。 以下是要解析的样例文件:

java 工作流引擎设计实现解析流程定义文件

src/test/resources/leave.json

{
  \"name\": \"leave\",
  \"displayName\": \"请假\",
  \"instanceUrl\": \"leaveForm\",
  \"nodes\": [
    {
      \"id\": \"start\",
      \"type\": \"snaker:start\",
      \"x\": 340,
      \"y\": 160,
      \"properties\": {
        \"width\": \"120\",
        \"height\": \"80\"
      },
      \"text\": {
        \"x\": 340,
        \"y\": 200,
        \"value\": \"开始\"
      }
    },
    {
      \"id\": \"apply\",
      \"type\": \"snaker:task\",
      \"x\": 520,
      \"y\": 160,
      \"properties\": {
        \"assignee\": \"approve.operator\",
        \"taskType\": \"Major\",
        \"performType\": \"ANY\",
        \"autoExecute\": \"N\",
        \"width\": \"120\",
        \"height\": \"80\",
        \"field\": {
          \"userKey\": \"1\"
        }
      },
      \"text\": {
        \"x\": 520,
        \"y\": 160,
        \"value\": \"请假申请\"
      }
    },
    {
      \"id\": \"approveDept\",
      \"type\": \"snaker:task\",
      \"x\": 740,
      \"y\": 160,
      \"properties\": {
        \"assignmentHandler\": \"com.mldong.config.FlowAssignmentHandler\",
        \"taskType\": \"Major\",
        \"performType\": \"ANY\",
        \"autoExecute\": \"N\",
        \"width\": \"120\",
        \"height\": \"80\"
      },
      \"text\": {
        \"x\": 740,
        \"y\": 160,
        \"value\": \"部门领导审批\"
      }
    },
    {
      \"id\": \"end\",
      \"type\": \"snaker:end\",
      \"x\": 980,
      \"y\": 160,
      \"properties\": {
        \"width\": \"120\",
        \"height\": \"80\"
      },
      \"text\": {
        \"x\": 980,
        \"y\": 200,
        \"value\": \"结束\"
      }
    }
  ],
  \"edges\": [
    {
      \"id\": \"t1\",
      \"type\": \"snaker:transition\",
      \"sourceNodeId\": \"start\",
      \"targetNodeId\": \"apply\",
      \"startPoint\": {
        \"x\": 358,
        \"y\": 160
      },
      \"endPoint\": {
        \"x\": 460,
        \"y\": 160
      },
      \"properties\": {
        \"height\": 80,
        \"width\": 120
      },
      \"pointsList\": [
        {
          \"x\": 358,
          \"y\": 160
        },
        {
          \"x\": 460,
          \"y\": 160
        }
      ]
    },
    {
      \"id\": \"t2\",
      \"type\": \"snaker:transition\",
      \"sourceNodeId\": \"apply\",
      \"targetNodeId\": \"approveDept\",
      \"startPoint\": {
        \"x\": 580,
        \"y\": 160
      },
      \"endPoint\": {
        \"x\": 680,
        \"y\": 160
      },
      \"properties\": {
        \"height\": 80,
        \"width\": 120
      },
      \"pointsList\": [
        {
          \"x\": 580,
          \"y\": 160
        },
        {
          \"x\": 680,
          \"y\": 160
        }
      ]
    },
    {
      \"id\": \"t3\",
      \"type\": \"snaker:transition\",
      \"sourceNodeId\": \"approveDept\",
      \"targetNodeId\": \"end\",
      \"startPoint\": {
        \"x\": 800,
        \"y\": 160
      },
      \"endPoint\": {
        \"x\": 962,
        \"y\": 160
      },
      \"properties\": {
        \"height\": 80,
        \"width\": 120
      },
      \"pointsList\": [
        {
          \"x\": 800,
          \"y\": 160
        },
        {
          \"x\": 830,
          \"y\": 160
        },
        {
          \"x\": 830,
          \"y\": 160
        },
        {
          \"x\": 932,
          \"y\": 160
        },
        {
          \"x\": 932,
          \"y\": 160
        },
        {
          \"x\": 962,
          \"y\": 160
        }
      ]
    }
  ]
}

类图

java 工作流引擎设计实现解析流程定义文件

流程图

java 工作流引擎设计实现解析流程定义文件

代码实现

model/logicflow/LfPoint.java

package com.mldong.flow.engine.model.logicflow;
import lombok.Data;
import java.io.Serializable;
/**
 *
 * logicFlow坐标
 * @author mldong
 * @date 2023/4/26
 */
@Data
public class LfPoint implements Serializable {
    private int x; // x轴坐标
    private int y; // y轴坐标
}

LogicFlow模型对象

model/logicflow/LfNode.java

package com.mldong.flow.engine.model.logicflow;
import cn.hutool.core.lang.Dict;
import lombok.Data;
import java.io.Serializable;
/**
 *
 * logicFlow节点
 * @author mldong
 * @date 2023/4/26
 */
@Data
public class LfNode implements Serializable {
    private String id; // 节点唯一id
    private String type; // 节点类型
    private int x; // 节点中心点x轴坐标
    private int y; // 节点中心点y轴坐标
    Dict properties; // 节点属性
    Dict text; // 节点文本
}

model/logicflow/LfEdge.java

package com.mldong.flow.engine.model.logicflow;
import cn.hutool.core.lang.Dict;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 *
 * LogicFlow边
 * @author mldong
 * @date 2022/6/12
 */
@Data
public class LfEdge implements Serializable {
    private String id; // 边唯一id
    private String type; // 边类型
    private String sourceNodeId; // 源节点id
    private String targetNodeId; // 目标节点id
    private Dict properties; // 边属性
    private Dict text; // 边文本
    private LfPoint startPoint; // 边开始点坐标
    private LfPoint endPoint; // 边结束点坐标
    private List<LfPoint> pointsList; // 边所有点集合
}

model/logicflow/LfModel.java

package com.mldong.flow.engine.model.logicflow;
import com.mldong.flow.engine.model.BaseModel;
import lombok.Data;
import java.util.List;
/**
 *
 * logicFlow模型
 * @author mldong
 * @date 2023/4/26
 */
@Data
public class LfModel extends BaseModel {
    private String type; // 流程定义分类
    private String expireTime;// 过期时间(常量或变量)
    private String instanceUrl; // 启动实例的url,前后端分离后,定义为路由名或或路由地址
    private String instanceNoClass; // 启动流程时,流程实例的流水号生成类
    private List<LfNode> nodes; // 节点集合
    private List<LfEdge> edges; // 边集合
}

解析类

parser/NodeParser.java

package com.mldong.flow.engine.parser;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.logicflow.LfEdge;
import com.mldong.flow.engine.model.logicflow.LfNode;
import java.util.List;
/**
 *
 * 节点解析接口
 * @author mldong
 * @date 2023/4/26
 */
public interface NodeParser {
    String NODE_NAME_PREFIX=\"snaker:\"; // 节点名称前辍
    String TEXT_VALUE_KEY = \"value\"; // 文本值
    String WIDTH_KEY = \"width\"; // 节点宽度
    String HEIGHT_KEY = \"height\"; // 节点高度
    String PRE_INTERCEPTORS_KEY = \"preInterceptors\"; // 前置拦截器
    String POST_INTERCEPTORS_KEY = \"postInterceptors\"; // 后置拦截器
    String EXPR_KEY = \"expr\"; // 表达式key
    String HANDLE_CLASS_KEY = \"handleClass\"; // 表达式处理类
    String FORM_KEY = \"form\"; // 表单标识
    String ASSIGNEE_KEY = \"assignee\"; // 参与人
    String ASSIGNMENT_HANDLE_KEY = \"assignmentHandler\"; // 参与人处理类
    String TASK_TYPE_KEY = \"taskType\"; // 任务类型(主办/协办)
    String PERFORM_TYPE_KEY = \"performType\"; // 参与类型(普通参与/会签参与)
    String REMINDER_TIME_KEY = \"reminderTime\"; // 提醒时间
    String REMINDER_REPEAT_KEY = \"reminderRepeat\"; // 重复提醒间隔
    String EXPIRE_TIME_KEY = \"expireTime\"; // 期待任务完成时间变量key
    String AUTH_EXECUTE_KEY = \"autoExecute\"; // 到期是否自动执行Y/N
    String CALLBACK_KEY = \"callback\"; // 自动执行回调类
    String EXT_FIELD_KEY = \"field\"; // 自定义扩展属性
    /**
     * 节点属性解析方法,由解析类完成解析
     * @param lfNode LogicFlow节点对象
     * @param edges 所有边对象
     */
    void parse(LfNode lfNode, List<LfEdge> edges);
    /**
     * 解析完成后,提供返回NodeModel对象
     * @return 节点模型
     */
    NodeModel getModel();
}

parser/AbstractNodeParser.java

package com.mldong.flow.engine.parser;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.TransitionModel;
import com.mldong.flow.engine.model.logicflow.LfEdge;
import com.mldong.flow.engine.model.logicflow.LfNode;
import java.util.List;
import java.util.stream.Collectors;
/**
 *
 * 通用属性解析(基本属性和边)
 * @author mldong
 * @date 2023/4/26
 */
public abstract class AbstractNodeParser implements NodeParser {
    // 节点模型对象
    protected NodeModel nodeModel;
    @Override
    public void parse(LfNode lfNode, List&lt;LfEdge&gt; edges) {
        nodeModel = newModel();
        // 解析基本信息
        nodeModel.setName(lfNode.getId());
        if(ObjectUtil.isNotNull(lfNode.getText())) {
            nodeModel.setDisplayName(lfNode.getText().getStr(TEXT_VALUE_KEY));
        }
        Dict properties = lfNode.getProperties();
        // 解析布局属性
        int x = lfNode.getX();
        int y = lfNode.getY();
        int w = Convert.toInt(properties.get(WIDTH_KEY),0);
        int h = Convert.toInt(properties.get(HEIGHT_KEY),0);
        nodeModel.setLayout(StrUtil.format(\"{},{},{},{}\",x,y,w,h));
        // 解析拦截器
        nodeModel.setPreInterceptors(properties.getStr(PRE_INTERCEPTORS_KEY));
        nodeModel.setPostInterceptors(properties.getStr(POST_INTERCEPTORS_KEY));
        // 解析输出边
        List&lt;LfEdge&gt; nodeEdges = getEdgeBySourceNodeId(lfNode.getId(), edges);
        nodeEdges.forEach(edge-&gt;{
            TransitionModel transitionModel = new TransitionModel();
            transitionModel.setName(edge.getId());
            transitionModel.setTo(edge.getTargetNodeId());
            transitionModel.setSource(nodeModel);
            transitionModel.setExpr(edge.getProperties().getStr(EXPR_KEY));
            if(CollectionUtil.isNotEmpty(edge.getPointsList())) {
                // x1,y1;x2,y2;x3,y3……
                transitionModel.setG(edge.getPointsList().stream().map(point-&gt;{
                    return point.getX()+\",\"+point.getY();
                }).collect(Collectors.joining(\";\")));
            } else {
                if(ObjectUtil.isNotNull(edge.getStartPoint()) &amp;&amp; ObjectUtil.isNotNull(edge.getEndPoint())) {
                    int startPointX = edge.getStartPoint().getX();
                    int startPointY = edge.getStartPoint().getY();
                    int endPointX = edge.getEndPoint().getX();
                    int endPointY = edge.getEndPoint().getY();
                    transitionModel.setG(StrUtil.format(\"{},{};{},{}\", startPointX, startPointY, endPointX, endPointY));
                }
            }
            nodeModel.getOutputs().add(transitionModel);
        });
        // 调用子类特定解析方法
        parseNode(lfNode);
    }
    /**
     * 子类实现此类完成特定解析
     * @param lfNode
     */
    public abstract void parseNode(LfNode lfNode);
    /**
     * 由子类各自创建节点模型对象
     * @return
     */
    public abstract NodeModel newModel();
    @Override
    public NodeModel getModel() {
        return nodeModel;
    }
    /**
     * 获取节点输入
     * @param targetNodeId 目标节点id
     * @param edges
     * @return
     */
    private List&lt;LfEdge&gt; getEdgeByTargetNodeId(String targetNodeId,List&lt;LfEdge&gt; edges) {
        return edges.stream().filter(edge-&gt;{
            return edge.getTargetNodeId().equals(targetNodeId);
        }).collect(Collectors.toList());
    }
    /**
     * 获取节点输出
     * @param sourceNodeId 源节点id
     * @param edges
     * @return
     */
    private List&lt;LfEdge&gt; getEdgeBySourceNodeId(String sourceNodeId,List&lt;LfEdge&gt; edges) {
        return edges.stream().filter(edge-&gt;{
            return edge.getSourceNodeId().equals(sourceNodeId);
        }).collect(Collectors.toList());
    }
}

parser/impl/StartParser.java

package com.mldong.flow.engine.parser.impl;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.StartModel;
import com.mldong.flow.engine.model.logicflow.LfNode;
import com.mldong.flow.engine.parser.AbstractNodeParser;
/**
 *
 * 开始节点解析类
 * @author mldong
 * @date 2023/4/26
 */
public class StartParser extends AbstractNodeParser {
    @Override
    public void parseNode(LfNode lfNode) {
    }
    @Override
    public NodeModel newModel() {
        return new StartModel();
    }
}

parser/impl/EndParser.java

package com.mldong.flow.engine.parser.impl;
import com.mldong.flow.engine.model.EndModel;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.logicflow.LfNode;
import com.mldong.flow.engine.parser.AbstractNodeParser;
/**
 *
 * 结束节点解析类
 * @author mldong
 * @date 2023/4/26
 */
public class EndParser extends AbstractNodeParser {
    @Override
    public void parseNode(LfNode lfNode) {
    }
    @Override
    public NodeModel newModel() {
        return new EndModel();
    }
}

parser/impl/TaskParser.java

package com.mldong.flow.engine.parser.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import com.mldong.flow.engine.enums.TaskPerformTypeEnum;
import com.mldong.flow.engine.enums.TaskTypeEnum;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.TaskModel;
import com.mldong.flow.engine.model.logicflow.LfNode;
import com.mldong.flow.engine.parser.AbstractNodeParser;
/**
 *
 * 任务节点解析类
 * @author mldong
 * @date 2023/4/26
 */
public class TaskParser extends AbstractNodeParser {
    /**
     * 解析task节点特有属性
     * @param lfNode
     */
    @Override
    public void parseNode(LfNode lfNode) {
        TaskModel taskModel = (TaskModel)nodeModel;
        Dict properties = lfNode.getProperties();
        taskModel.setForm(properties.getStr(FORM_KEY));
        taskModel.setAssignee(properties.getStr(ASSIGNEE_KEY));
        taskModel.setAssignmentHandler(properties.getStr(ASSIGNMENT_HANDLE_KEY));
        taskModel.setTaskType(TaskTypeEnum.codeOf(properties.getInt(TASK_TYPE_KEY)));
        taskModel.setPerformType(TaskPerformTypeEnum.codeOf(properties.getInt(PERFORM_TYPE_KEY)));
        taskModel.setReminderTime(properties.getStr(REMINDER_TIME_KEY));
        taskModel.setReminderRepeat(properties.getStr(REMINDER_REPEAT_KEY));
        taskModel.setExpireTime(properties.getStr(EXPIRE_TIME_KEY));
        taskModel.setAutoExecute(properties.getStr(AUTH_EXECUTE_KEY));
        taskModel.setCallback(properties.getStr(CALLBACK_KEY));
        // 自定义扩展属性
        Object field = properties.get(EXT_FIELD_KEY);
        if(field!=null) {
            taskModel.setExt(Convert.convert(Dict.class, field));
        }
    }
    @Override
    public NodeModel newModel() {
        return new TaskModel();
    }
}

parser/impl/ForkParser.java

package com.mldong.flow.engine.parser.impl;
import com.mldong.flow.engine.model.ForkModel;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.logicflow.LfNode;
import com.mldong.flow.engine.parser.AbstractNodeParser;
/**
 *
 * 分支节点解析类
 * @author mldong
 * @date 2023/4/26
 */
public class ForkParser extends AbstractNodeParser {
    @Override
    public void parseNode(LfNode lfNode) {
    }
    @Override
    public NodeModel newModel() {
        return new ForkModel();
    }
}

parser/impl/JoinParser.java

package com.mldong.flow.engine.parser.impl;
import com.mldong.flow.engine.model.JoinModel;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.logicflow.LfNode;
import com.mldong.flow.engine.parser.AbstractNodeParser;
/**
 *
 * 合并节点解析器
 * @author mldong
 * @date 2023/4/26
 */
public class JoinParser extends AbstractNodeParser {
    @Override
    public void parseNode(LfNode lfNode) {
    }
    @Override
    public NodeModel newModel() {
        return new JoinModel();
    }
}

parser/impl/DecisionParser.java

package com.mldong.flow.engine.parser.impl;
import cn.hutool.core.lang.Dict;
import com.mldong.flow.engine.model.DecisionModel;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.logicflow.LfNode;
import com.mldong.flow.engine.parser.AbstractNodeParser;
/**
 *
 * 决策节点解析类
 * @author mldong
 * @date 2023/4/26
 */
public class DecisionParser extends AbstractNodeParser {
    /**
     * 解析decision节点特有属性
     * @param lfNode
     */
    @Override
    public void parseNode(LfNode lfNode) {
        DecisionModel decisionModel = (DecisionModel) nodeModel;
        Dict properties = lfNode.getProperties();
        decisionModel.setExpr(properties.getStr(EXPR_KEY));
        decisionModel.setHandleClass(properties.getStr(HANDLE_CLASS_KEY));
    }
    @Override
    public NodeModel newModel() {
        return new DecisionModel();
    }
}

服务上下文相关类

Context.java

package com.mldong.flow.engine;
import java.util.List;
/**
 *
 * 服务上下文接口,类似spring的ioc
 * @author mldong
 * @date 2023/4/26
 */
public interface Context {
    /**
     * 根据服务名称、实例向服务工厂注册
     * @param name 服务名称
     * @param object 服务实例
     */
    void put(String name, Object object);
    /**
     * 根据服务名称、类型向服务工厂注册
     * @param name 服务名称
     * @param clazz 类型
     */
    void put(String name, Class&lt;?&gt; clazz);
    /**
     * 判断是否存在给定的服务名称
     * @param name 服务名称
     * @return
     */
    boolean exist(String name);
    /**
     * 根据给定的类型查找服务实例
     * @param clazz 类型
     * @return
     */
    &lt;T&gt; T find(Class&lt;T&gt; clazz);
    /**
     * 根据给定的类型查找所有此类型的服务实例
     * @param clazz 类型
     * @return
     */
    &lt;T&gt; List&lt;T&gt; findList(Class&lt;T&gt; clazz);
    /**
     * 根据给定的服务名称、类型查找服务实例
     * @param name 服务名称
     * @param clazz 类型
     * @return
     */
    &lt;T&gt; T findByName(String name, Class&lt;T&gt; clazz);
}

impl/SimpleContext.java

package com.mldong.flow.engine.impl;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.mldong.flow.engine.Context;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 *
 * 简单的上下文发现实现类
 * @author mldong
 * @date 2023/4/26
 */
public class SimpleContext implements Context {
    private Dict dict = Dict.create();
    @Override
    public void put(String name, Object object) {
        dict.put(name, object);
    }
    @Override
    public void put(String name, Class&lt;?&gt; clazz) {
        dict.put(name, ReflectUtil.newInstance(clazz));
    }
    @Override
    public boolean exist(String name) {
        return ObjectUtil.isNotNull(dict.getObj(name));
    }
    @Override
    public &lt;T&gt; T find(Class&lt;T&gt; clazz) {
        for (Map.Entry&lt;String, Object&gt; entry : dict.entrySet()) {
            if (clazz.isInstance(entry.getValue())) {
                return clazz.cast(entry.getValue());
            }
        }
        return null;
    }
    @Override
    public &lt;T&gt; List&lt;T&gt; findList(Class&lt;T&gt; clazz) {
        List&lt;T&gt; res = new ArrayList&lt;&gt;();
        for (Map.Entry&lt;String, Object&gt; entry : dict.entrySet()) {
            if (clazz.isInstance(entry.getValue())) {
                res.add(clazz.cast(entry.getValue()));
            }
        }
        return res;
    }
    @Override
    public &lt;T&gt; T findByName(String name, Class&lt;T&gt; clazz) {
        for (Map.Entry&lt;String, Object&gt; entry : dict.entrySet()) {
            if (entry.getKey().equals(name) &amp;&amp; clazz.isInstance(entry.getValue())) {
                return clazz.cast(entry.getValue());
            }
        }
        return null;
    }
}

core/ServiceContext.java

package com.mldong.flow.engine.core;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ReflectUtil;
import com.mldong.flow.engine.Context;
import java.util.List;
/**
 *
 * 单例服务上下文
 * @author mldong
 * @date 2022/6/12
 */
public class ServiceContext {
    private static Context context;
    public static void setContext(Context context) {
        ServiceContext.context = context;
    }
    public static void put(String name, Object object) {
        Assert.notNull(context,\"未注册服务上下文\");
        context.put(name, object);
    }
    public static void put(String name, Class&lt;?&gt; clazz) {
        Assert.notNull(context,\"未注册服务上下文\");
        context.put(name, ReflectUtil.newInstance(clazz));
    }
    public static boolean exist(String name) {
        Assert.notNull(context,\"未注册服务上下文\");
        return context.exist(name);
    }
    public static &lt;T&gt; T find(Class&lt;T&gt; clazz) {
        Assert.notNull(context,\"未注册服务上下文\");
        return context.find(clazz);
    }
    public static &lt;T&gt; List&lt;T&gt; findList(Class&lt;T&gt; clazz) {
        Assert.notNull(context,\"未注册服务上下文\");
        return context.findList(clazz);
    }
    public static &lt;T&gt; T findByName(String name, Class&lt;T&gt; clazz) {
        Assert.notNull(context,\"未注册服务上下文\");
        return context.findByName(name, clazz);
    }
}

解析入口

parser/ModelParser.java

package com.mldong.flow.engine.parser;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONUtil;
import com.mldong.flow.engine.core.ServiceContext;
import com.mldong.flow.engine.model.NodeModel;
import com.mldong.flow.engine.model.ProcessModel;
import com.mldong.flow.engine.model.TaskModel;
import com.mldong.flow.engine.model.TransitionModel;
import com.mldong.flow.engine.model.logicflow.LfEdge;
import com.mldong.flow.engine.model.logicflow.LfModel;
import com.mldong.flow.engine.model.logicflow.LfNode;
import java.io.ByteArrayInputStream;
import java.util.List;
public class ModelParser {
    private ModelParser(){}
    /**
     * 将json定义文件解析成流程模型对象
     * @param bytes
     * @return
     */
    public static ProcessModel parse(byte [] bytes) {
        String json = IoUtil.readUtf8(new ByteArrayInputStream(bytes));
        LfModel lfModel = JSONUtil.parse(json).toBean(LfModel.class);
        ProcessModel processModel = new ProcessModel();
        List<LfNode> nodes = lfModel.getNodes();
        List<LfEdge> edges = lfModel.getEdges();
        if(CollectionUtil.isEmpty(nodes) || CollectionUtil.isEmpty(edges) )  {
            return processModel;
        }
        // 流程定义基本信息
        processModel.setName(lfModel.getName());
        processModel.setDisplayName(lfModel.getDisplayName());
        processModel.setType(lfModel.getType());
        processModel.setInstanceUrl(lfModel.getInstanceUrl());
        processModel.setInstanceNoClass(lfModel.getInstanceNoClass());
        // 流程节点信息
        nodes.forEach(node->{
            String type = node.getType().replace(NodeParser.NODE_NAME_PREFIX,\"\");
            NodeParser nodeParser = ServiceContext.findByName(type,NodeParser.class);
            if(nodeParser!=null) {
                nodeParser.parse(node, edges);
                NodeModel nodeModel = nodeParser.getModel();
                processModel.getNodes().add(nodeParser.getModel());
                if (nodeModel instanceof TaskModel) {
                    processModel.getTasks().add((TaskModel) nodeModel);
                }
            }
        });
        // 循环节点模型,构造输入边、输出边的source、target
        for(NodeModel node : processModel.getNodes()) {
            for(TransitionModel transition : node.getOutputs()) {
                String to = transition.getTo();
                for(NodeModel node2 : processModel.getNodes()) {
                    if(to.equalsIgnoreCase(node2.getName())) {
                        node2.getInputs().add(transition);
                        transition.setTarget(node2);
                    }
                }
            }
        }
        return processModel;
    }
}

配置类

cfg/Configuration.java

package com.mldong.flow.engine.cfg;
import com.mldong.flow.engine.Context;
import com.mldong.flow.engine.core.ServiceContext;
import com.mldong.flow.engine.impl.SimpleContext;
import com.mldong.flow.engine.parser.impl.*;
public class Configuration {
    public Configuration() {
        this(new SimpleContext());
    }
    public Configuration(Context context) {
        ServiceContext.setContext(context);
        ServiceContext.put(\"decision\", DecisionParser.class);
        ServiceContext.put(\"end\", EndParser.class);
        ServiceContext.put(\"fork\", ForkParser.class);
        ServiceContext.put(\"join\", JoinParser.class);
        ServiceContext.put(\"start\", StartParser.class);
        ServiceContext.put(\"task\", TaskParser.class);
    }
}

单元测试

ModelParserTest.java

package com.mldong.flow;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Dict;
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/4/26
 */
public class ModelParserTest {
    @Test
    public void parseTest() {
        new Configuration();
        ProcessModel processModel = ModelParser.parse(IoUtil.readBytes(this.getClass().getResourceAsStream(\"/leave.json\")));
        Execution execution = new Execution();
        execution.setArgs(Dict.create());
        processModel.getStart().execute(execution);
    }
}

运行结果

model:StartModel,name:start,displayName:开始,time:2023-04-26 21:32:40
model:TaskModel,name:apply,displayName:请假申请,time:2023-04-26 21:32:41
model:TaskModel,name:approveDept,displayName:部门领导审批,time:2023-04-26 21:32:42
model:EndModel,name:end,displayName:结束,time:2023-04-26 21:32:42

相关源码 mldong-flow-demo-03

流程设计器 在线体验

以上就是java 工作流引擎设计实现解析流程定义文件的详细内容,更多关于java 工作流引擎的资料请关注其它相关文章!

资源下载此资源下载价格为1小猪币,终身VIP免费,请先
由于本站资源来源于互联网,以研究交流为目的,所有仅供大家参考、学习,不存在任何商业目的与商业用途,如资源存在BUG以及其他任何问题,请自行解决,本站不提供技术服务! 由于资源为虚拟可复制性,下载后不予退积分和退款,谢谢您的支持!如遇到失效或错误的下载链接请联系客服QQ:442469558

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 java 工作流引擎设计实现解析流程定义文件 http://www.20zxx.cn/763390/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务