zoukankan      html  css  js  c++  java
  • Activiti工作流学习-----基于5.19.0版本(2)

    二、activiti.cfg.xml的其他bean节点配置

    2.1 新特性:Job Executor和Async Executor

    从5.17.0版本的activiti开始提供作业执行者(Job Executor)和异步作业执行者(Async Executor),Async Executor执行表现更好,并且执行异步作业对数据库更加友善。activiti官方推荐使用Async Executor,并且一些老的Job Executor依旧有效。在Java EE 7运行环境中,JSR-236规范支持容器管理ManagedJobExecutor和ManagedAsyncJobExecutor,例如可以配置如下:

    <bean id="threadFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
       <property name="jndiName" value="java:jboss/ee/concurrency/factory/default" />
    </bean>
    
    <bean id="customJobExecutor" class="org.activiti.engine.impl.jobexecutor.ManagedJobExecutor">
       <!-- ... -->
       <property name="threadFactory" ref="threadFactory" />
       <!-- ... -->
    </bean>

    2.2 激活Job executor

    Job executor作为管理多线程执行定时任务的组件,在单元测试场景里,Job executor在多线程中执行是测试不方便的,所以activiti提供了api解决了这个麻烦:

    查询获取Job executor可以通过ManagementService.createJobQuery方法实现,执行该作业可以调用ManagementService.executeJob,使得在单元测试中Job executor可以被控制,顺利关闭Job executor。默认的Job executor是在流程引擎启动就被激活的,如果需要关闭这个功能,可以配置:

    <property name="jobExecutorActivate" value="false" />

    2.3 激活Async executor

    AsyncExecutor作为管理线程池执行定时任务的组件,默认activiti是关闭AsyncExecutor的,使用它的配置如下:

    <property name="asyncExecutorEnabled" value="true" />
    <property name="asyncExecutorActivate" value="true" />

    asyncExecutorEnabled属性设置设置true后将代替那些老的Job executor,第二个属性asyncExecutorActivate是指示activiti在流程引擎启动就激活AsyncExecutor。

    2.4 流程定义缓存配置

    所有被解析的流程定义都会被缓存起来,这是因为流程定义是不会改变的,没有必要多次请求数据库。默认的activiti是没有限制缓存数量的,如果需要设置:

    <property name="processDefinitionCacheLimit" value="10" />

    缓存内部是使用HashMap数据结构和LRU算法实现的。当然,缓存的数量的设置值最好根据流程定义的总数和正在运行的流程实例使用的流程定义数量决定。你也可以使用自定义的缓存实现类替换内部提供的缓存实现,只需要实现接口org.activiti.engine.impl.persistence.deploy.DeploymentCache,然后配置即可:

    <property name="processDefinitionCache">
      <bean class="org.activiti.MyCache" />
    </property>

    对于自定义缓存实现的缓存数量限制可以设置knowledgeBaseCacheLimit和knowledgeBaseCache属性。

    2.5 日志

    在activiti 5.12的时候,日志框架使用的是SLF4J,替换掉早前的jdk的日志工具,现在所有的日志(activiti, spring, mybatis, …​)都通过SLF4J来输出日志,你可以具体的日志实现。

    工作流没有提供日志的具体实现jar包在依赖里面,需要你自己手动添加,如果没有添加,SLF4J会全程使用NOP-logger,它不会全程记录所有的日志的,并且警告没有被记录,在Maven中比如添加log4j:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
    </dependency>

    activiti-explorer和activiti-rest项目是使用的log4j,activiti项目测试也是使用的log4j记录日志。

    如果你的类路径下面已经有了commons-logging的jar了的话,这时需要commons-logging干的活交给slf4j,比如要让spring输出日志使用slf4j的话,需要使用依赖:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
    </dependency>

    如果使用的服务器是Tomcat,需要注意tomcat自己的类路径下面也有日志的jar包,解决办法参考:http://www.slf4j.org/codes.html#release

    2.6 日志配置相关工作流上下文

    从版本5.13开始,Activiti支持使用slf4j记录工作流上下文,日志通过底层日志logger记录的内容有:

    • processDefinition Id ------    mdcProcessDefinitionID

    • processInstance Id  -------   mdcProcessInstanceID

    • execution Id -     ----   mdcexecutionId

    日志记录有格式化的信息和其他的普通信息,例如日志记录可以配置:

     log4j.appender.consoleAppender.layout.ConversionPattern =ProcessDefinitionId=%X{mdcProcessDefinitionID}
    executionId=%X{mdcExecutionId} mdcProcessInstanceID=%X{mdcProcessInstanceID} mdcBusinessKey=%X{mdcBusinessKey} %m%n"
    在系统关键的地方进行记录或检测是非常有必要的,通过日志分析也是其中一种手段。

    2.7 事件处理

    在Activiti 5.15中引入了事件机制,它让你在工作流引擎中的各种事件发生时得到消息,activiti能够支持注册一个侦听器对于某些类型的事件而不是任何类型的事件发生时收到通知,一方面可以在配置文件中添加engine-wide事件监听器配置,然后engine-wide事件监听器类会调用相应的API,另一方面也可以在在BPMN配置文件中配置。

    所有的事件类都是org.activiti.engine.delegate.event.ActivitiEvent的子类,事件会提供type、executionId、processInstanceId和processDefinitionId,某些事件包含了事件发生的上下文,附加载荷的信息。

    2.8 事件监听器的实现

    事件监听器需要实现org.activiti.engine.delegate.event.ActivitiEventListener,例如:

    public class MyEventListener implements ActivitiEventListener {
    
      @Override
      public void onEvent(ActivitiEvent event) {
        switch (event.getType()) {
    
          case JOB_EXECUTION_SUCCESS:
            System.out.println("A job well done!");
            break;
    
          case JOB_EXECUTION_FAILURE:
            System.out.println("A job has failed...");
            break;
    
          default:
            System.out.println("Event received: " + event.getType());
        }
      }
    
      @Override
      public boolean isFailOnException() {
        // The logic in the onEvent method of this listener is not critical, exceptions
        // can be ignored if logging fails...
        return false;
      }
    }
    MyEventListener接收标准事件类型并处理和异常处理,其中isFailOnException()决定了onEvent(..)是否抛出异常,如果返回false,异常将会被忽略。如果返回true,异常将会逐级向上提交,
    造成当前运行的命令的失败。如果当前执行具有事务,事务将会回滚。activiti官方建议如果事件的业务不是非常重要,还是返回false。
    activiti提供了通用的实现类来处理普通的事件监听,例如:
    org.activiti.engine.delegate.event.BaseEntityEventListener:它将会监听entity类的事件,它隐藏了类型检查和重写了四个方法,onCreate(..), onUpdate(..)和onDelete(..),
    对于其他的事件,onEntityEvent(..)将会被调用。

    2.9 事件的相关配置

    如果一个事件监听器在流程引擎配置,流程引擎启动将会激活,即使重启引擎也会保持该状态。eventListeners属性值为org.activiti.engine.delegate.event.ActivitiEventListener
    的实例的list,例如:
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        ...
        <property name="eventListeners">
          <list>
             <bean class="org.activiti.engine.example.MyEventListener" />
          </list>
        </property>
    </bean>
    另外typedEventListeners属性值为Map,key为事件的名称,value表示为一个org.activiti.engine.delegate.event.ActivitiEventListener的list集合,例如:
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        ...
        <property name="typedEventListeners">
          <map>
            <entry key="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" >
              <list>
                <bean class="org.activiti.engine.example.MyJobEventListener" />
              </list>
            </entry>
          </map>
        </property>
    </bean>

    事件发生的顺序取决于被配置的监听器的顺序。首先,所有的普通的监听器会被调用(也就是说eventListeners属性,至于eventListeners的内部的监听器顺序和配置的顺序有关)

    ,然后是在typedListeners属性配置的会被调用。

    2.10 程序运行时动态添加监听器

    调用RuntimeService的api方法可以实现这个功能:(注意:系统重启会导致监听器消失)
    void addEventListener(ActivitiEventListener listenerToAdd);
    
    void addEventListener(ActivitiEventListener listenerToAdd, ActivitiEventType... types);
    
    void removeEventListener(ActivitiEventListener listenerToRemove);
    
    

    2.11 添加监听器到流程定义中

    在流程定义中添加监听器是允许的,这里定义的监听器会被流程定义相关的事件和所有的相关的流程实例启动后调用,监听器的实现类可以使用全类名、能够被解析为bean的表达式。例如下面这个配置,第一个监听器将接收所有的事件,它使用的是全类名进行配置的,第二个监听器仅仅是在作业执行成功或者失败会被执行,并且使用了在流程引擎中定义的beans属性配置的监听器的表达式。

    <process id="testEventListeners">
      <extensionElements>
        <activiti:eventListener class="org.activiti.engine.test.MyEventListener" />
        <activiti:eventListener delegateExpression="${testEventListener}" events="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" />
      </extensionElements>
      ...
    </process>

     如果我们需要在流程定义中配置监听entity的监听器的话,可以这样配置:

    <process id="testEventListeners">
      <extensionElements>
        <activiti:eventListener class="org.activiti.engine.test.MyEventListener" entityType="task" />
        <activiti:eventListener delegateExpression="${testEventListener}" events="ENTITY_CREATED" entityType="task" />
      </extensionElements>
      ...
    </process>

    其中entityType的值有:attachment, comment, execution, identity-link, job, process-instance, process-definition, task。

  • 相关阅读:
    Deployment descriptor
    实体、list 、xml之间的转化
    关于C# 汉字转拼音问题
    NPoco学习笔记(1)
    SQL(二)
    SQL(一)
    sobel算子及cvSobel
    图像的平滑处理
    erase的用法
    int main(int argc, char* argv[ ])
  • 原文地址:https://www.cnblogs.com/liujie037/p/5778514.html
Copyright © 2011-2022 走看看