Activiti6.0工作流引擎学习(二) -- 引擎配置
Activiti6.0工作流引擎学习(二) – 引擎配置
1.Activiti流程引擎配置涉及的类

1.1 流程引擎配置类的作用
- ProcessEngineConfiguration
- 查找并解析xml配置文件activiti.cfg.xml
- 提供多个静态方法创建配置对象

- 实现几个基于不同场景场景的子类,配置方式非常的灵活

1.2 部分子类的使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Test public void testConfig1(){ ProcessEngineConfiguration engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault(); log.info("engine ={}",engine); } @Test public void testConfig2(){ ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration(); log.info("configuration = {}",configuration); }
|
2.数据库配置
2.1 缺省配置默认,使用H2内存数据库
2.2 配置JDBC属性,使用mybatis提供的链接池

2.3 配置DataSource,可自选第三方实现
- Druid 为监控而生的数据库连接池 来自阿里


- Dbcp 老牌数据源连接池,稳定可靠,Tomcat自带
- HikariCP 来自日本的极速数据源连接池,Spring默选
2.4 数据库更新策略
- 配置databaseSchemaUpdate
- false:启动时检查数据库版本,发生不匹配抛异常
- true: 启动时自动检查并甭信数据库表,不存在会创建
- create-drop: 启动时创建数据库表结构,结束时删除表结构
2.5 数据库配置编码
2.5.1 使用默认的配置文件创建流程引擎
activiti.cfg.xml
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?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.StandaloneProcessEngineConfiguration">
</bean>
</beans>
|
1 2 3 4 5 6 7 8
| public void test1(){ ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault(); log.info("configuration = {}",configuration); ProcessEngine processEngine = configuration.buildProcessEngine(); log.info("获取流程引擎 = [{}]",processEngine.getName()); processEngine.close(); }
|
2.5.2 使用druid数据源
activiti_druid.cfg.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <?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.StandaloneProcessEngineConfiguration">
<property name="databaseSchemaUpdate" value="drop-create" /> <property name="dataSource" ref="dataSource"/> <property name="history" value="full" /> <property name="dbHistoryUsed" value="true"/> <property name="dbIdentityUsed" value="true"/> </bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="jdbc:mysql://111.229.203.5:3306/activiti?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true"/> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="username" value="weaver"/> <property name="password" value="192612"/> <property name="initialSize" value="1"/> <property name="maxActive" value="10"/> <property name="filters" value="stat,slf4j"/> </bean>
</beans>
|
1 2 3 4 5 6 7 8
| public void test2(){ ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti_druid.cfg.xml"); log.info("configuration = {}",configuration); ProcessEngine processEngine = configuration.buildProcessEngine(); log.info("获取流程引擎 = [{}]",processEngine.getName()); processEngine.close(); }
|
3.日志记录配置
3.1 日志组件的关系及MDC

3.1.1 配置开启MDC(Mapped Diagnostic Contexts)
- 默认没有开启,需要手动设置
LogMDC.setMDCEnable(true)
- 配置logback.xml日志模版
%X{mdcProcessInstanceID}
- 流程只有在执行过程出现异常才会记录MDC信息
3.2 配置历史记录级别(HistoryLevel)
3.2.1 配置HistoryLevel
- none:不记录历史流程,性能高,流程结束后不可读取
- activiti:归档流程实例和活动实例,流程变量不同步
- addit:默认值,在activiti基础上同步变量值,保存表单属性
- full:性能较差,记录所有实例和变量细节变化
3.3 配置基于db的事件日志(Event logging)
3.3.1 配置Event Logging
- 试验性的事件记录机制,性能影响较大
- 开启默认记录所有数据的变化过程,表记录快速增长
- 日志内容json格式,建议存入mongoDB、Elastic Search
3.4 日志记录 mdc
4 历史记录配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| package com.atguigu.test;
import com.google.common.collect.Maps; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.history.HistoricDetail; import org.activiti.engine.runtime.Execution; 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 java.util.Map;
public class TestMDC { private static Logger log = LoggerFactory.getLogger(TestMDC.class); @Rule public ActivitiRule activitiRule = new ActivitiRule(); @Test @Deployment(resources = {"my-process.bpmn20.xml"}) public void test(){ Map<String,Object> params = Maps.newHashMap(); params.put("keyStart1","value1"); params.put("keyStart2","value2"); ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process",params); List<Execution> executions = activitiRule.getRuntimeService().createExecutionQuery().listPage(0, 100); for (Execution execution : executions) { log.info("executions {}",executions); } log.info("executions size = {}",executions.size()); String id = executions.iterator().next().getId(); activitiRule.getRuntimeService().setVariable(id,"keyStart1","value1_"); Task task = activitiRule.getTaskService().createTaskQuery().singleResult(); Map<String,String> properties = Maps.newHashMap(); properties.put("formkey1","valuef1"); properties.put("formkey2","valuef2"); activitiRule.getFormService().submitTaskFormData(task.getId(),properties); List<HistoricActivityInstance> historicActivityInstances = activitiRule.getHistoryService().createHistoricActivityInstanceQuery().listPage(0, 100); for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { log.info("historicActivityInstances = {}",historicActivityInstances); } log.info("historicActivityInstances size = {}",historicActivityInstances.size());
List<HistoricDetail> historicDetails = activitiRule.getHistoryService().createHistoricDetailQuery().listPage(0, 100); for (HistoricDetail historicDetail : historicDetails) { log.info("historicDetail [{}]",historicDetail); } log.info("historicDetail size = [{}]", historicDetails.size()); } }
|
5.事件处理及监听配置-eventlog
5.1 事件及监听器原理

5.2 监听器的配置方式
- 配置Listener
- eventListeners:监听所有事件派发通知
- typedEventListeners:监听指定事件类型的通知
- activiti:eventListener:只监听特定流程定义的事件

5.3 Activiti事件监听
5.3.1 相关API
- ActivitiEvent:事件对象
- ActivitiEventListener:监听器
- ActivitiEventType:事件类型
5.4 ActivitiEventListener监听器的使用
- 配置文件中增加对应的配置
1 2 3 4 5 6 7
| <property name="eventListeners"> <list> <bean class="com.atguigu.event.ProcessEventListener"/> </list> </property>
|
- 创建一个实体类,实现
ActivitiEventListener
类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.atguigu.event;
import org.activiti.bpmn.model.ActivitiListener; 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;
public class ProcessEventListener implements ActivitiEventListener { private static Logger log = LoggerFactory.getLogger(ProcessEventListener.class); @Override public void onEvent(ActivitiEvent event) { ActivitiEventType type = event.getType(); if(ActivitiEventType.PROCESS_STARTED.equals(type)){ log.info("流程启动 {}",event.getProcessInstanceId()); }else if(ActivitiEventType.PROCESS_COMPLETED.equals(type)){ log.info("流程结束"); } }
@Override public boolean isFailOnException() { return false; } }
|
5.5 TypedEventListeners监听器的使用
- 配置文件
1 2 3 4 5 6 7 8 9 10
| <property name="typedEventListeners"> <map> <entry key="PROCESS_STARTED"> <list> <bean class="com.atguigu.event.ProcessEventListener"/> </list> </entry> </map> </property>
|
- 流程监听实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.atguigu.event;
import org.activiti.bpmn.model.ActivitiListener; 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;
public class ProcessEventListener implements ActivitiEventListener { private static Logger log = LoggerFactory.getLogger(ProcessEventListener.class); @Override public void onEvent(ActivitiEvent event) { ActivitiEventType type = event.getType(); if(ActivitiEventType.PROCESS_STARTED.equals(type)){ log.info("流程启动 {}",event.getProcessInstanceId()); }else if(ActivitiEventType.PROCESS_COMPLETED.equals(type)){ log.info("流程结束"); } }
@Override public boolean isFailOnException() { return false; } }
|
6. 命令拦截器配置–command
6.1 命令模式与责任链模式
6.1.1 命令模式


6.1.2 责任链模式
- CommandInterceptor

- 配置Interceptor
- customPreCommandInterceptors:配置在默认拦截器之前
- customPostCommandInterceptors:配置在默认拦截器之后
- commandInvoker:配置最后的执行器
6.2 拦截器的配置方式
- activiti.cfg.xml文件的修改
1 2 3 4 5 6
| <property name="customPreCommandInterceptors"> <list> <bean class="com.atguigu.interceptor.DurationInterceptor"/> </list> </property>
|
- 实体类的编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.atguigu.interceptor;
import org.activiti.engine.impl.interceptor.AbstractCommandInterceptor; import org.activiti.engine.impl.interceptor.Command; import org.activiti.engine.impl.interceptor.CommandConfig;
public class DurationInterceptor extends AbstractCommandInterceptor { @Override public <T> T execute(CommandConfig config, Command<T> command) { long l = System.currentTimeMillis(); this.getNext().execute(config,command); long l1 = System.currentTimeMillis(); long duration = l1 - l; System.out.println("执行的时长----->"+duration); return null; } }
|
6.3 Activiti的拦截器

7. 作业执行器 Job Executor
7.1 作业执行器配置
(1) asyncExecutorActivate:激活作业执行器
(2) asyncExectuorXXX:异步执行器的属性配置
(3) asyncExecutor:异步执行器的bean
7.2 配置自定义线程池
7.2.1 自定义线程池ExecutorService
(1) corePoolSize:核心线程数
(2) maxPoolSize: 最大线程数
(3) queueCapacity:堵塞队列大小
7.2.2 基于spring线程池的配置

7.3 流程定义定时启动流程
7.3.1 定时开始事件
- timeDate:指定启动时间
- timeDuration:指定持续时间间隔后执行
- timeCycle:R5/P1DT1H指定事件段后周期执行
7.4 配置文件修改
activiti.cfg.xml文件修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <!--打开定时任务的激活器--> <property name="asyncExecutorActivate" value="true"/> <!--定义异步执行器--> <property name="asyncExecutor" ref="defaultAsyncJobExecutor"/> </bean> <!--系统默认的自定义任务执行器--> <bean id = "defaultAsyncJobExecutor" class="org.activiti.engine.impl.asyncexecutor.DefaultAsyncJobExecutor"> <!--需要的服务--> <property name="executorService" ref="executorService"/> </bean> <!--使用spring的线程池--> <bean id = "executorService" class="org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean"> <!--具体的配置--> </bean>
|
8 Activiti与Spring的集成
8.1 集成Spring配置
8.1.1 相关配置
(1) 添加pom依赖activiti-spring
1 2 3 4 5 6
| <!-- https://mvnrepository.com/artifact/org.activiti/activiti-spring --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring</artifactId> <version>6.0.0</version> </dependency>
|
(2) 基于Spring的默认配置activiti-context.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <?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="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="jdbc:mysql://111.229.203.5:3306/activiti?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true"/> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="username" value="weaver"/> <property name="password" value="192612"/> <property name="initialSize" value="1"/> <property name="maxActive" value="10"/> <property name="filters" value="stat,slf4j"/> </bean> <!--事务管理器配置--> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--指定数据源--> <property name="dataSource" ref="dataSource"/> </bean> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> <property name="dataSource" ref="dataSource"/> <!--配置事务管理--> <property name="transactionManager" ref="dataSourceTransactionManager"/> <!--数据源的创建格式--> <property name="databaseSchemaUpdate" value="true"/> </bean> <!--构造流程引擎对象--> <bean id = "processEngineFactoryBean" class="org.activiti.spring.ProcessEngineFactoryBean"> <!--指定流程配置对象--> <property name="processEngineConfiguration" ref="processEngineConfiguration"/> </bean> <!--报漏服务给Spring--> <bean id="runtimeService" factory-bean="processEngineFactoryBean" factory-method="getRuntimeService"></bean> <bean id="repositoryService" factory-bean="processEngineFactoryBean" factory-method="getRepositoryService"></bean> <bean id="formService" factory-bean="processEngineFactoryBean" factory-method="getFormService"></bean> <bean id="taskService" factory-bean="processEngineFactoryBean" factory-method="getTaskService"></bean> <bean id="historyService" factory-bean="processEngineFactoryBean" factory-method="getHistoryService"></bean> <bean id="activitiRule" class="org.activiti.engine.test.ActivitiRule"> <property name="processEngine" ref="processEngineFactoryBean"/> </bean> </beans>
|
(3) Activiti核心服务注入Spring容器
详细配置见上一步
8.2 基于Spring对Activiti管理
8.2.1 功能特征
(1) 集成Spring事务管理器
(2) 定义文件表达式中使用Spring bean
(3) 自动部署资源文件
8.3 基于Spring的流程单元测试
8.3.1 单元测试
(1) 添加pom依赖spring-test
1 2 3 4 5 6 7
| <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.2.5.RELEASE</version> <scope>test</scope> </dependency>
|
(2) 辅助测试Rule:ActivitiRule
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package com.atguigu.test;
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;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:activiti-context.xml"}) public class TestSpring { private static Logger log = LoggerFactory.getLogger(TestSpring.class);
@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");
Task task = taskService.createTaskQuery().singleResult(); taskService.complete(task.getId()); }
}
|
(3) 辅助测试TestCase:SpringActivitiTestCase