Activiti6.0(三)引擎配置

作者: 郭少华 | 来源:发表于2019-07-15 16:50 被阅读26次

    引擎配置类介绍

    • ProcessEngineConfigUration
      查找并解析xml配置文件activiti.cfrg.xml
      提供多个静态方法配置对象
      实现几个基于不通场景的子类

    • 静态方法创建配置对象

    • 默认路径加载一个资源配置文件构造对象:ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault()
    • 指定目录加载一个资源配置文件构造对象
      ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String)
    • 指定目录和修改id类型加载一个资源配置文件构造对象
      ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String,String)
    • 通过流加载一个资源配置文件构造对象
      ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(InputStream)
    • 通过流和修改id类型加载一个资源配置文件构造对象
      ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(InputStream,String)
    • 独立的引擎配置对象
      ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration()
    • 通过内存数据库构造对象
      ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
    • 流程引擎配置及子类
      ProcessEngineConfiguration
    • ProcessEngineConfigurationImpl 抽象类配置了ProcessEngineConfiguration的户型
    • StandaloneProcessEngineConfiguration 通过new的方式创建对象
    • SpringProcessEngineConfiguration 基于spring集成完成扩展

    创建流程引擎配置-创建maven activiti脚手架

    • 打开activiti6.0源码 cd tooling/archetypes/
    • mvn clean install
    • 添加main/java 与main/resources 目录


      image.png
    • 把helloworld项目里面到main函数与配置文件复制过来,并修改archetype-metadata.xml


      image.png
    • 修改main函数里面到参数


      image.png
    • cd activiti-archetype-unittest/
    • mvn clean install
    • 添加到maven脚手架


      image.png

    创建流程引擎配置 config_samples

    创建新的项目并创建子模块选择自己创建的脚手架


    image.png

    测试其他引擎配置类

    public class ConfigTest {
    
        private static  final Logger logger= LoggerFactory.getLogger(ConfigTest.class);
    
        @Test
        public void testConfig1(){
            //基于activiti.cfg.xml 并创建基于内存的h2数据库对象依赖spring容器创建
            ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
            logger.info("configuration = {}",cfg);
    
        }
    
        @Test
        public void testConfig2(){
            //独立的引擎配置对象
            ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
            logger.info("configuration = {}",cfg);
    
        }
    }
    

    流程引擎数据库配置

    • 缺省默认配置,使用H2内存数据库
    • 配置jdbc属性,使用mybatis链接池
    • 配置DataSource,可自选第三方实现

    配置jdbc属性,使用mybatis链接池

    基本配置
    jdbcUrl、jdbcDriver、jdbcUsername、jdbcPassword
    链接池配置
    jdbcMaxActiveConnections、jdbcMaxIdleConnections、jdbcMaxCheckoutTime、jdbcMaxWaitTime

    配置DataSource,可自选第三方实现

    • Druid 为监控而生的数据库链接池来自阿里
    • Dbcp 老牌数据源链接池,稳定可靠,Tomcat自带
    • HikarIcp 来自日本的极速数据源链接池,spring默选

    Druid链接池activiti.cfg.xml配置


    image.png

    数据库更新策略

    配置DatabaseSchemaUpdate

    • false:启动时检查数据库版本,发生不匹配抛异常,适用于生产环境
    • true:启动时自动检查并更新数据库表,不存在创建,适用与开发环境
    • create-drop:启动时创建数据库表结构,结束时删除表结构,适用于测试环境

    引擎配置数据库Demo

    通过修改 activiti.cfg.xml 把默认的H2数据库改成mysql数据库

    创建测试类

    public class ConfigDBTest {
        private static  final Logger logger= LoggerFactory.getLogger(ConfigDBTest.class);
    
        @Test
        public void  testConfig1(){
            ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
            logger.info("configuration = {}",cfg);
            ProcessEngine processEngine = cfg.buildProcessEngine();
            logger.info("获取流程引擎 {}",processEngine.getName());
            processEngine.close();
        }
    
    }
    

    修改 activiti.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">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
      </bean>
    
    </beans>
    
    

    通过修改创建新的配置文件并指定把链接方式改成druid链接

    创建一个新的配置文件


    image.png

    activiti_druid.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">
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
        <!--数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--是否需要历史数据-->
        <property name="dbHistoryUsed" value="true"/>
        <!--是否需要用户数据-->
        <property name="dbIdentityUsed" value="true"/>
        <!--给表加前缀-->
        <property name="databaseTablePrefix" value="T_"/>-
    
      </bean>
    
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="initialSize" value="2"/>
        <property name="maxActive" value="10"/>
      </bean>
    
    </beans>
    

    读取配置文件

    public class ConfigDBTest {
        private static  final Logger logger= LoggerFactory.getLogger(ConfigDBTest.class);
        @Test
        public void  testConfig2(){
            ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti_druid.cfg.xml");
            logger.info("configuration = {}",cfg);
            ProcessEngine processEngine = cfg.buildProcessEngine();
            logger.info("获取流程引擎 {}",processEngine.getName());
            processEngine.close();
        }
    
    }
    

    日志记录配置开启mdc日志记录

    加 LogMDC.setMDCEnabled(true);当出现异常时会在日志显示流程id等信息

    public class ConfigMDCTest {
        private static  final Logger logger= LoggerFactory.getLogger(ConfigMDCTest.class);
    
        @Rule
        public ActivitiRule activitiRule = new ActivitiRule("activiti_mdc.cfg.xml");
    
    
    
        @Test
        @Deployment(resources = {"com/guosh/activiti/my-process.bpmn20.xml"})
        public void test() {
            LogMDC.setMDCEnabled(true);
    
            ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
            assertNotNull(processInstance);
            Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
            assertEquals("Activiti is awesome!", task.getName());
            activitiRule.getTaskService().complete(task.getId());
        }
    
    }
    

    通过拦截器设置MDC

    <?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">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
        <!--自定义拦截每次执行流程都打印流程id-->
        <property name="commandInvoker" ref="commandInvoker"/>
      </bean>
      <bean id="commandInvoker" class="com.guosh.activiti.interceptor.MDCCommandInvoker"/>
    </beans>
    
    
    public class MDCCommandInvoker extends DebugCommandInvoker {
    
        private static final Logger logger = LoggerFactory.getLogger(DebugCommandInvoker.class);
    
        @Override
        public void executeOperation(Runnable runnable) {
            boolean mdcEnabled = LogMDC.isMDCEnabled();
            LogMDC.setMDCEnabled(true);
            if (runnable instanceof AbstractOperation) {
                AbstractOperation operation = (AbstractOperation) runnable;
    
                if (operation.getExecution() != null) {
                    LogMDC.putMDCExecution(operation.getExecution());
                }
    
            }
    
            super.executeOperation(runnable);
            LogMDC.clear();
            if(!mdcEnabled){
                LogMDC.setMDCEnabled(false);
            }
        }
    
    }
    

    历史记录配置

    配置HistoryLevel(流程结束后的历史记录)

    • none:不记录历史流程,性能高,流程结束后不可读取
    • activiti:归档流程实例,流程变量不同步(能看到历史内容历史活动)
    • audit:默认值,在activiti基础上同步变量值,保存表单属性(能看到历史表单,历史详情)
    • full:性能较差,记录所有实例和变量细节变化(上面基础上能看到详情的变化)

    测试文件

    public class ConfigMDCTest {
        private static  final Logger logger= LoggerFactory.getLogger(ConfigMDCTest.class);
    
        @Rule
        public ActivitiRule activitiRule = new ActivitiRule("activiti_history.cfg.xml");
    
    
        @Test
        @Deployment(resources = {"com/guosh/activiti/my-process.bpmn20.xml"})
        public void test() {
            //启动流程
            startProcessInstance();
    
            //修改变量
            changeVariable();
    
            //提交表单task
            submitTaskForm();
    
    
            //输出历史内容
            //输出历史活动
            showHistoryActivity();
    
            //历史变量
            showHistoryVaiable();
    
    
            //输出历史用户任务
            showHistoryTask();
    
            //历史表单详情
            showHistoryForm();
    
    
            //输出历史详情
            showHistoryDetail();
        }
    
        private void showHistoryDetail() {
            List<HistoricDetail> historicDetails = activitiRule.getHistoryService().createHistoricDetailQuery().list();
            for (HistoricDetail historicDetail:historicDetails) {
                logger.info("historicDetail = {}",historicDetail);
            }
            logger.info("historicDetails.size = {}",historicDetails.size());
        }
    
        private void showHistoryForm() {
            List<HistoricDetail> historicDetailsFrom = activitiRule.getHistoryService().createHistoricDetailQuery().formProperties().list();
            for (HistoricDetail historicDetail:historicDetailsFrom) {
                logger.info("historicDetail = {}",historicDetail);
            }
            logger.info("historicDetailsFrom.size = {}",historicDetailsFrom.size());
        }
    
        private void showHistoryTask() {
            List<HistoricTaskInstance> historicTaskInstances = activitiRule.getHistoryService().createHistoricTaskInstanceQuery().list();
            for (HistoricTaskInstance historicTaskInstance:historicTaskInstances) {
                logger.info("historicTaskInstance = {}",historicTaskInstance);
            }
            logger.info("historicTaskInstances.size = {}",historicTaskInstances.size());
        }
    
        private void showHistoryVaiable() {
            List<HistoricVariableInstance> historicVariableInstances = activitiRule.getHistoryService().createHistoricVariableInstanceQuery().list();
            for (HistoricVariableInstance historicActivityInstance:historicVariableInstances) {
                logger.info("historicActivityInstance = {}",historicActivityInstance);
            }
            logger.info("historicVariableInstances.size = {}",historicVariableInstances.size());
        }
    
        private void showHistoryActivity() {
            List<HistoricActivityInstance> historicActivityInstances = activitiRule.getHistoryService().createHistoricActivityInstanceQuery().list();
            for (HistoricActivityInstance historicActivityInstance:historicActivityInstances) {
                logger.info("historicActivityInstance = {}",historicActivityInstance);
            }
            logger.info("historicActivityInstance.size = {}",historicActivityInstances.size());
        }
    
        private void submitTaskForm() {
            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);
        }
    
        private void changeVariable() {
            List<Execution> executions = activitiRule.getRuntimeService().createExecutionQuery().listPage(0, 100);
            for (Execution execution:executions) {
                logger.info("execution = {}",execution);
            }
            logger.info("execution.size = {}", executions.size());
            String id=executions.iterator().next().getId();
            activitiRule.getRuntimeService().setVariable(id,"keyStart1","value1_");
        }
    
        private void startProcessInstance() {
            Map<String,Object> params= Maps.newHashMap();
            params.put("keyStart1","value1");
            params.put("keyStart2","value2");
    
            ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process",params);
        }
    
    }
    
    <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">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
        <!--自定义拦截每次执行流程都打印流程id-->
        <property name="commandInvoker" ref="commandInvoker"/>
        <!--查看历史的级别-->
    
        <!--所有历史都看不到-->
        <!--<property name="history" value="none"/>-->
        <!--能查看历史活动历史变量-->
        <!--<property name="history" value="activity"/>-->
        <!--能查看到所有,但是查看不到数据的修改记录-->
        <!--<property name="history" value="audit"/>-->
        <property name="history" value="full"/>
    
    
      </bean>
      <bean id="commandInvoker" class="com.guosh.activiti.interceptor.MDCCommandInvoker"/>
    </beans>
    

    事件处理及监听器配置

    事件处理

    enableDatabaseEventLogging 作用监听变化记录变化日志

    public class ConfigEventLogTest {
        private static  final Logger logger= LoggerFactory.getLogger(ConfigEventLogTest.class);
    
        @Rule
        public ActivitiRule activitiRule = new ActivitiRule("activiti_evenlog.cfg.xml");
    
    
        @Test
        @Deployment(resources = {"com/guosh/activiti/my-process.bpmn20.xml"})
        public void test() {
            ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
            Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
            assertEquals("Activiti is awesome!", task.getName());
            activitiRule.getTaskService().complete(task.getId());
            //根据流程id查询
            List<EventLogEntry> envenLogEntrys = activitiRule.getManagementService()
                    .getEventLogEntriesByProcessInstanceId(processInstance.getId());
    
            for (EventLogEntry eventLogEntry:envenLogEntrys) {
                logger.info("eventLogEntry.type = {},eventLogEntry.data = {}",eventLogEntry.getType(),eventLogEntry.getData());
    
            }
            logger.info("envenLogEntrys.sice = {},eventLogEntry.data = {}",envenLogEntrys.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">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
        <!--自定义拦截每次执行流程都打印流程id-->
        <property name="commandInvoker" ref="commandInvoker"/>
        <!--事件监听器-->
        <property name="enableDatabaseEventLogging" value="true"/>
    
      </bean>
      <bean id="commandInvoker" class="com.guosh.activiti.interceptor.MDCCommandInvoker"/>
    </beans>
    

    监听器配置

    image.png image.png
    • 配置Listener
    • eventListeners: 监听所有事件派发通知
    • typedEventListeners:监听指定事件类型的通知
    • activiti:eventListener:只监听特定的流程定义事件
    • 相关Api
    • ActivitiEvent:事件对象
    • ActivitiEventListener:监听器
    • ActivitiEventType:事件类型

    1.注册监听第一种写法

    <?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">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
        <!--第一种方式-->
        <property name="eventListeners">
          <list>
            <bean class="com.guosh.activiti.event.ProcessEventListener"/>
          </list>
        </property>
    
    </beans>
    
    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 {}",event.getType(),event.getProcessInstanceId());
            }
            //流程结束
            else if(ActivitiEventType.PROCESS_COMPLETED.equals(eventType)){
                logger.info("流程结束 {} \t {}",event.getType(),event.getProcessInstanceId());
    
            }
        }
    
        @Override
        public boolean isFailOnException() {
            return false;
        }
    }
    

    2.注册监听第二种写法

        <property name="typedEventListeners">
          <map>
            <!--流程启动-->
            <entry key="PROCESS_STARTED">
              <list>
                <bean class="com.guosh.activiti.event.ProcessEventListener"/>
              </list>
            </entry>
          </map>
        </property>
    

    3.自定义监听

    public class ConfigEventListenerTest {
        private static  final Logger logger= LoggerFactory.getLogger(ConfigEventListenerTest.class);
    
        @Rule
        public ActivitiRule activitiRule = new ActivitiRule("activiti_evenlistener.cfg.xml");
    
    
        @Test
        @Deployment(resources = {"com/guosh/activiti/my-process.bpmn20.xml"})
        public void test() {
            ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
            Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
            assertEquals("Activiti is awesome!", task.getName());
            activitiRule.getTaskService().complete(task.getId());
    
            //发出一个自定义事件
            activitiRule.getRuntimeService().dispatchEvent(new ActivitiActivityEventImpl(ActivitiEventType.CUSTOM));
    
        }
    
    }
    
    public class CustomEventListener implements ActivitiEventListener {
        private static  final Logger logger= LoggerFactory.getLogger(CustomEventListener.class);
    
        @Override
        public void onEvent(ActivitiEvent event) {
            ActivitiEventType eventType = event.getType();
            //判断如果是自定义的事件
            if(ActivitiEventType.CUSTOM.equals(eventType)){
                logger.info("监听到自定义事件 {} \t {}",event.getType(),event.getProcessInstanceId());
            }
    
        }
    
        @Override
        public boolean isFailOnException() {
            return false;
        }
    }
    
    
    <?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">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
        <!--自定义监听事件-->
            <property name="eventListeners">
              <list>
                <bean class="com.guosh.activiti.event.CustomEventListener"/>
              </list>
            </property>
    
      </bean>
      <bean id="commandInvoker" class="com.guosh.activiti.interceptor.MDCCommandInvoker"/>
    </beans>
    

    4.通过代码注册监听

    public class ConfigEventListenerTest {
        private static  final Logger logger= LoggerFactory.getLogger(ConfigEventListenerTest.class);
    
        @Rule
        public ActivitiRule activitiRule = new ActivitiRule("activiti_evenlistener.cfg.xml");
    
    
        @Test
        @Deployment(resources = {"com/guosh/activiti/my-process.bpmn20.xml"})
        public void test() {
            activitiRule.getRuntimeService().addEventListener(new CustomEventListener());
            ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
            Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
            assertEquals("Activiti is awesome!", task.getName());
            activitiRule.getTaskService().complete(task.getId());
            //通过addEventListener注册
            activitiRule.getRuntimeService().addEventListener(new CustomEventListener());
            //发出一个自定义事件
            activitiRule.getRuntimeService().dispatchEvent(new ActivitiActivityEventImpl(ActivitiEventType.CUSTOM));
    
        }
    
    }
    

    命令拦截器的配置

    • 命令模式与责任链模式


      image.png
    image.png
    • 拦截器的配置方式

    配置Interceptor

    1. customPreCommandInterceptors:配置在默认拦截器之前
    2. customPostCommandInterceptors:配置在默认拦截器之后
    3. commandInvoker:配置最后的执行器
    public class DurationCommandInterceptor extends AbstractCommandInterceptor {
    
        private static final Logger logger = LoggerFactory.getLogger(DurationCommandInterceptor.class);
    
        @Override
        public <T> T execute(CommandConfig config, Command<T> command) {
            //取毫秒数
            long start =System.currentTimeMillis();
            try {
                return this.getNext().execute(config,command);
            }finally {
                long duration = System.currentTimeMillis() - start;
                logger.info("{} 执行时长 {} 毫秒",command.getClass().getSimpleName(),duration);
            }
    
        }
    }
    
    
    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 = {"com/guosh/activiti/my-process.bpmn20.xml"})
        public void test() {
            ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
            Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
            assertEquals("Activiti is awesome!", task.getName());
            activitiRule.getTaskService().complete(task.getId());
        }
    
    }
    
    <?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">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
    
        <!--拦截器-->
        <property name="customPreCommandInterceptors">
          <list>
            <bean class="com.guosh.activiti.interceptor.DurationCommandInterceptor"/>
          </list>
        </property>
    
        <property name="customPostCommandInterceptors">
          <list>
            <bean class="com.guosh.activiti.interceptor.DurationCommandInterceptor"/>
          </list>
        </property>
    
        <!--能实现mdc同样的效果-->
        <property name="enableVerboseExecutionTreeLogging" value="true"/>
    
        <!--自定义拦截每次执行流程都打印流程id-->
    <!--    <property name="commandInvoker" ref="commandInvoker"/>-->
      </bean>
      <bean id="commandInvoker" class="com.guosh.activiti.interceptor.MDCCommandInvoker"/>
    </beans>
    

    作业执行器

    • 作业执行器的配置
      相关配置
    1. asyncExecutorActivate:激活作业执行器
    2. asyncExecutorXXX:异步执行器对属性配置
    3. asyncExecutor:异步执行期bean

    定时开始事件
    timDate:指定启动时间
    timeDuration:指定持续时间间隔后执行
    timCycle:R5/P1DT1H指定事件段后周期执行

    • 配置自定义线程池
      自定义线程池ExecutorService
    • threadNamePrefix:线程池名字前缀
    • corePoolSice:核心线程数
    • maxPoolSize:最大线程数
    • queueCapacity:堵塞队列大小
    image.png
    • 流程定义定时启动流程
      线程池配置
    <?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">
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false" />
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="root" />
        <!--数据库更新策略-->
        <property name="databaseSchemaUpdate" value="true"/>
    
        <!--异步激活器-->
        <property name="asyncExecutorActivate" value="true"/>
        <!--异步执行器-->
        <property name="asyncExecutor" ref="asyncExecutor"/>
        <!--监听JOB事件-->
        <property name="eventListeners">
          <list>
            <bean class="com.guosh.activiti.event.JobEventListener"/>
          </list>
        </property>
    
    
      </bean>
      <bean id="asyncExecutor" class="org.activiti.engine.impl.asyncexecutor.DefaultAsyncJobExecutor">
        <property name="executorService" ref="executorService"/>
      </bean>
      <!--线程池-->
      <bean id="executorService" class="org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean">
        <!--线程池名字前缀-->
        <property name="threadNamePrefix" value="activiti-job"/>
        <!--核心线程池-->
        <property name="corePoolSize" value="5"/>
        <!--最大线程数-->
        <property name="maxPoolSize" value="20"/>
        <!--堵塞队列大小-->
        <property name="queueCapacity" value="100"/>
        <!--拒绝策略-->
        <property name="rejectedExecutionHandler">
          <bean class="java.util.concurrent.ThreadPoolExecutor$AbortPolicy"/>
        </property>
    
      </bean>
    </beans>
    
    

    流程定时任务配置

    <?xml version="1.0" encoding="UTF-8"?>
    
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
        xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
        xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
        expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
    
        <process id="my-process">
    
            <!--<startEvent id="start" />-->
            <startEvent id="start" >
                <!--定时启动-->
                <timerEventDefinition>
                    <!--含义执行五次间隔十秒-->
                    <timeCycle>R5/PT10S</timeCycle>
                </timerEventDefinition>
    
            </startEvent>
            <sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
    
    
            <userTask id="someTask" name="Activiti is awesome!" />
            <sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
    
            <endEvent id="end" />
    
        </process>
    
    </definitions>
    

    定时任务事件监听

    public class JobEventListener implements ActivitiEventListener {
        private static  final Logger logger= LoggerFactory.getLogger(JobEventListener.class);
    
        @Override
        public void onEvent(ActivitiEvent event) {
            ActivitiEventType eventType = event.getType();
            String name=eventType.name();
            //判断如果是自定义的事件
            if(name.startsWith("TIMER")||name.startsWith("JOB")){
                logger.info("监听到JOB事件 {} \t {}",event.getType(),event.getProcessInstanceId());
            }
    
        }
    
        @Override
        public boolean isFailOnException() {
            return false;
        }
    }
    
    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 = {"com/guosh/activiti/my-process_job.bpmn20.xml"})
        public void test() throws InterruptedException {
            logger.info("start");
            //当前有多少个定时任务在执行
            List<Job> jobs = activitiRule.getManagementService().createTimerJobQuery().list();
            for (Job job:jobs) {
                logger.info("定时任务 = {},默认重试次数 = {}",job,job.getRetries());
            }
            logger.info("jobs.size = {}", jobs.size());
            //等待
            Thread.sleep(1000*100);
    
            logger.info("end");
        }
    
    }
    

    集成Spring配置

    相关配置

    • 添加pom依赖activiti-spring
    • 基于spring的默认配置activiti-context.xml
    • Activiti核心服务注入Spring容器

    功能特征

    • 集成spring事物管理器
    • 定义文件表达式中使用Spring bean
    • 自动部署资源文件

    单元测试

    • 添加pom依赖spring-test
    • 辅助测试Rule:ActivitiRule
    • 辅助测试TestCase:SpringActrivitiTest

    配置activiti-context.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.spring.SpringProcessEngineConfiguration">
    
        <property name="databaseSchemaUpdate" value="true"/>
        <!--数据源-->
        <property name="dataSource" ref="dataSource"/>
    
        <!--事务管理器-->
        <property name="transactionManager" ref="transactionManager"/>
      </bean>
    
      <!--流程引擎对象-->
      <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
      </bean>
    
      <!--注册服务-->
      <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
      <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
      <bean id="formService" factory-bean="processEngine" factory-method="getFormService"/>
      <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
      <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
    
      <bean id="activitiRule" class="org.activiti.engine.test.ActivitiRule">
        <property name="processEngine" ref="processEngine"/>
      </bean>
    
    
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/activiti6unit?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="initialSize" value="2"/>
        <property name="maxActive" value="10"/>
      </bean>
    
    
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
      </bean>
      
      <bean id="helloBean" class="com.guosh.activiti.delegate.HelloBean"></bean>
    
    </beans>
    
    

    测试类

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:activiti-context.xml"})
    public class ConfigSpringTest {
        private static  final Logger logger= LoggerFactory.getLogger(ConfigSpringTest.class);
    
        @Rule
        @Autowired
        public ActivitiRule activitiRule;
    
        @Autowired
        private RuntimeService runtimeService;
    
        @Autowired
        private TaskService taskService;
    
    
        @Test
        @Deployment(resources = {"com/guosh/activiti/my-process_spring.bpmn20.xml"})
        public void test() {
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("my-process");
            assertNotNull(processInstance);
            Task task = taskService.createTaskQuery().singleResult();
            taskService.complete(task.getId());
        }
    
    }
    

    my-process_spring.bpmn20.xml流程文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
        xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
        xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
        expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
    
        <process id="my-process">
    
            <startEvent id="start" />
            <sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
    
    
            <userTask id="someTask" name="Activiti is awesome!" />
            <sequenceFlow id="flow2" sourceRef="someTask" targetRef="helloBean" />
            <!--${helloBean.sayHello()}可以调取到自己写到类到方法-->
            <serviceTask id="helloBean" activiti:expression="${helloBean.sayHello()}"/>
            <sequenceFlow id="flow3" sourceRef="helloBean" targetRef="end" />
    
            <endEvent id="end" />
    
        </process>
    
    </definitions>
    

    相关文章

      网友评论

        本文标题:Activiti6.0(三)引擎配置

        本文链接:https://www.haomeiwen.com/subject/vpagkctx.html