本节继续对activiti流程引擎的配置进行学习
首先在activiti_eventlog.cfg.xml中配置eventlog属性为true
编写一个eventlog测试代码 ConfigEventLogTest.java
import org.activiti.engine.event.EventLogEntry;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/07
*/
public class ConfigEventLogTest {
private static final Logger logger = LoggerFactory.getLogger(ConfigEventLogTest.class);
//这里已经包含了流程引擎的创建
@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti_eventlog.cfg.xml");
@Test
@Deployment(resources = {"./my-process.bpmn20.xml"})
public void configMDCTest1() {
ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
List list = activitiRule.getTaskService().createTaskQuery().list();
activitiRule.getTaskService().complete(list.get(0).getId());
List eventLogEntries = activitiRule.getManagementService()
.getEventLogEntriesByProcessInstanceId(processInstance.getProcessInstanceId());
for (EventLogEntry eventLogEntry : eventLogEntries) {
logger.info("eventlog.type= {}, eventlog.data ={}", eventLogEntry.getType().toString(), new String( eventLogEntry.getData()) );
}
logger.info("eventlogEntryies size={}", eventLogEntries.size());
}
}
执行日志情况如下:
源码查看
在ProcessEngineConfigurationImpl.java类中有创建时间监听器的代码
这里创建了一个新的EventLogger对象,这个对象是实现了一个监听器
在这个类的初始化函数里面,设置了各种事件的监听处理类
另外,当监听到事件后,调用 onEvent方法:
有三种类型的监听器
eventListeners:监听所有事件派发的通知
typedEventListeners:监听指定事件类型的通知
activiti:eventListener:只监听特定流程定义的事件
相关api对象:
ActivitiEvent 事件对象
ActivitiEventListener 监听器
ActivitiEventType 事件类型,是枚举类型,监听器针对具体的类型进行操作
首先在配置文件中添加监听的配置
生成一个事件监听类的具体实现ProcessEventListener.java
package com.study.activiti.event;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/09
*/
public class ProcessEventListener implements ActivitiEventListener {
private static final Logger logger = LoggerFactory.getLogger(ProcessEventListener.class);
@Override
public void onEvent(ActivitiEvent event) {
ActivitiEventType type = event.getType();
if( ActivitiEventType.PROCESS_STARTED.equals( type)){
logger.info("流程启动 {} \t 流程实例id={}", type, event.getProcessInstanceId());
}
if( ActivitiEventType.PROCESS_COMPLETED.equals( type)){
logger.info("流程启动 {} \t 流程实例id={}", type, event.getProcessInstanceId());
}
}
@Override
public boolean isFailOnException() {
return false;
}
}
创建测试代码ConfigEventListenerTest
import com.study.activiti.event.CustomEventListener;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiActivityEventImpl;
import org.activiti.engine.event.EventLogEntry;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/07
*/
public class ConfigEventListenerTest {
private static final Logger logger = LoggerFactory.getLogger(ConfigEventListenerTest.class);
//这里已经包含了流程引擎的创建
@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti_eventListener.cfg.xml");
@Test
@Deployment(resources = {"./my-process.bpmn20.xml"})
public void test1() {
ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
List list = activitiRule.getTaskService().createTaskQuery().list();
activitiRule.getTaskService().complete(list.get(0).getId());
List eventLogEntries = activitiRule.getManagementService()
.getEventLogEntriesByProcessInstanceId(processInstance.getProcessInstanceId());
for (EventLogEntry eventLogEntry : eventLogEntries) {
logger.info("eventlog.type= {}, eventlog.data ={}", eventLogEntry.getType().toString(), new String( eventLogEntry.getData()) );
}
logger.info("eventlogEntryies size={}", eventLogEntries.size());
}
}
执行日志中会打印出来刚才监听实现中的打印信息
下面在上面基础上添加eventTpyeListener的功能。这个功能是通过监听指定类型的事件作出响应
创建针对指定类型的事件监听类ProcessEventTypeListener.java
package com.study.activiti.event;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/09
*/
public class ProcessEventTypeListener implements ActivitiEventListener {
private static final Logger logger = LoggerFactory.getLogger(ProcessEventTypeListener.class);
@Override
public void onEvent(ActivitiEvent event) {
ActivitiEventType type = event.getType();
if( ActivitiEventType.ACTIVITY_COMPLETED .equals( type)){
logger.info("活动结束 {} \t 流程实例id={}", type, event.getProcessInstanceId());
}
}
@Override
public boolean isFailOnException() {
return false;
}
}
在配置文件中添加对应的配置内容
执行的时候,我们可以看到在原来的监听基础上,我们还多了事件类型的监听处理
我们还可以进行用户自定义的监听,需要3个步骤:
首先添加一个事件监听的自定义处理
流程事件处理中dispatch一个自定义事件
在配置文件中添加这个事件的处理配置
下面我们看一下上面的三个步骤具体实现
package com.study.activiti.event;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/09
*/
public class CustomEventListener implements ActivitiEventListener {
private static final Logger logger = LoggerFactory.getLogger(CustomEventListener.class);
@Override
public void onEvent(ActivitiEvent event) {
ActivitiEventType type = event.getType();
if( ActivitiEventType.CUSTOM.equals( type)){
logger.info("监听到用户事件 {} \t 流程实例id={}", type, event.getProcessInstanceId());
}
}
@Override
public boolean isFailOnException() {
return false;
}
}
2 修改流程处理中内容,在测试代码中添加下面语句
3、修改配置文件
最后我们看一下执行结果
在下列位置创建一个拦截器
这个类的代码如下:
package com.study.activiti.interceptor;
import org.activiti.engine.impl.interceptor.AbstractCommandInterceptor;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/13
*/
public class DurationCommandInterceptor extends AbstractCommandInterceptor {
private static final Logger logger = LoggerFactory.getLogger(DurationCommandInterceptor.class);
@Override
public T execute(CommandConfig config, Command command) {
long start = System.currentTimeMillis();
try{
return this.getNext().execute(config, command);
}finally{
long duration = System.currentTimeMillis()- start;
logger.info("{} 执行时长 {} 毫秒", command.getClass().getSimpleName(), duration);
}
}
}
创建一个测试类ConfigInterceptorTest.java
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiActivityEventImpl;
import org.activiti.engine.event.EventLogEntry;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/07
*/
public class ConfigInterceptorTest {
private static final Logger logger = LoggerFactory.getLogger(ConfigInterceptorTest.class);
//这里已经包含了流程引擎的创建
@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti_interceptor.cfg.xml");
@Test
@Deployment(resources = {"./my-process.bpmn20.xml"})
public void test1() {
ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
List list = activitiRule.getTaskService().createTaskQuery().list();
activitiRule.getTaskService().complete(list.get(0).getId());
}
}
下图为执行日志
作业执行器的相关配置有:
作业执行器的配置
配置自定义线程池
流程定义定时启动配置
一些重要的配置参数:
asyncExecutorActivate 激活作业执行器,asyncExecutorXXX 异步执行配置,asyncExecutor, 一步执行器器bean
自定义线程池 ExecutorService: corePoolSize核心线程数 maxPoolSize最大线程数
QueueCapacity:堵塞队列大小
作业执行定时开始事件(Timer Start Event):
timeDate, 指定启动时间
timeDuration: 指定持续时间间隔后执行
timeCycle:指定周期执行
下面我们实现一个基于job的流程,并进行监听,打印job执行的相关信息
首先创建一个bpmc的xml文件
R5/PT10S
创建一个只监听job的监听器:JobEventListener.java
package com.study.activiti.event;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/09
*/
public class JobEventListener implements ActivitiEventListener {
private static final Logger logger = LoggerFactory.getLogger(JobEventListener.class);
@Override
public void onEvent(ActivitiEvent event) {
ActivitiEventType type = event.getType();
String name = type.name();
if( name.startsWith("TIMER") || name.startsWith("JOB")){
logger.info("监听到用户事件 {} \t 流程实例id={}", type, event.getProcessInstanceId());
}
}
@Override
public boolean isFailOnException() {
return false;
}
}
创建对应的配置文件activiti-job.cfg.xml
创建一个测视类,主要是打印定时job启动后的任务执行信息,任务执行信息是通过监听器来传递的。
import org.activiti.engine.event.EventLogEntry;
import org.activiti.engine.runtime.Job;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/07
*/
public class ConfigJobTest {
private static final Logger logger = LoggerFactory.getLogger(ConfigJobTest.class);
//这里已经包含了流程引擎的创建
@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti_job.cfg.xml");
@Test
@Deployment(resources = {"./my-process-job.bpmn20.xml"})
public void Test1() throws InterruptedException {
logger.info("start");
List jobs = activitiRule.getManagementService().createTimerJobQuery().listPage(0, 100);
for (Job job:jobs){
logger.info("定时任务={}, 默认重试次数={}", job, job.getRetries());
}
logger.info("jobs.size={}", jobs.size());
Thread.sleep(1000*100);
logger.info("end");
}
}
在监听器中,我们代码指定了如果事件的类似为TIMER或者JOB的需要进行处理(打印)
集成spring需要添加pom依赖activi-spring,基于Spring的默认配置是activiti-context.xml,核心服务需要注入Spring容器。如果需要单元测试,还需要在pom中添加spring-test,辅助测试Rule:ActivitiRule。下面通过一个demo来演示如何进行spring集成。思路是:先集成spring,然后通过自定义个bean,注入到流程的某个环节中。
创建一个配置文件activiti-context.xml,内容如下:
创建一个测试类可以进行spring集成测试
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/07
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:activiti_context.xml"})
public class ConfigSpringTest {
private static final Logger logger = LoggerFactory.getLogger(ConfigSpringTest.class);
//这里自动装配配置文件中的activitirule
@Rule
@Autowired
public ActivitiRule activitiRule;
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Test
@Deployment(resources = {"./my-process.bpmn20.xml"})
public void test() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("my-process");
;
assertNotNull(processInstance);
List list = taskService.createTaskQuery().list();
for (Task task : list
) {
taskService.complete(task.getId());
}
}
}
下图是执行日志的情况:
注意一下,spring需要junit的版本在4.12以上,否则会报告如下错误。
下面设计一个自定义的bean,并注入到流程执行过程中。在流程配置文件中添加一个节点,并且这个节点执行这个bean的sayHello方法。创建一个类HelloBean
package com.study.activiti.delegate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Describe:
*
* @author cwqsolo
* @date 2020/01/29
*/
public class HelloBean {
private static final Logger logger = LoggerFactory.getLogger(HelloBean.class);
public void sayHello(){
logger.info("Hello world");
}
}
在配置文件activiti_context.xml里配置bean的地方,加上这个bean的配置
下面创建一个新的流程定义文件,在某个环节中配置上我们的自定义类
执行我们的测试类,在打印的信息中可以看到下面内容: