今天说一下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@elt2006.com
*/
@RequestMapping(value="rollBack",method = RequestMethod.POST )
@ResponseBody
public 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.使用流程实例对象获取BusinessKey
String 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 代码:
@Override
public int rollBackTask(String taskId, String jumpTaskId, String execId) {
checkSheetDao.deleteHisTask(taskId,execId);
/*更新跳转任务的完成时间 和状态*/
checkSheetDao.updateJumpTask(jumpTaskId,execId);
String linkId=checkSheetDao.getLinkId(taskId);
//更新taskId 解除关联 ACT_RU_IDENTITYLINK
checkSheetDao.unlockTask(linkId);
//更新当前任务 名称 fromKey id
checkSheetDao.updateRunTask(execId,taskId,jumpTaskId);
//更新ACT_RU_IDENTITYLINK 的taskid
checkSheetDao.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_=NULL
where
EXECUTION_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,
(
SELECT
TASK_DEF_KEY_,
FORM_KEY_,
NAME_,
ID_
FROM
ACT_HI_TASKINST
WHERE
EXECUTION_ID_ = #{execId,jdbcType=VARCHAR}
AND ID_ = #{jumpId,jdbcType=VARCHAR}
) b
SET a.ID_ = b.ID_,
a.TASK_DEF_KEY_ = b.TASK_DEF_KEY_,
a.NAME_ = b.NAME_,
a.FORM_KEY_ = b.FORM_KEY_
WHERE
a.EXECUTION_ID_ = #{execId,jdbcType=VARCHAR}
AND a.id_ = #{taskId,jdbcType=VARCHAR}
</update>
<update id="updateExecActId" parameterType="map" >
UPDATE ACT_RU_EXECUTION a,
(
SELECT
TASK_DEF_KEY_
FROM
ACT_RU_TASK
WHERE
ID_ = #{taskId,jdbcType=VARCHAR}
) b
SET a.ACT_ID_ = b.TASK_DEF_KEY_
WHERE
ID_ = #{execId,jdbcType=VARCHAR}
</update>
我用的版本是activiti5.22.0,有疑问可以威信联系springjson 或者私信我