工作流SDK接口使用说明
1.需求场景 在涉及到工作流相关的业务场景时,业务数据和流程数据最好是要做到相互隔离,互不影响。因此,数据和逻辑之间,耦合度越低越好。工作流引擎作为一个独立的模块,要方便业务数据调用。
2.接口说明 启动一个流程,需要插入业务数据,也需要插入流程数据(包括流程日志、流程任务)。为了方便整合流程,流程引擎提供SDK接口调用。
流程主要有2个接口:启动流程和提交流程,其他的为辅助接口。
所有的接口功能,都封装在FlowUtil类中,提供静态方法调用。
2.1.启动流程 启动流程,只需要调用FlowUtil.startFlowInstance(NoCodeFlowParam flowParam)方法即可,传入NoCodeFlowParam对象参数,返回NoCodeResult对象。方法自动处理流程数据,如果传入了业务数据SQL语句,也会处理业务数据。
NoCodeFlowParam定义如下:
public class NoCodeFlowParam {
private int flowId;
private int dataId;
private int userId;
private int actionType;
//操作类型
private int nodeId;
//当前操作节点
private int backNodeId;
//回退、拒绝、驳回后的节点
private String nextNodeIds;
//下一节点
private String tableName;
//业务数据库表名称
private boolean executeSQL;
//是否执行更新或插入业务数据SQL
private String sqlBusiness;
//业务数据SQL
private Object[] sqlParam;
//业务数据SQL参数
private NoCodeFlowNode flowNode;
//当前流程节点
private NoCodeFlowProcess flowProcess;
//处理日志
private List flowTaskList;
//要发布的任务列表
private int remarkField;
//备注关联字段id
private int attachmentField;
//附件关联字段id
private String flowRemark;
//备注信息
private String flowAttachment;
//相关附件
}
在调用启动流程时,并不需要传入所有参数。参数说明如下:
- flowId。流程Id,必填。当前启动的是哪个流程。引擎会根据该Id值查找配置项。
- dataId。业务数据Id,视情况而定。如果自己单独处理了业务数据(新增业务数据),则需要传递dataId,以便引擎更新该业务数据的流程状态。如果需要引擎处理业务数据,则不需要传值。
- userId。当前操作的用户id,必填。一般从session中取值,获取当前用户Id。如果是APP等无状态接口,则通过接口用户验证取到用户Id值。
- actionType。操作类型,不用填。启动流程时,不需要传值。内部会固定为NoCodeFlowNode.NODE_TYPE_START,其值为1。提交流程时,则根据实际是什么操作,就传递什么值。各种操作类型,在NoCodeFlowNode中有定义。
- nodeId。当前操作的节点Id,不用填。启用流程会固定查找启动节点。
- backNodeId。回退节点,不用填。启动流程时,不会回退。
- nextNodeIds。下一个节点Id列表,不用填。内部会自动获取。
- tableName。业务数据库表名称,必填。引擎需要去更新业务数据的流程启动人、流程节点、流程状态数据。
- executeSQL。是否执行业务数据SQL,必填。设置为true后,引擎会执行业务数据的SQL语句(sqlBusiness和sqlParam)。会自动判断是insert还是update。
- sqlBusiness。业务SQL语句,视情况而定。如果需要引擎执行业务数据,则传递SQL语句给引擎执行。支持insert和update。如果是insert,则会把新增的数据id值,返回到NoCodeResult的data属性中。
- sqlParam。业务SQL语句配套的参数,根据sqlBusiness而定。
- flowNode。当前流程节点,不用填。如果是启动流程,引擎会自动查找开启节点;如果是提交流程,引擎会根据nodeId
- flowProcess。流程日志对象,不用填。引擎会自动构造。
- flowTaskList。流程任务对象列表,不用填。引擎会自动构造。
- remarkField。关联节点的备注字段,不用填。自动根据节点设置项来读取。
- attachmentField。关联节点的附件字段,不用填。自动根据节点设置项来读取。
- flowRemark。备注说明内容,视情况而定。需要存储到流程日志中。如果有,就赋值。
- flowAttachment。相关附件内容,视情况而定。需要存储在流程日志中。如果有,就赋值。
2.2.提交流程 提交流程,调用接口FlowUtil.submitFlowInstance(NoCodeFlowParam flowParam)方法,参数与返回值,类似于启动流程。
要传递的参数,与启动流程的区别如下。
- nodeId。节点Id,必填。当前提交的是哪个流程节点,必填。
- dataId。业务数据Id,必填。提交流程时,必然是有关联的业务数据。
- actionType。操作类型,必填。提交流程时,必然是选择某种操作。
- backNodeId。如果是回退操作类型,还需要传递选择的回退节点Id。
//提交发起流程表单。添加业务表单数据,发起流程。
public NoCodeResult submitFlowStart(HttpSession httpSession, Map mapRequestParam, int flowId) {
if (!baseValidate(httpSession, mapRequestParam, flowId)) {
return mResult;
}//获取发起流程节点字段列表
mListField = FlowService.getFlowStartPageFieldList(flowId);
//将request的数据,存入字段列表
setFieldValueFromRequestForSave();
//验证字段数据
if (!validateFieldValueForSave()) {
return mResult;
}//从session中获取当前用户id
int userId = StringUtil.convertToInt(httpSession.getAttribute(NoCodeUser.SESSION_USERID));
//保存业务数据的SQL和参数
List
3.2.提交流程 提交流程与启动流程类似,只需要多传递几个参数即可。
//确认流程提交。已经创建了流程,进行业务数据更新,以及流程状态更新。
public NoCodeResult submitFlowAction(HttpSession httpSession, Map mapRequestParam, int flowId, int nodeId, int dataId) {
if (!baseValidate(httpSession, mapRequestParam, flowId, dataId)) {
return mResult;
} //获取操作类型
int actionType = StringUtil.convertToInt(StringUtil.convertStringArrayToString(mapRequestParam.get("actionType")));
if (actionType <= 0) {
mResult.setFailureInfo("请选择操作类型");
return mResult;
} int backNodeId = StringUtil.convertToInt(StringUtil.convertStringArrayToString(mapRequestParam.get("backNodeId")));
if (actionType == NoCodeFlowNode.NODE_ACTION_BACK && backNodeId <= 0) {
mResult.setFailureInfo("退回操作未选择回退节点");
return mResult;
} //TODO 需要对当前节点类型进行判断,如果是驳回修改的,那么需要更新原始表单。 //从session中获取当前用户id
int userId = StringUtil.convertToInt(httpSession.getAttribute(NoCodeUser.SESSION_USERID));
//获取当前节点的字段列表
mListField = FlowService.getFlowActionPageFieldList(flowId, nodeId);
if (mListField == null || mListField.size() == 0) {
mResult.setSuccessInfo("无字段需要保存");
return mResult;
}
//将request的数据,存入字段列表
setFieldValueFromRequestForSave();
//验证字段数据
if (!validateFieldValueForSave()) {
return mResult;
} //保存业务数据的SQL和参数
List
3.3.节点定义 对节点进行定义,包含节点类型、状态、操作类型。
public class NoCodeFlowNode {
//region 流程节点类型
public final static int NODE_TYPE_START = 1;
//开始节点
public final static int NODE_TYPE_END = 2;
//结束节点
public final static int NODE_TYPE_SERIAL = 3;
//串行节点
public final static int NODE_TYPE_BRANCH = 4;
//分支节点
public final static int NODE_TYPE_AND_SINGLE = 5;
//并行单审节点
public final static int NODE_TYPE_AND_MULTI = 6;
//并行多审节点
public final static int NODE_TYPE_AND_ALL = 7;
//会签节点
//endregion //region 流程节点操作类型
public static final int NODE_ACTION_SAVE = 0;
//暂存
public static final int NODE_ACTION_SUBMIT = 1;
//提交
public static final int NODE_ACTION_CANCEL = 2;
//撤回
public static final int NODE_ACTION_REJECT = 8;
//驳回修改
public static final int NODE_ACTION_REFUSE = 9;
//审核拒绝
public static final int NODE_ACTION_APPROVE = 10;
//审核通过
public static final int NODE_ACTION_READ = 11;
//阅读
public static final int NODE_ACTION_FORWARD = 12;
//转发
public static final int NODE_ACTION_BACK = 49;
//退回
public static final int NODE_ACTION_FREEZE = 50;
//冻结
public static final int NODE_ACTION_UNFREEZE = 51;
//解冻
public static final int NODE_ACTION_DELETE = 98;
//删除
public static final int NODE_ACTION_ABANDON = 99;
//作废
public static final int NODE_ACTION_FINISH = 100;
//完结
//endregion //region 流程节点状态
public static final int NODE_STATE_NO_SUBMIT = 0;
//未提交
public static final int NODE_STATE_HAS_SUBMIT = 1;
//已提交
public static final int NODE_STATE_CANCEL = 2;
//已撤回
public static final int NODE_STATE_REJECT = 8;
//驳回修改
public static final int NODE_STATE_REFUSE = 9;
//审核拒绝
public static final int NODE_STATE_APPROVE = 10;
//审核通过
public static final int NODE_STATE_READ = 11;
//已阅读
public static final int NODE_STATE_FORWARD = 12;
//已转发
public static final int NODE_STATE_BACK = 49;
//退回
public static final int NODE_STATE_FREEZE = 50;
//已冻结
public static final int NODE_STATE_UNFREEZE = 51;
//已解冻
public static final int NODE_STATE_DELETE = 98;
//已删除
public static final int NODE_STATE_ABANDON = 99;
//已作废
public static final int NODE_STATE_FINISHED = 100;
//已完结
//endregion
}
3.4.获取节点数据 【工作流SDK接口使用说明】辅助类FlowUtil中还封装了其他方法,以便方便的获取流程相关的数据。
主要就是获取流程节点类型、状态、操作类型的描述说明、显示样式颜色等。
public class FlowUtil {
//region 节点状态、类型、动作,值与名称转换
//获取节点值与名称的map表
public static Map getNodeTypeMap() {
Map mapNodeType = new LinkedHashMap<>();
mapNodeType.put(NoCodeFlowNode.NODE_TYPE_START, "开始节点");
mapNodeType.put(NoCodeFlowNode.NODE_TYPE_END, "结束节点");
mapNodeType.put(NoCodeFlowNode.NODE_TYPE_SERIAL, "串行节点");
mapNodeType.put(NoCodeFlowNode.NODE_TYPE_BRANCH, "分支节点");
mapNodeType.put(NoCodeFlowNode.NODE_TYPE_AND_SINGLE, "并行单审节点");
mapNodeType.put(NoCodeFlowNode.NODE_TYPE_AND_MULTI, "并行多审节点");
mapNodeType.put(NoCodeFlowNode.NODE_TYPE_AND_ALL, "会签节点");
return mapNodeType;
} //根据节点类型值,获取节点名称
public static String getNodeTypeName(int nodeType) {
return getNodeTypeMap().get(nodeType);
} //获取流程状态值与名称map表
public static Map getNodeStateMap() {
Map mapNodeState = new LinkedHashMap<>();
mapNodeState.put(NoCodeFlowNode.NODE_STATE_NO_SUBMIT, "未提交");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_HAS_SUBMIT, "已提交");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_APPROVE, "已通过");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_REFUSE, "已拒绝");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_REJECT, "已驳回");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_CANCEL, "已撤回");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_READ, "已阅读");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_FORWARD, "已转发");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_BACK, "已退回");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_FREEZE, "已冻结");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_UNFREEZE, "已解冻");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_DELETE, "已删除");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_ABANDON, "已作废");
mapNodeState.put(NoCodeFlowNode.NODE_STATE_FINISHED, "已完结");
return mapNodeState;
} //根据节点状态值,获取节点状态名称
public static String getNodeStateName(int nodeState) {
return getNodeStateMap().get(nodeState);
} //获取操作类型值与名称map表
public static Map getNodeActionMap() {
Map mapNodeState = new LinkedHashMap<>();
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_SAVE, " 暂存");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_SUBMIT, "提交");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_CANCEL, "撤回");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_APPROVE, "审核通过");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_REFUSE, "审核拒绝");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_REJECT, "驳回修改");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_FORWARD, "转发");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_READ, "阅读");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_BACK, "退回");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_FREEZE, "冻结");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_UNFREEZE, "解冻");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_DELETE, "删除");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_ABANDON, "作废");
mapNodeState.put(NoCodeFlowNode.NODE_ACTION_FINISH, "完结");
return mapNodeState;
} //根据节点操作类型值,获取操作类型名称
public static String getNodeActionName(int nodeAction) {
return getNodeActionMap().get(nodeAction);
} //根据节点动作,获取节点状态
public static int getNodeStateByAction(int nodeAction) {
switch (nodeAction) {
case NoCodeFlowNode.NODE_ACTION_SAVE://暂存
return NoCodeFlowNode.NODE_STATE_NO_SUBMIT;
//未提交
case NoCodeFlowNode.NODE_ACTION_SUBMIT://提交
return NoCodeFlowNode.NODE_STATE_HAS_SUBMIT;
//已提交
case NoCodeFlowNode.NODE_ACTION_CANCEL://撤回
return NoCodeFlowNode.NODE_STATE_CANCEL;
//已撤回
case NoCodeFlowNode.NODE_ACTION_APPROVE://审核通过
return NoCodeFlowNode.NODE_STATE_APPROVE;
//已审核通过
case NoCodeFlowNode.NODE_ACTION_REFUSE://审核拒绝
return NoCodeFlowNode.NODE_STATE_REFUSE;
//已审核拒绝
case NoCodeFlowNode.NODE_ACTION_REJECT://驳回修改
return NoCodeFlowNode.NODE_STATE_REJECT;
//已驳回修改
case NoCodeFlowNode.NODE_ACTION_FORWARD://转发
return NoCodeFlowNode.NODE_STATE_FORWARD;
//已转发
case NoCodeFlowNode.NODE_ACTION_READ://阅读
return NoCodeFlowNode.NODE_STATE_READ;
//已阅读
case NoCodeFlowNode.NODE_ACTION_BACK://退回
return NoCodeFlowNode.NODE_STATE_BACK;
//已退回
case NoCodeFlowNode.NODE_ACTION_FREEZE://冻结
return NoCodeFlowNode.NODE_STATE_FREEZE;
//已冻结
case NoCodeFlowNode.NODE_ACTION_UNFREEZE://解冻
return NoCodeFlowNode.NODE_STATE_UNFREEZE;
//已解冻
case NoCodeFlowNode.NODE_ACTION_DELETE://删除
return NoCodeFlowNode.NODE_STATE_DELETE;
//已删除
case NoCodeFlowNode.NODE_ACTION_ABANDON://作废
return NoCodeFlowNode.NODE_STATE_ABANDON;
//已作废
case NoCodeFlowNode.NODE_ACTION_FINISH://完结
return NoCodeFlowNode.NODE_STATE_FINISHED;
//已完结
}return NoCodeFlowNode.NODE_STATE_NO_SUBMIT;
}
//endregion //region 节点状态、动作、类型,文字颜色样式
//获取节点值与名称的map表
public static Map getNodeTypeCssMap() {
Map mapNodeTypeCss = new LinkedHashMap<>();
mapNodeTypeCss.put(NoCodeFlowNode.NODE_TYPE_START, "text-info");
mapNodeTypeCss.put(NoCodeFlowNode.NODE_TYPE_END, "text-muted");
mapNodeTypeCss.put(NoCodeFlowNode.NODE_TYPE_SERIAL, "text-success");
mapNodeTypeCss.put(NoCodeFlowNode.NODE_TYPE_BRANCH, "text-warning");
mapNodeTypeCss.put(NoCodeFlowNode.NODE_TYPE_AND_SINGLE, "text-danger");
mapNodeTypeCss.put(NoCodeFlowNode.NODE_TYPE_AND_MULTI, "text-danger");
mapNodeTypeCss.put(NoCodeFlowNode.NODE_TYPE_AND_ALL, "text-danger");
return mapNodeTypeCss;
} //根据节点类型获取文字样式名称
public static String getNodeTypeCss(int nodeType) {
return getNodeTypeCssMap().get(nodeType);
} //获取流程状态值与名称map表
public static Map getNodeStateCssMap() {
Map mapNodeStateCss = new LinkedHashMap<>();
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_NO_SUBMIT, "");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_HAS_SUBMIT, "text-success");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_APPROVE, "text-info");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_REFUSE, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_REJECT, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_CANCEL, "text-warning");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_READ, "text-success");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_FORWARD, "text-success");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_BACK, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_FREEZE, "text-warning");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_UNFREEZE, "text-info");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_DELETE, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_ABANDON, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_STATE_FINISHED, "text-muted");
return mapNodeStateCss;
} //根据节点状态获取文字样式名称
public static String getNodeStateCss(int nodeState) {
return getNodeStateCssMap().get(nodeState);
} //获取操作类型值与名称map表
public static Map getNodeActionCssMap() {
Map mapNodeStateCss = new LinkedHashMap<>();
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_SAVE, "");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_SUBMIT, "text-success");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_CANCEL, "text-warning");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_APPROVE, "text-info");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_REFUSE, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_REJECT, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_FORWARD, "text-success");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_READ, "text-success");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_BACK, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_FREEZE, "text-warning");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_UNFREEZE, "text-info");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_DELETE, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_ABANDON, "text-danger");
mapNodeStateCss.put(NoCodeFlowNode.NODE_ACTION_FINISH, "text-muted");
return mapNodeStateCss;
} //根据节点类型获取文字样式名称
public static String getNodeActionCss(int nodeAction) {
return getNodeActionCssMap().get(nodeAction);
} //endregion
}
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 基于微信小程序带后端ssm接口小区物业管理平台设计
- 2020-04-07vue中Axios的封装和API接口的管理
- 调取接口时报404错误(ID:16)
- CICC(脑机接口,科幻几近成真())
- 接口|axios接口报错-参数类型错误解决
- 190403|190403 - Jmeter压测接口
- JavaScript|vue 基于axios封装request接口请求——request.js文件
- 微信小程序请求接口格式
- 简易有效Api接口防攻击策略