add 添加自定义任务监听策略

This commit is contained in:
gssong 2023-12-27 22:06:12 +08:00
parent a0e1413b69
commit ed66fbf38e
10 changed files with 227 additions and 1 deletions

View File

@ -0,0 +1,27 @@
package org.dromara.workflow.annotation;
import java.lang.annotation.*;
/**
* 流程任务监听注解
*
* @author may
* @date 2023-12-27
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface FlowListenerAnnotation {
/**
* 流程定义
*/
String processDefinitionKey();
/**
* 节点定义
*/
String taskDefId() default "";
}

View File

@ -2,6 +2,8 @@ package org.dromara.workflow.flowable.config;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import org.dromara.workflow.common.enums.TaskStatusEnum; import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.flowable.strategy.FlowEventStrategy;
import org.dromara.workflow.flowable.strategy.FlowTaskEventHandler;
import org.flowable.bpmn.model.BoundaryEvent; import org.flowable.bpmn.model.BoundaryEvent;
import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.FlowElement;
@ -10,9 +12,11 @@ import org.flowable.common.engine.impl.cfg.TransactionState;
import org.flowable.engine.RepositoryService; import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService; import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService; import org.flowable.engine.TaskService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution; import org.flowable.engine.runtime.Execution;
import org.flowable.engine.task.Comment; import org.flowable.engine.task.Comment;
import org.flowable.task.api.Task; import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -40,12 +44,16 @@ public class GlobalFlowableListener implements FlowableEventListener {
@Lazy @Lazy
private RepositoryService repositoryService; private RepositoryService repositoryService;
@Autowired
private FlowEventStrategy flowEventStrategy;
@Override @Override
public void onEvent(FlowableEvent flowableEvent) { public void onEvent(FlowableEvent flowableEvent) {
if (flowableEvent instanceof FlowableEngineEvent flowableEngineEvent) { if (flowableEvent instanceof FlowableEngineEvent flowableEngineEvent) {
FlowableEngineEventType engineEventType = (FlowableEngineEventType) flowableEvent.getType(); FlowableEngineEventType engineEventType = (FlowableEngineEventType) flowableEvent.getType();
switch (engineEventType) { switch (engineEventType) {
case JOB_EXECUTION_SUCCESS -> jobExecutionSuccess((FlowableEngineEntityEvent) flowableEngineEvent); case JOB_EXECUTION_SUCCESS -> jobExecutionSuccess((FlowableEngineEntityEvent) flowableEngineEvent);
case TASK_COMPLETED -> taskCompleted((FlowableEngineEntityEvent) flowableEngineEvent);
} }
} }
} }
@ -65,6 +73,11 @@ public class GlobalFlowableListener implements FlowableEventListener {
return TransactionState.COMMITTED.name(); return TransactionState.COMMITTED.name();
} }
/**
* 处理边界定时事件自动审批记录
*
* @param event 事件
*/
protected void jobExecutionSuccess(FlowableEngineEntityEvent event) { protected void jobExecutionSuccess(FlowableEngineEntityEvent event) {
Execution execution = runtimeService.createExecutionQuery().executionId(event.getExecutionId()).singleResult(); Execution execution = runtimeService.createExecutionQuery().executionId(event.getExecutionId()).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(event.getProcessDefinitionId()); BpmnModel bpmnModel = repositoryService.getBpmnModel(event.getProcessDefinitionId());
@ -83,4 +96,21 @@ public class GlobalFlowableListener implements FlowableEventListener {
} }
} }
} }
/**
* 处理任务办理监听
*
* @param event 事件
*/
protected void taskCompleted(FlowableEngineEntityEvent event) {
TaskEntity entity = (TaskEntity) event.getEntity();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(entity.getProcessDefinitionId()).singleResult();
String processDefinitionKey = processDefinition.getKey();
String taskDefinitionKey = entity.getTaskDefinitionKey();
String beanName = processDefinitionKey + "_" + taskDefinitionKey;
FlowTaskEventHandler handler = flowEventStrategy.getTaskHandler(beanName);
if (handler != null) {
handler.handleTask(entity);
}
}
} }

View File

@ -0,0 +1,68 @@
package org.dromara.workflow.flowable.strategy;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.workflow.annotation.FlowListenerAnnotation;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* 流程任务监听策略
*
* @author may
* @date 2023-12-27
*/
@Component
public class FlowEventStrategy implements BeanPostProcessor {
private final Map<String, FlowTaskEventHandler> flowTaskEventHandlers = new HashMap<>();
private final Map<String, FlowProcessEventHandler> flowProcessEventHandlers = new HashMap<>();
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof FlowTaskEventHandler || bean instanceof FlowProcessEventHandler) {
FlowListenerAnnotation annotation = bean.getClass().getAnnotation(FlowListenerAnnotation.class);
if (null != annotation) {
if (StringUtils.isNotBlank(annotation.processDefinitionKey()) && StringUtils.isNotBlank(annotation.taskDefId())) {
String id = annotation.processDefinitionKey() + "_" + annotation.taskDefId();
if (!flowTaskEventHandlers.containsKey(id)) {
flowTaskEventHandlers.put(id, (FlowTaskEventHandler) bean);
}
}
if (StringUtils.isNotBlank(annotation.processDefinitionKey()) && StringUtils.isBlank(annotation.taskDefId())) {
if (!flowProcessEventHandlers.containsKey(annotation.processDefinitionKey())) {
flowProcessEventHandlers.put(annotation.processDefinitionKey(), (FlowProcessEventHandler) bean);
}
}
}
}
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
/**
* 获取可执行bean
*
* @param beanName beanName
*/
public FlowTaskEventHandler getTaskHandler(String beanName) {
if (!flowTaskEventHandlers.containsKey(beanName)) {
return null;
}
return flowTaskEventHandlers.get(beanName);
}
/**
* 获取可执行bean
*
* @param beanName beanName
*/
public FlowProcessEventHandler getProcessHandler(String beanName) {
if (!flowProcessEventHandlers.containsKey(beanName)) {
return null;
}
return flowProcessEventHandlers.get(beanName);
}
}

View File

@ -0,0 +1,19 @@
package org.dromara.workflow.flowable.strategy;
/**
* 流程监听
*
* @author may
* @date 2023-12-27
*/
public interface FlowProcessEventHandler {
/**
* 执行办理任务监听
*
* @param processInstanceId 流程实例id
* @param status 状态
*/
void handleProcess(String processInstanceId, String status);
}

View File

@ -0,0 +1,19 @@
package org.dromara.workflow.flowable.strategy;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
/**
* 流程任务监听
*
* @author may
* @date 2023-12-27
*/
public interface FlowTaskEventHandler {
/**
* 执行办理任务监听
*
* @param taskEntity 任务
*/
void handleTask(TaskEntity taskEntity);
}

View File

@ -0,0 +1,24 @@
package org.dromara.workflow.listener;
import lombok.extern.slf4j.Slf4j;
import org.dromara.workflow.annotation.FlowListenerAnnotation;
import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
import org.springframework.stereotype.Component;
/**
* 自定义监听测试
*
* @author may
* @date 2023-12-27
*/
@Slf4j
@Component
@FlowListenerAnnotation(processDefinitionKey = "leave1")
public class TestCustomProcessHandler implements FlowProcessEventHandler {
@Override
public void handleProcess(String processInstanceId, String status) {
log.info("流程实例ID:" + processInstanceId + ",状态:" + status);
}
}

View File

@ -0,0 +1,24 @@
package org.dromara.workflow.listener;
import lombok.extern.slf4j.Slf4j;
import org.dromara.workflow.annotation.FlowListenerAnnotation;
import org.dromara.workflow.flowable.strategy.FlowTaskEventHandler;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;
/**
* 自定义监听测试
*
* @author may
* @date 2023-12-27
*/
@Slf4j
@Component
@FlowListenerAnnotation(processDefinitionKey = "leave1", taskDefId = "sid-31C52262-04C3-43D8-A3FB-8434017A6572")
public class TestCustomTaskHandler implements FlowTaskEventHandler {
@Override
public void handleTask(TaskEntity taskEntity) {
log.info("任务名称:" + taskEntity.getName());
}
}

View File

@ -2,7 +2,6 @@ package org.dromara.workflow.listener;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService; import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener; import org.flowable.engine.delegate.ExecutionListener;

View File

@ -26,8 +26,10 @@ import org.dromara.workflow.domain.vo.GraphicInfoVo;
import org.dromara.workflow.domain.vo.ProcessInstanceVo; import org.dromara.workflow.domain.vo.ProcessInstanceVo;
import org.dromara.workflow.domain.vo.TaskVo; import org.dromara.workflow.domain.vo.TaskVo;
import org.dromara.workflow.flowable.CustomDefaultProcessDiagramGenerator; import org.dromara.workflow.flowable.CustomDefaultProcessDiagramGenerator;
import org.dromara.workflow.flowable.strategy.FlowEventStrategy;
import org.dromara.workflow.flowable.cmd.DeleteExecutionCmd; import org.dromara.workflow.flowable.cmd.DeleteExecutionCmd;
import org.dromara.workflow.flowable.cmd.ExecutionChildByExecutionIdCmd; import org.dromara.workflow.flowable.cmd.ExecutionChildByExecutionIdCmd;
import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
import org.dromara.workflow.service.IActHiProcinstService; import org.dromara.workflow.service.IActHiProcinstService;
import org.dromara.workflow.service.IActProcessInstanceService; import org.dromara.workflow.service.IActProcessInstanceService;
import org.dromara.workflow.utils.WorkflowUtils; import org.dromara.workflow.utils.WorkflowUtils;
@ -69,6 +71,7 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
private final TaskService taskService; private final TaskService taskService;
private final IActHiProcinstService actHiProcinstService; private final IActHiProcinstService actHiProcinstService;
private final ManagementService managementService; private final ManagementService managementService;
private final FlowEventStrategy flowEventStrategy;
@Value("${flowable.activity-font-name}") @Value("${flowable.activity-font-name}")
private String activityFontName; private String activityFontName;
@ -366,6 +369,8 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
} }
runtimeService.updateBusinessStatus(processInvalidBo.getProcessInstanceId(), BusinessStatusEnum.INVALID.getStatus()); runtimeService.updateBusinessStatus(processInvalidBo.getProcessInstanceId(), BusinessStatusEnum.INVALID.getStatus());
runtimeService.deleteProcessInstance(processInvalidBo.getProcessInstanceId(), deleteReason); runtimeService.deleteProcessInstance(processInvalidBo.getProcessInstanceId(), deleteReason);
FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(historicProcessInstance.getProcessDefinitionKey());
processHandler.handleProcess(historicProcessInstance.getId(), BusinessStatusEnum.INVALID.getStatus());
return true; return true;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -495,6 +500,8 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
managementService.executeCommand(deleteExecutionCmd); managementService.executeCommand(deleteExecutionCmd);
} }
runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.CANCEL.getStatus()); runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.CANCEL.getStatus());
FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
processHandler.handleProcess(processInstanceId, BusinessStatusEnum.CANCEL.getStatus());
return true; return true;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -20,7 +20,9 @@ import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.domain.bo.*; import org.dromara.workflow.domain.bo.*;
import org.dromara.workflow.domain.vo.MultiInstanceVo; import org.dromara.workflow.domain.vo.MultiInstanceVo;
import org.dromara.workflow.domain.vo.TaskVo; import org.dromara.workflow.domain.vo.TaskVo;
import org.dromara.workflow.flowable.strategy.FlowEventStrategy;
import org.dromara.workflow.flowable.cmd.*; import org.dromara.workflow.flowable.cmd.*;
import org.dromara.workflow.flowable.strategy.FlowProcessEventHandler;
import org.dromara.workflow.service.IActTaskService; import org.dromara.workflow.service.IActTaskService;
import org.dromara.workflow.utils.WorkflowUtils; import org.dromara.workflow.utils.WorkflowUtils;
import org.flowable.common.engine.impl.identity.Authentication; import org.flowable.common.engine.impl.identity.Authentication;
@ -59,6 +61,7 @@ public class ActTaskServiceImpl implements IActTaskService {
private final HistoryService historyService; private final HistoryService historyService;
private final IdentityService identityService; private final IdentityService identityService;
private final ManagementService managementService; private final ManagementService managementService;
private final FlowEventStrategy flowEventStrategy;
/** /**
* 启动任务 * 启动任务
@ -161,6 +164,8 @@ public class ActTaskServiceImpl implements IActTaskService {
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus()); UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus());
managementService.executeCommand(updateBusinessStatusCmd); managementService.executeCommand(updateBusinessStatusCmd);
FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
processHandler.handleProcess(processInstance.getId(), BusinessStatusEnum.FINISH.getStatus());
} else { } else {
sendMessage(list, processInstance.getName(), completeTaskBo.getMessageType(), null); sendMessage(list, processInstance.getName(), completeTaskBo.getMessageType(), null);
} }
@ -431,6 +436,8 @@ public class ActTaskServiceImpl implements IActTaskService {
runtimeService.deleteProcessInstance(task.getProcessInstanceId(), StrUtil.EMPTY); runtimeService.deleteProcessInstance(task.getProcessInstanceId(), StrUtil.EMPTY);
} }
runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.TERMINATION.getStatus()); runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.TERMINATION.getStatus());
FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(historicProcessInstance.getProcessDefinitionKey());
processHandler.handleProcess(historicProcessInstance.getId(), BusinessStatusEnum.TERMINATION.getStatus());
return true; return true;
} catch (Exception e) { } catch (Exception e) {
throw new ServiceException(e.getMessage()); throw new ServiceException(e.getMessage());
@ -609,6 +616,8 @@ public class ActTaskServiceImpl implements IActTaskService {
managementService.executeCommand(deleteExecutionCmd); managementService.executeCommand(deleteExecutionCmd);
} }
runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus()); runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus());
FlowProcessEventHandler processHandler = flowEventStrategy.getProcessHandler(processInstance.getProcessDefinitionKey());
processHandler.handleProcess(processInstanceId, BusinessStatusEnum.BACK.getStatus());
} catch (Exception e) { } catch (Exception e) {
throw new ServiceException(e.getMessage()); throw new ServiceException(e.getMessage());
} }