1.需求场景
在涉及到工作流相关的业务场景时,业务数据和流程数据最好是要做到相互隔离,互不影响。因此,数据和逻辑之间,耦合度越低越好。工作流引擎作为一个独立的模块,要方便业务数据调用。
2.接口说明
2.1.1.启动流程
启动一个流程,需要插入业务数据,也需要插入流程日志和发布流程任务。
要做到业务数据与流程数据隔离,所以启动流程接口startFlowInstance提供2种方式:自行添加完业务数据后,启动流程;以及让流程引擎来处理业务数据,并启动流程(那么需要把添加业务数据的SQL传递给流程)。
如下代码所示,为2种方式的接口源码。
//启动一个新的流程实例。流程引擎向业务表中插入数据(需传入插入数据的SQL语句和参数)。成功后,会返回新插入的业务数据id
public static NoCodeResult startFlowInstance(String tableName, int flowId, int userId, String sqlInsert, Object[] sqlParams) {
NoCodeResult noCodeResult = new NoCodeResult();
if (StringUtil.isEmpty(sqlInsert)) {
noCodeResult.setFailureInfo("业务插入SQL语句不能为空");
return noCodeResult;
}
//进行基本的流程数据校验
NoCodeFlowParam flowParam = startFlowInstanceBaseValidate(tableName, flowId, userId, noCodeResult);
if (flowParam == null) {
return noCodeResult;
}
//传递业务数据插入SQL语句和参数
flowParam.setSqlBusiness(sqlInsert);
flowParam.setSqlParam(sqlParams);
//执行启动流程:调用事务启动流程
return executeStartFlowDao(flowParam);
}
//启动一个新的流程实例。流程引擎只处理流程相关数据,如果启动失败,建议自行删除添加的业务数据
public static NoCodeResult startFlowInstance(String tableName, int flowId, int userId, int dataId) {
NoCodeResult noCodeResult = new NoCodeResult();
//进行基本的流程数据校验
NoCodeFlowParam flowParam = startFlowInstanceBaseValidate(tableName, flowId, userId, noCodeResult);
if (flowParam == null) {
return noCodeResult;
}
//自行添加完业务数据后,将新添加的业务数据id传递进去
flowParam.setDataId(dataId);
//执行启动流程:调用事务启动流程
return executeStartFlowDao(flowParam);
}
3.调用样例
3.1.启动流程
启动流程提供2种方式接口。
3.1.1.自动处理业务并启动流程
如果由工作流引擎来处理业务数据,则需要将插入业务数据的SQL语句以及SQL参数,传递到接口方法中。
接口启动流程成功后,会返回新增业务数据的id。如下样例所示,为启动流程和自动处理业务数据代码。
//提交发起流程表单。添加业务表单数据,发起流程。
public NoCodeResult submitFlowStart(HttpSession httpSession, Map<String, String[]> mapRequestParam, int flowId) {
//保存业务数据的SQL和参数
List<Object> sqlParam = genSqlParamForInsert(mListField);
String sqlSave = genSqlQueryForDataInsert();
//从session中获取当前用户id
int userId = StringUtil.convertToInt(httpSession.getAttribute(NoCodeUser.SESSION_USERID));
//暂存数据后,启动新流程。启动成功后,会将新的流程实例id赋值到data属性中
NoCodeResult noCodeResult = FlowUtil.startFlowInstance(mPage.getTableName(), flowId, userId, sqlSave, sqlParam.toArray());
return noCodeResult;
}
3.1.2.手动处理业务并启动流程
如果业务数据比较复杂,不能通过一条insert语句来解决,那么可以在自己手动添加完业务数据后,再启动流程。
注意:如果启动流程失败后,要对已处理的业务数据,进行回滚。因为业务和流程的处理,不是一个事务操作。所以必须要对失败情况进行处理。
手动处理业务以及启动流程的代码样例如下:
//手动处理完业务数据后,启动流程。
public NoCodeResult manualStartFlow(HttpSession httpSession, Map<String, String[]> mapRequestParam, int flowId) {
if (!baseValidate(httpSession, mapRequestParam, flowId)) {
return mResult;
}
//验证字段数据
if (!validateFieldValueForSave()) {
return mResult;
}
//保存业务数据的SQL和参数
List<Object> sqlParam = genSqlParamForInsert(mListField);
String sqlSave = genSqlQueryForDataInsert();
int rowId = 0;
try {
FlowInstanceDao instanceDao = new FlowInstanceDao();
rowId = instanceDao.insertBusinessData(sqlSave, sqlParam.toArray());
if (rowId <= 0) {
mResult.setFailureInfo("添加业务数据失败");
return mResult;
}
} catch (SQLException e) {
e.printStackTrace();
ExceptionUtil.insertDB(e, "添加业务数据异常");
mResult.setExceptionInfo(e, "添加业务数据异常");
return mResult;
}
//从session中获取当前用户id
int userId = StringUtil.convertToInt(httpSession.getAttribute(NoCodeUser.SESSION_USERID));
//暂存数据后,启动新流程。启动成功后,会将新的流程实例id赋值到data属性中
NoCodeResult noCodeResult = FlowUtil.startFlowInstance(mPage.getTableName(), flowId, userId, rowId);
//如果流程启动失败,则需要回滚业务
if (!noCodeResult.isSuccess()){
//删除新增的业务数据
}
return noCodeResult;
}