今天说一下activiti中任务回退的实现,业务场景:流程中任意节点除了开始节点,每个任务节点都能回退到上级节点,会签(暂时没考虑),来个简单流程图
1、简单介绍下activiti开启流程后表之间的关系,回退任务就是根据表数据的关系,修改表数据完成回退。
ACT_RU_TASK 正在运行的任务节点表
ACT_RU_EXECUTION 运行时流程执行实例表
ACT_HI_TASKINST 历史任务节点表(包括正在运行的)
ACT_RU_IDENTITYLINK 任务与人员关联表
2、回退任务我们只需要提供当前taskId 和要回退到节点的taskId
具体实现:
1、根据taskId 查询上一个节点taskId 和 运行时流程实例ID_ ,我用的springboot controller代码如下
/*** 任务回退* @param remark* @param taskId 当前任务id* @return* @throws Exception* @author penghongbao@*/@RequestMapping(value="rollBack",method = RequestMethod.POST )@ResponseBodypublic MessageBody rollBack(@RequestParam(value="remark",required=false)String remark,@RequestParam(value="taskId",required=true)String taskId) throws Exception{Task task=workFlowService.getTaskById(taskId);ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();//4.使用流程实例对象获取BusinessKeyString business_key = pi.getBusinessKey();String execId=task.getExecutionId();CheckSheetProHis his=new CheckSheetProHis();his.setId(ToolUtils.getUUID());his.setCheckProId(business_key);his.setOptime(DateUtil.toString(new Date()));if(remark!=null){his.setShenpiremark(remark);}his.setShenpiaction(task.getName()+"-撤銷");his.setExecutor(UCHome.getLabUser().getName());String processInstanceId = task.getProcessInstanceId();List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).finished().orderByTaskCreateTime().desc().list();String parentTaskId="";if (list != null && list.size() > 0) {//按照完成时间排序取第一个 回退到该节点parentTaskId=list.get(0).getId();for (HistoricTaskInstance hti : list) {System.out.print("taskId:" + hti.getId()+",");System.out.print("name:" + hti.getName()+",");System.out.print("pdId:" + hti.getProcessDefinitionId()+",");System.out.print("assignee:" + hti.getAssignee()+",");}}//workFlowService.TaskRollBack(taskId);if(StringUtils.isNotBlank(parentTaskId)){//插入审批记录//退回任务checkSheetClient.rollBackTask(taskId,parentTaskId,execId);//记录日志checkSheetProHisClient.insert(his);}else{return MessageBody.getMessageBody(false,"上级任务为空!");}return MessageBody.getMessageBody(true,"撤销成功!");}
2、根据任务id和实例id进行回退操作具体步骤和sql如下
service 代码:@Overridepublic int rollBackTask(String taskId, String jumpTaskId, String execId) {checkSheetDao.deleteHisTask(taskId,execId);/*更新跳转任务的完成时间 和状态*/checkSheetDao.updateJumpTask(jumpTaskId,execId);String linkId=checkSheetDao.getLinkId(taskId);//更新taskId 解除关联 ACT_RU_IDENTITYLINKcheckSheetDao.unlockTask(linkId);//更新当前任务 名称 fromKey idcheckSheetDao.updateRunTask(execId,taskId,jumpTaskId);//更新ACT_RU_IDENTITYLINK 的taskidcheckSheetDao.updateLinkTask(linkId,jumpTaskId);//更新execu的 act_id_checkSheetDao.updateExecActId(execId,jumpTaskId);return Constants.SUCCESS;}
dao层代码:
/**1、删除历史表ACT_HI_TASKINST 没完成的任务***/public int deleteHisTask(String taskId,String execId){Map<String,Object> param=new HashMap();param.put("taskId",taskId);param.put("execId",execId);return this.getSqlReadSession().getMapper(CheckSheetMapper.class).deleteHisTask(param);}/**2、更新ACT_HI_TASKINST 已完成的任务完成时间为NULL ***/public int updateJumpTask(String jumpTaskId,String execId){Map<String,Object> param=new HashMap();param.put("taskId",jumpTaskId);param.put("execId",execId);return this.getSqlReadSession().getMapper(CheckSheetMapper.class).updateJumpTask(param);}/**3、获取linkId***/public String getLinkId(String taskId){Map<String,Object> param=new HashMap();param.put("taskId",taskId);return this.getSqlReadSession().getMapper(CheckSheetMapper.class).getLinkId(param);}/**4、更新成NULL 解除任务关联***/public int unlockTask(String id){Map<String,Object> param=new HashMap();param.put("id",id);return this.getSqlReadSession().getMapper(CheckSheetMapper.class).unlockTask(param);}/**5、更新成taskId 解除任务关联***/public int updateRunTask(String execId,String taskId,String jumpId){Map<String,Object> param=new HashMap();param.put("execId",execId);param.put("taskId",taskId);param.put("jumpId",jumpId);return this.getSqlReadSession().getMapper(CheckSheetMapper.class).updateRunTask(param);}/**6、更新成taskId 解除任务关联***/public int updateLinkTask(String id,String taskId){Map<String,Object> param=new HashMap();param.put("id",id);param.put("taskId",taskId);return this.getSqlReadSession().getMapper(CheckSheetMapper.class).updateLinkTask(param);}/**7、更新成taskId 解除任务关联***/public int updateExecActId(String execId,String jumpTaskId){Map<String,Object> param=new HashMap();param.put("execId",execId);param.put("taskId",jumpTaskId);return this.getSqlReadSession().getMapper(CheckSheetMapper.class).updateExecActId(param);}
mybatis -sql代码:
<delete id="deleteHisTask" parameterType="map" >DELETE from ACT_HI_TASKINST where EXECUTION_ID_=#{execId,jdbcType=VARCHAR} and id_=#{taskId,jdbcType=VARCHAR}</delete><update id="updateJumpTask" parameterType="map" >update ACT_HI_TASKINST set END_TIME_ =NULL,DURATION_=NULL,DELETE_REASON_=NULLwhereEXECUTION_ID_=#{execId,jdbcType=VARCHAR} and id_=#{taskId,jdbcType=VARCHAR}</update><select id="getLinkId" parameterType="map" resultType="java.lang.String">select ID_ from ACT_RU_IDENTITYLINK where TASK_ID_=#{taskId,jdbcType=VARCHAR}</select><update id="unlockTask" parameterType="map" >update ACT_RU_IDENTITYLINK set TASK_ID_=NULL where ID_=#{id,jdbcType=VARCHAR}</update><update id="updateLinkTask" parameterType="map" >update ACT_RU_IDENTITYLINK set TASK_ID_=#{taskId,jdbcType=VARCHAR} where ID_=#{id,jdbcType=VARCHAR}</update><update id="updateRunTask" parameterType="map" >UPDATE ACT_RU_TASK a,(SELECTTASK_DEF_KEY_,FORM_KEY_,NAME_,ID_FROMACT_HI_TASKINSTWHEREEXECUTION_ID_ = #{execId,jdbcType=VARCHAR}AND ID_ = #{jumpId,jdbcType=VARCHAR}) bSET a.ID_ = b.ID_,a.TASK_DEF_KEY_ = b.TASK_DEF_KEY_,a.NAME_ = b.NAME_,a.FORM_KEY_ = b.FORM_KEY_WHEREa.EXECUTION_ID_ = #{execId,jdbcType=VARCHAR}AND a.id_ = #{taskId,jdbcType=VARCHAR}</update><update id="updateExecActId" parameterType="map" >UPDATE ACT_RU_EXECUTION a,(SELECTTASK_DEF_KEY_FROMACT_RU_TASKWHEREID_ = #{taskId,jdbcType=VARCHAR}) bSET a.ACT_ID_ = b.TASK_DEF_KEY_WHEREID_ = #{execId,jdbcType=VARCHAR}</update>
我用的版本是activiti5.22.0,有疑问可以威信联系springjson 或者私信我