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;
}