在使用camunda的过程中,往往需要给用户任务节点设置审批人,最快的方法就是 使用全局监听来实现。
直接先定义 全局任务监听和执行监听
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.delegate.DelegateTask;
import org.camunda.bpm.engine.delegate.TaskListener;
import org.springframework.stereotype.Component;
/**
* 全局任务监听,用于设置任务处理人逻辑
*
*/
@Component
@Slf4j
public class GlobalTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
log.info("用户任务监听");
// 查询审批配置,设置审批人
// 设置单个审批人
// delegateTask.setAssignee();
// 设置候选用户
// delegateTask.addCandidateUsers();
}
}
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.ExecutionListener;
import org.camunda.bpm.model.bpmn.impl.instance.SequenceFlowImpl;
import org.camunda.bpm.model.bpmn.impl.instance.UserTaskImpl;
import org.camunda.bpm.model.bpmn.instance.FlowElement;
import org.camunda.bpm.model.bpmn.instance.FlowNode;
import org.camunda.bpm.model.bpmn.instance.LoopCharacteristics;
import org.camunda.bpm.model.bpmn.instance.MultiInstanceLoopCharacteristics;
import org.camunda.bpm.model.bpmn.instance.UserTask;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
// 这个执行监听用于 多实例任务节点设置审批人
@Slf4j
@Component
public class GlobalMultiInstanceExecutionListener implements ExecutionListener {
@Override
public void notify(DelegateExecution delegateExecution) throws Exception {
log.info("全局执行监听");
FlowElement currentElement = delegateExecution.getBpmnModelElementInstance();
// 是连线
if ((!(currentElement instanceof SequenceFlowImpl))) {
return;
}
// 是任务节点
FlowNode targetNode = ((SequenceFlowImpl) currentElement).getTarget();
if ((!(targetNode instanceof UserTask))) {
return;
}
// 是多实例节点
LoopCharacteristics loopCharacteristics = ((UserTaskImpl) targetNode).getLoopCharacteristics();
if (!Objects.nonNull(loopCharacteristics) || !(loopCharacteristics instanceof MultiInstanceLoopCharacteristics)) {
return;
}
// 设置 多实例集合
// TODO 设置审批逻辑
}
}
实现的方法是 自定义 BpmnParseListener 解析器 在流程引擎解析xml的时候,把上面两个监听器添加到xml中。继承 ProcessApplicationEventParseListener ,并重写里面的方法。
ProcessApplicationEventParseListener 里面有每个节点类型的解析方法,这里只重写了两个
解析用户任务的方法 parseUserTask 和解析连线节点 parseSequenceFlow 方法,如果有其他需求,可以重写父类里面的其他方法
这里给多实例节点设置审批人比较特殊,不能在执行到这个节点上的时候 使用任务监听或执行监听来设置,必须在执行到这个节点之前就设置好多实例集合,所以这里在多实例节点前的连线上添加 执行监听。
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.application.impl.event.ProcessApplicationEventParseListener;
import org.camunda.bpm.engine.delegate.ExecutionListener;
import org.camunda.bpm.engine.delegate.TaskListener;
import org.camunda.bpm.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.camunda.bpm.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.camunda.bpm.engine.impl.pvm.PvmActivity;
import org.camunda.bpm.engine.impl.pvm.delegate.ActivityBehavior;
import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl;
import org.camunda.bpm.engine.impl.pvm.process.ScopeImpl;
import org.camunda.bpm.engine.impl.pvm.process.TransitionImpl;
import org.camunda.bpm.engine.impl.task.TaskDefinition;
import org.camunda.bpm.engine.impl.util.xml.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 自定义 解析器
*/
@Slf4j
@Component
public class DyBpmnParseListener extends ProcessApplicationEventParseListener {
@Autowired
private GlobalTaskListener globalTaskListener;
@Autowired
private GlobalMultiInstanceExecutionListener globalMultiInstanceExecutionListener;
/**
* 自定义流程引擎 在解析用户任务前的逻辑
* 给所有任务 添加 create事件 任务监听 GlobalTaskListener
*/
@Override
public void parseUserTask(Element userTaskElement, ScopeImpl scope, ActivityImpl activity) {
this.addStartEventListener(activity);
this.addEndEventListener(activity);
UserTaskActivityBehavior activityBehavior = (UserTaskActivityBehavior) activity.getActivityBehavior();
TaskDefinition taskDefinition = activityBehavior.getTaskDefinition();
taskDefinition.addTaskListener(TaskListener.EVENTNAME_CREATE, globalTaskListener);
this.addTaskCreateListeners(taskDefinition);
this.addTaskAssignmentListeners(taskDefinition);
this.addTaskCompleteListeners(taskDefinition);
this.addTaskUpdateListeners(taskDefinition);
this.addTaskDeleteListeners(taskDefinition);
}
/**
* 解析连线
* 如果连线的目标节点 是多实例节点,则给当前连线设置 执行监听
*/
@Override
public void parseSequenceFlow(Element sequenceFlowElement, ScopeImpl scopeElement, TransitionImpl transition) {
PvmActivity destination = transition.getDestination();
ActivityBehavior activityBehavior = destination.getActivityBehavior();
// 多实例,默认给当前连线设置执行监听
if (activityBehavior instanceof MultiInstanceActivityBehavior) {
transition.addListener(ExecutionListener.EVENTNAME_TAKE, globalMultiInstanceExecutionListener);
}
this.addTakeEventListener(transition);
}
}
然后将自定义解析器添加到 流程引擎插件中
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ProcessEngineConfig implements ProcessEnginePlugin {
@Autowired
private DyBpmnParseListener dyBpmnParseListener;
@Override
public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
// 关闭历史记录清理,系统需要保留历史记录
processEngineConfiguration.setHistoryCleanupEnabled(false);
// 配置自定义解析器
processEngineConfiguration.getCustomPreBPMNParseListeners().add(dyBpmnParseListener);
}
@Override
public void postInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
}
@Override
public void postProcessEngineBuild(ProcessEngine processEngine) {
}
}