1.事件及監聽器原理
當流程引擎啟動的時候,我們定義的監聽器,就已經注冊在一個事件類型上面。
注冊的方式有多種,它可以注冊在所有的事件類型上面、也可以注冊在指定的幾個事件類型上面,這樣引擎啟動的時候就已經完成了監聽器與事件的注冊。
那么在流程運行的過程中,會有這樣一個環節:
首先我們有一個事件源與一個事件類型的關系,比如說,我創建一個流程引擎,這個事件源就是流程引擎對象。類型就是 把它創建了。也就是說流程引擎創建過程,
觸發出我們的事件,這個事件對象,也就是流程引擎被創建。當這個事件被分發出來的時候,或者發布出來的時候,也就會被監聽器監聽這個事件。
當然,我們可以在一個事件上注冊多個監聽器,當事件發生的時候,監聽器會一次執行自己的方法,這樣就可以讓一個事件在發生變化的時候,監聽器直接或者間接的感受到它的變化。
綜上,這個過程中,我們需要:
首先有一個事件對象
在這個事件對象上綁定或注冊監聽器和事件類型
監聽器會觸發的方法。
監聽器配置方式:
Activiti的事件監聽(與監聽原理圖相對應):
Activiti的事件監聽:
在實現監聽器的過程中,大多監聽器都會對事件類型做一個判斷。監聽器只去判斷幾個事件類型,類型不符的直接忽略。
(ps:事件類型里還支持自定義類型。)
創建一個監聽器ProcessEventListener:
public class ProcessEventListener implements ActivitiEventListener { private static final Logger LOGGER = LoggerFactory.getLogger(ProcessEventListener.class); //簡單的完成一下監聽器的效果 @Override public void onEvent(ActivitiEvent event) { ActivitiEventType eventType = event.getType(); if (ActivitiEventType.PROCESS_STARTED.equals(eventType)){ LOGGER.info("流程啟動 {} \t {}",eventType,event.getProcessInstanceId()); }else if (ActivitiEventType.PROCESS_COMPLETED.equals(eventType)){ LOGGER.info("流程結束 {} \t {}",eventType,event.getProcessInstanceId()); } } @Override public boolean isFailOnException() { return false; } }
注冊監聽配置文件:
activiti_eventListener.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration"> <!-- 給引擎設置自定義的commandInvoker --> <!--<property name="commandInvoker" ref="commandInvoker" />--> <property name="eventListeners"> <list> <!-- 配置上監聽器 --> <bean class="com.yy.avtiviti.helloworld.event.ProcessEventListener"/> </list> </property> </bean> <bean id="commandInvoker" class="com.yy.avtiviti.helloworld.intercept.MDCCommandInvoker"/> </beans>
測試類:
public class configEventListenerTest { private static final Logger LOGGER = LoggerFactory.getLogger(configTest.class); @Rule public ActivitiRule activitiRule = new ActivitiRule("activiti_eventListener.cfg.xml");//傳入自定義的mdc配置文件 @Test @Deployment(resources = {"my-process.bpmn20.xml"})//流程定義文件 public void test() { ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process"); Task task = activitiRule.getTaskService().createTaskQuery().singleResult(); activitiRule.getTaskService().complete(task.getId()); //想遍歷EventLog數據,需要用到新的service(ManagementService) //狀態流轉 LOGGER.info("-----------狀態流轉----------"); List<EventLogEntry> eventLogEntries = activitiRule .getManagementService() .getEventLogEntriesByProcessInstanceId( processInstance.getProcessDefinitionId()); for (EventLogEntry eventLogEntry : eventLogEntries) { LOGGER.info("eventLog.type = {},eventLog.data = {}",eventLogEntry.getType(),new String(eventLogEntry.getData())); } LOGGER.info("eventLogEntries = {}",eventLogEntries.size()); }
測試結果如下:
第二種注冊監聽的配置方法,只用改配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration"> <!-- 給引擎設置自定義的commandInvoker --> <!--<property name="commandInvoker" ref="commandInvoker" />--> <!--<property name="eventListeners"> <list> <!– 配置上監聽器 –> <bean class="com.yy.avtiviti.helloworld.event.ProcessEventListener"/> </list> </property>--> <property name="typedEventListeners"> <map> <!-- 只監聽流程啟動這個事件 --> <entry key="PROCESS_STARTED"> <list> <bean class="com.yy.avtiviti.helloworld.event.ProcessEventListener"/> </list> </entry> </map> </property> </bean> <bean id="commandInvoker" class="com.yy.avtiviti.helloworld.intercept.MDCCommandInvoker"/> </beans>
測試結果如下圖,與預期相符,只監聽了流程的啟動。