本文集体博客地址:Activiti7事件监听 (leafage.top)

良久没有记录笔记了,最近做了一些对于工作流的事件,记录一下应用activiti 7的一些教训。

需要:

  1. 在流程发动和流程操作的过程中,给相干人员发送流程审批的告诉揭示;
  2. 不要在配置流程时手动增加,不能侵入到流程操作的过程,影响流程执行;

<mark>这个怎么动手呢?没搞过activiti,activiti7 的官网文档写的跟屎一样烂,感觉好难呀</mark>...

文档参考性不高,那就试试看官网的示例,找到 activiti 的 repository ,有一个示例 module 叫 activiti-examples,<mark>这里的示例不能间接跑,只能看</mark>,要想跑起来,就复制,粘贴,放到本人的我的项目中。跑题了,说会主题。。。

activiti中的几个关联的重要的类或接口:

  1. activiti 中每个流程信息是通过 ProcessInstance 形容,它有这么几个状态:created、started、completed、cancelled、resumed、updated、suspended,与之对应的相干事件形容类是:ProcessCreatedEvent、ProcessStartedEvent、ProcessCompletedEvent、ProcessCancelledEvent、ProcessResumedEvent、ProcessUpdatedEvent、ProcessSuspendedEvent等。

  2. 每个流程节点在 activiti 中 通过 Task 来形容,它有这么几个个状态:created、assigned、completed、updated、cancelled、suspended等,与之对应的相干事件形容类是:TaskCreatedEvent、TaskAssignedEvent、TaskCompletedEvent、TaskUpdatedEvent、TaskCancelledEvent、TaskSuspendedEvent等。

如何配置监听器?

1. 全局事件监听器:

波及到两个类\接口,全局事件监听器 ActivitiEventListener 和 ProcessEngineConfigurationConfigurer(有一个默认的实现类:DefaultActivityBehaviorFactoryMappingConfigurer)

ActitiviEventListener 接口有一个 void onEvent(ActivitiEvent activitiEvent) 办法,即在事件状态发生变化时,能够产生的动作都会在这个办法中进行。其源码如下:

/** * Describes a class that listens for {@link ActivitiEvent}s dispatched by the engine. *  */public interface ActivitiEventListener {  void onEvent(ActivitiEvent event);  boolean isFailOnException();}

ActivitiEvent 蕴含了流程的定义ID,示例ID,执行ID,和事件类型信息,源码如下:

public interface ActivitiEvent {  ActivitiEventType getType();  String getExecutionId();  String getProcessInstanceId();  String getProcessDefinitionId();}

其事件类型包含很多,源码如下:

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 ...}

ProcessEngineConfigurationConfigurer 中的 void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) 办法能够增加自定义的事件监听器,这个监听器作用域为整个流程过程。其源码如下:

public class DefaultActivityBehaviorFactoryMappingConfigurer implements ProcessEngineConfigurationConfigurer {    private VariablesMappingProvider variablesMappingProvider;    private ProcessVariablesInitiator processVariablesInitiator;        private final EventSubscriptionPayloadMappingProvider eventSubscriptionPayloadMappingProvider;    public DefaultActivityBehaviorFactoryMappingConfigurer(VariablesMappingProvider variablesMappingProvider,                                                           ProcessVariablesInitiator processVariablesInitiator,                                                           EventSubscriptionPayloadMappingProvider eventSubscriptionPayloadMappingProvider){        this.variablesMappingProvider = variablesMappingProvider;        this.processVariablesInitiator = processVariablesInitiator;        this.eventSubscriptionPayloadMappingProvider = eventSubscriptionPayloadMappingProvider;    }    @Override    public void configure(SpringProcessEngineConfiguration processEngineConfiguration){        processEngineConfiguration.setEventSubscriptionPayloadMappingProvider(eventSubscriptionPayloadMappingProvider);        processEngineConfiguration.setActivityBehaviorFactory(new MappingAwareActivityBehaviorFactory(variablesMappingProvider,                                                                                                      processVariablesInitiator));    }}

如何来监听事件?

  1. 实现 ActivitiEventListener 接口,重写 void onEvent(ActivitiEvent event) 办法;
  2. 新增配置类,继承 DefaultActivityBehaviorFactoryMappingConfigurer 类(或实现 ProcessEngineConfigurationConfigurer 接口)并重写 configura() 办法, 给 SpringProcessEngineConfiguration 属性增加自定义的监听器实现类;

示例如下:

@Configurationpublic 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)));    }}
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);        }    }}

2. 运行时状态监听器:

在实例中有一个 activiti-api-basic-process-example 和 activiti-api-basic-task-example 两个示例工程,展现了如何进行配置运行时的process和task的监听。

activiti-api-basic-process-example 中,流程监听示例:

@Beanpublic ProcessRuntimeEventListener<ProcessCompletedEvent> processCompletedListener() {    return processCompleted -> logger.info(">>> Process Completed: '"            + processCompleted.getEntity().getName() +            "' We can send a notification to the initiator: " + processCompleted.getEntity().getInitiator());}

activiti-api-basic-task-example 中,工作监听示例:

@Beanpublic TaskRuntimeEventListener<TaskAssignedEvent> taskAssignedListener() {    return taskAssigned -> logger.info(">>> Task Assigned: '"            + taskAssigned.getEntity().getName() +            "' We can send a notification to the assginee: " + taskAssigned.getEntity().getAssignee());}@Beanpublic TaskRuntimeEventListener<TaskCompletedEvent> taskCompletedListener() {    return taskCompleted -> logger.info(">>> Task Completed: '"            + taskCompleted.getEntity().getName() +            "' We can send a notification to the owner: " + taskCompleted.getEntity().getOwner());}

参照示例,咱们能够进行自定义的流程中事件监听的配置,这种形式,不须要实现 ActivitiEventlistener 接口,也不须要继承 DefaultActivityBehaviorFactoryMappingConfigurer 类或实现 ProcessEngineConfigurationConfigurer 接口,只须要注册相干事件的监听器即可。示例如下:

@Configurationpublic 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 是超类,而一些属性是间接获取不到的,如果要获取,就须要进行向下强转,而每种事件的类型,实现子类又是不同的,须要做很多的判断,然而第二种办法就不必,因为以后监听器中的对象就是改类型对应的事件的相干对象,可能间接获取到相干的变量和信息。