监听器
目录
任务监听器
说明
任务监听器是处理业务逻辑的重要的地方,当任务创建
、设定负责人
、完成任务
时都可以监听的到从而来处理自己的业务。
常用于监听Assignment事件,设置完负责人给负责人发一个消息来通知提示。注意:任务监听器只能在节点UserTask
上使用。
监听的事件类型(Event
属性):
-
Create:任务创建后触发。常用于任务创建后设置任务负责人等。
-
Assignment:任务分配后触发。常用于设置完负责人后向负责人发邮件、短信等通知一下。
-
Delete:任务完成后触发。
-
All:所有事件发生都触发。
bpmn设置
直接点击Task Listeners 前面的三角是展示不了内容的,要先点击Task Listeners右边的空白处再点击三角才会展开,Listener也是如此。
class为java类名 in 包路径
监听器代码
任务监听器需要实现TaskListener
,然后重写notify
函数
public class OffWorkTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
System.out.println(delegateTask.getName());
// create,assignment,delete,all
System.out.println(delegateTask.getEventName());
// delegateTask.setAssignee("xxx");
}
}
也可以自动指定责任人
public class MyTaskListener implements TaskListener {
public void notify(DelegateTask delegateTask) {
//判断当前的任务是 创建申请 并且是 create事件,则指定责任人为 张三
if("创建申请".equals(delegateTask.getName()) &&
"create".equals(delegateTask.getEventName())){
delegateTask.setAssignee("张三");
}
}
}
或者根据任务名称发送通知
public class TaskListListener implements TaskListener {
private ActivitiMapper activitiMapper = SpringContextHolder.getBean(ActivitiMapper.class);
@Override
public void notify(DelegateTask delegateTask) {
String taskName = delegateTask.getName();
List<String> listId = new ArrayList<>();
switch (taskName) {
case "环委办(督查科)发布任务":
List<String> inspectorId = activitiMapper.findInspectorId();
delegateTask.addCandidateUsers(inspectorId);
break;
case"牵头单位分发任务":
String leadCooperate = activitiMapper.findLeadCooperate(delegateTask.getProcessDefinitionId());
listId.add(leadCooperate);
delegateTask.addCandidateUsers(listId);
break;
case"牵头单位完成任务":
String leadCooperate1 = activitiMapper.findLeadCooperate(delegateTask.getProcessDefinitionId());
listId.add(leadCooperate1);
delegateTask.addCandidateUsers(listId);
break;
case"责任科室审核材料":
String office = activitiMapper.findOffice(delegateTask.getProcessDefinitionId());
listId.add(office);
delegateTask.addCandidateUsers(listId);
break;
case"环委办(督查科)接收材料":
List<String> inspectorId1 = activitiMapper.findInspectorId();
delegateTask.addCandidateUsers(inspectorId1);
break;
default:
break;
}
}
}
执行监听器
说明
执行侦听器意味着侦听一组有限的流程执行操作,如start、end和take,开发者可以在启动或结束之前添加一些特定的业务逻辑,执行监听器粒度较大
任务监听器只能监听UserTask,执行监听器用在流程的不同的阶段上:
-
开始事件和结束事件的开始和结束
-
经过输出顺序流
-
流程活动的开始和结束
-
流程网关的开始和结束
-
中间事假的开始和结束
bpmn设置
监听器代码
执行监听器需要实现ExecutionListener
import org.activiti.engine.delegate.ExecutionListener;
public class MyExecutionListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
// Id=_2
System.out.println("Id=" + execution.getCurrentFlowElement().getId());
// Name=StartEvent
System.out.println("Name=" + execution.getCurrentFlowElement().getName());
// EventName=start
System.out.println("EventName=" + execution.getEventName());
// ProcessDefinitionId=helloworld:1:3
System.out.println("ProcessDefinitionId=" + execution.getProcessDefinitionId());
// ProcessInstanceId=2501
System.out.println("ProcessInstanceId=" + execution.getProcessInstanceId());
}
}
事件监听器
说明
事件监听器可以监听Activiti引擎抛出的一组大型事件,这些事件级别较低,类型非常丰富,触发次数也较多。
事件监听器粒度较小,出于便于维护的目的,建议使用事件监听器,将事件监听和流程文件分开管理。
可监听事件
官方文档给出了所有可监听事件https://www.activiti.org/userguide/#eventDispatcherEventTypes
-
可监听事件的源码及翻译如下,太长折叠一下
public enum ActivitiEventType { // ENTITY :流程实例,发起流程时,从流程模板中创建实例 ENTITY_CREATED, // 创建 ENTITY_INITIALIZED, // 初始化完成(如果这个实体的创建会包含子实体的创建,这个事件会在子实体都创建/初始化完成后被触发,这是与ENTITY_CREATED的区别) ENTITY_UPDATED, // 更新 ENTITY_DELETED, // 删除 ENTITY_SUSPENDED, // 暂停(会被ProcessDefinitions, ProcessInstances 和 Tasks抛出) ENTITY_ACTIVATED, // 激活(会被ProcessDefinitions, ProcessInstances 和 Tasks抛出) // 定时器 TIMER_SCHEDULED, // 创建 TIMER_FIRED, // 触发 // 作业 JOB_CANCELED, // 取消 JOB_EXECUTION_SUCCESS, // 执行成功 JOB_EXECUTION_FAILURE, // 执行失败 JOB_RETRIES_DECREMENTED, // 重试减少(因为作业执行失败,导致重试次数减少) CUSTOM, // 自定义 // 引擎 ENGINE_CREATED, // 创建 ENGINE_CLOSED, // 关闭 // 流程节点 ACTIVITY_STARTED, // 开始 ACTIVITY_COMPLETED, // 完成 ACTIVITY_CANCELLED, // 取消 ACTIVITY_SIGNALED, // 收到了一个信号 ACTIVITY_COMPENSATE, // 将要被补偿 ACTIVITY_MESSAGE_SENT, // 消息发送 ACTIVITY_MESSAGE_WAITING, // 消息等待 ACTIVITY_MESSAGE_RECEIVED, // 消息接收 ACTIVITY_ERROR_RECEIVED, // 接收失败 // 流程历史 HISTORIC_ACTIVITY_INSTANCE_CREATED, // 创建 HISTORIC_ACTIVITY_INSTANCE_ENDED, // 结束 // 队列流程 SEQUENCEFLOW_TAKEN, // 已采取 UNCAUGHT_BPMN_ERROR, // 未获取到bpmn 异常 // 变量 VARIABLE_CREATED, // 创建 VARIABLE_UPDATED, // 更新 VARIABLE_DELETED, // 删除 // 任务 TASK_CREATED, // 创建(它位于ENTITY_CREATE事件之后。当任务是由流程创建时,这个事件会在TaskListener执行之前被执行) TASK_ASSIGNED, // 分配 TASK_COMPLETED, // 完成(它会在ENTITY_DELETE事件之前触发。当任务是流程一部分时,事件会在流程继续运行之前, 后续事件将是ACTIVITY_COMPLETE,对应着完成任务的节点) // 进程 PROCESS_STARTED, // 开始 PROCESS_COMPLETED, // 完成(在最后一个节点的ACTIVITY_COMPLETED事件之后触发。 当流程到达的状态,没有任何后续连线时, 流程就会结束。) PROCESS_COMPLETED_WITH_ERROR_END_EVENT, // 异常结束 PROCESS_CANCELLED, // 取消 HISTORIC_PROCESS_INSTANCE_CREATED, // 流程实例创建 HISTORIC_PROCESS_INSTANCE_ENDED, // 流程实例创建 // 成员 MEMBERSHIP_CREATED, // 用户被添加到一个组里 MEMBERSHIP_DELETED, // 用户被从一个组中删除 MEMBERSHIPS_DELETED; // 所有成员被从一个组中删除 // other code ... }
全局事件监听器
实现 ActivitiEventListener 接口
实现 ActivitiEventListener 接口,重写 void onEvent(ActivitiEvent event) 方法
public class ActivitiTaskEventListener implements ActivitiEventListener {
@Override
public void onEvent(ActivitiEvent activitiEvent) {
if (!StringUtils.hasText(activitiEvent.getProcessInstanceId())) {
return;
}
processEngine = ProcessEngines.getDefaultProcessEngine();
// 流程实例
ProcessInstance processInstance = processEngine.getRuntimeService().createProcessInstanceQuery()
.processInstanceId(activitiEvent.getProcessInstanceId()).singleResult();
if (processInstance == null) {
return;
}
List<ActivitiTaskLog> taskLogList = new ArrayList<>();
switch (activitiEvent.getType()) {
// 任务执行后
case TASK_COMPLETED:
// 任务被处理,给创建人, 下一个任务的候选人
List<ActivitiTaskLog> taskCompletedLogs = this.taskCompleted(processInstance, activitiEvent.getExecutionId());
if (!CollectionUtils.isEmpty(taskCompletedLogs)) {
taskLogList.addAll(taskCompletedLogs);
}
break;
case PROCESS_COMPLETED:
// 流程完成,给创建人,协助人,抄送人发通知
List<ActivitiTaskLog> processCompletedLogs = this.processCompleted(processInstance);
if (!CollectionUtils.isEmpty(processCompletedLogs)) {
taskLogList.addAll(processCompletedLogs);
}
break;
default:
}
//执行日志操作
if (!CollectionUtils.isEmpty(taskLogList)) {
activitiTaskLogService.createBatch(taskLogList);
}
}
}
新增配置类
继承 DefaultActivityBehaviorFactoryMappingConfigurer
类(或实现 ProcessEngineConfigurationConfigurer
接口)并重写 configura()
方法, 给 SpringProcessEngineConfiguration
属性添加自定义的监听器实现类
@Configuration
public class ActivitiConfiguration extends DefaultActivityBehaviorFactoryMappingConfigurer {
@Autowired
ActivitiTaskLogService activitiTaskLogService;
@Autowired
UserService userService;
public ActivitiConfiguration(VariablesMappingProvider variablesMappingProvider, ProcessVariablesInitiator processVariablesInitiator,
EventSubscriptionPayloadMappingProvider eventSubscriptionPayloadMappingProvider) {
super(variablesMappingProvider, processVariablesInitiator, eventSubscriptionPayloadMappingProvider);
}
@Override
public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
super.configure(springProcessEngineConfiguration);
springProcessEngineConfiguration.setEventListeners(
Collections.singletonList(new ActivitiTaskEventListener(activitiTaskLogService, userService)));
}
}
运行时状态监听器(推荐)
不需要实现 ActivitiEventlistener 接口,也不需要继承 DefaultActivityBehaviorFactoryMappingConfigurer 类或实现 ProcessEngineConfigurationConfigurer 接口,只需要注册相关事件的监听器即可
@Configuration
public class ActivitiConfiguration {
private final RuntimeService runtimeService;
private final ActRuTaskLogService actRuTaskLogService;
public ActivitiConfiguration(RuntimeService runtimeService, ActRuTaskLogService actRuTaskLogService) {
this.runtimeService = runtimeService;
this.actRuTaskLogService = actRuTaskLogService;
}
@Bean
public TaskRuntimeEventListener<TaskAssignedEvent> taskAssignedListener() {
return taskAssigned -> {
ExecutionEntity execution = (ExecutionEntity) runtimeService.createProcessInstanceQuery()
.processInstanceId(taskAssigned.getProcessInstanceId()).singleResult();
String startUserId = execution.getStartUserId();
String fileProcInstId = this.fileProcInstId(execution);
// 排除发起申请的任务,给 assignee 发消息
if (!taskAssigned.getEntity().getAssignee().equals(startUserId)) {
Task task = taskAssigned.getEntity();
ActRuTaskLog taskLog = new ActRuTaskLog(task.getProcessInstanceId(), task.getId(),
taskAssigned.getEntity().getAssignee(), String.format(NotifyConstants.PENDING_WARN,
this.userName(startUserId), this.processType(fileProcInstId), this.projName(execution)),
NotifyTypeConstants.CANDIDATE);
actRuTaskLogService.create(taskLog);
}
};
}
@Bean
public TaskRuntimeEventListener<TaskCompletedEvent> taskCompletedListener() {
return taskCompleted -> {
ExecutionEntity execution = (ExecutionEntity) runtimeService.createProcessInstanceQuery()
.processInstanceId(taskCompleted.getProcessInstanceId()).singleResult();
String startUserId = execution.getStartUserId();
String fileProcInstId = this.fileProcInstId(execution);
Task task = taskCompleted.getEntity();
// 发起审批,给抄送人、协助人发消息
if (!taskCompleted.getEntity().getAssignee().equals(startUserId)) {
// 任务所有人
String owner = taskCompleted.getEntity().getOwner();
ActRuTaskLog taskLog = new ActRuTaskLog(task.getProcessInstanceId(), task.getId(),
this.userName(owner), String.format(NotifyConstants.PENDING_WARN,
this.userName(startUserId), this.processType(fileProcInstId), this.projName(execution)),
NotifyTypeConstants.CANDIDATE);
actRuTaskLogService.create(taskLog);
} else {
// 给发起人发送任务处理结果的通知
ActRuTaskLog taskLog = new ActRuTaskLog(task.getProcessInstanceId(), task.getId(),
taskCompleted.getEntity().getAssignee(), String.format(NotifyConstants.PENDING,
this.userName(startUserId), this.processType(fileProcInstId), this.projName(execution),
this.userName(task.getAssignee()), ""), NotifyTypeConstants.PENDING);
actRuTaskLogService.create(taskLog);
}
};
}
@Bean
public TaskCandidateEventListener<TaskCandidateUserAddedEvent> taskCandidateUserEventListener() {
return taskCandidateEvent -> log.info(">>> Task Candidate User Add: '"
+ taskCandidateEvent.getEntity().toString());
}
@Bean
public TaskCandidateEventListener<TaskCandidateGroupAddedEvent> taskCandidateGroupEventListener() {
return taskCandidateEvent -> log.info(">>> Task Candidate Group Add: '"
+ taskCandidateEvent.getEntity().toString());
}
@Bean
public ProcessRuntimeEventListener<ProcessCompletedEvent> processCompletedEventListener() {
return processCompletedEvent -> log.info("===>>> Process Completed: '"
+ processCompletedEvent.getEntity().toString());
}
/**
* 获取流程表单名
*
* @param executionEntity 执行对象
* @return 表单名
*/
private String projName(ExecutionEntity executionEntity) {
Object processInstanceName = executionEntity.getVariable("projName");
return null == processInstanceName ? "" : processInstanceName.toString();
}
/**
* 获取流程文件ID
*
* @param executionEntity 执行对象
* @return 文件ID
*/
private String fileProcInstId(ExecutionEntity executionEntity) {
Object fileProcInstId = executionEntity.getVariable("fileProcInstId");
return fileProcInstId == null ? "" : fileProcInstId.toString();
}
/**
* 审批类型
*
* @param fileProcInstId 文件ID
* @return 类型
*/
private String processType(String fileProcInstId) {
return StringUtils.hasText(fileProcInstId) ? "用印" : "合同";
}
/**
* 获取姓名
*
* @param userId 用户ID
* @return 用户姓名
*/
private String userName(String userId) {
return userId + "操作人";
}
}
两种方案对比
更推荐使用第二种,因为第一种方案中,ActivitiEvent 是超类,而一些属性是直接获取不到的,如果要获取,就需要进行向下强转,而每种事件的类型,实现子类又是不同的,需要做很多的判断,但是第二种方法就不用,因为当前监听器中的对象就是改类型对应的事件的相关对象,能够直接获取到相关的变量和信息。