乐趣区

关于工作流:工作流引擎使用详解工作流框架Activiti的详细配置以及安装和使用

创立 ProcessEngine

  • Activiti 流程引擎的配置文件是名为 activiti.cfg.xml 的 XML 文件.留神与应用 Spring 形式创立流程引擎是不一样的
  • 应用 org.activiti.engine.ProcessEngines 类, 取得 ProcessEngine:

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine()

    它会在 classpath 下搜寻activiti.cfg.xml, 并基于这个文件中的配置构建引擎

    <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="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
      <property name="jdbcDriver" value="org.h2.Driver" />
      <property name="jdbcUsername" value="sa" />
      <property name="jdbcPassword" value="" />
    
      <property name="databaseSchemaUpdate" value="true" />
    
      <property name="jobExecutorActivate" value="false" />
    
      <property name="mailServerHost" value="mail.my-corp.com" />
      <property name="mailServerPort" value="5025" />
    </bean>
    
    </beans>

    配置文件中应用的 ProcessEngineConfiguration 能够通过编程形式创立, 能够配置不同的bean id

    ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
    ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String resource);
    ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String resource, String beanName);    // 配置不同的 bean id
    ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(InputStream inputStream);
    ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(InputStream inputStream, String beanName);

    如果不应用配置文件进行配置, 就会基于默认创立配置

  • ProcessEngineConfiguration.createXXX() 办法都会返回 ProcessEngineConfiguration, 后续能够调整成所需的对象. 在调用buildProcessEngine() 后, 就会创立一个ProcessEngine:

    ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
    .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
    .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
    .setJobExecutorActivate(true)
    .buildProcessEngine();

    ProcessEngineConfiguration bean

  • activiti.cfg.xml必须蕴含一个id=’processEngineConfiguration’ 的 bean

     <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

    这个 bean 会用来构建ProcessEngine. 有多个类能够用来定义processEngineConfiguration. 这些类对应不同的环境, 并设置了对应的默认值:

    • org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration: 独自运行的流程引擎.Activiti 会本人处理事务. 默认数据库只在引擎启动时检测(如果没有 Activiti 的表或者表构造不正确就会抛出异样)
    • org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration: 单元测试时的辅助类.Activiti 会本人管制事务. 默认应用 H2 内存数据库, 数据库表会在引擎启动时创立, 敞开时删除. 应用它时, 不须要其余配置(除非应用 job 执行器或邮件性能)
    • org.activiti.spring.SpringProcessEngineConfiguration: 在 Spring 环境下应用流程引擎
    • org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration: 独自运行流程引擎, 并应用 JTA 事务

      数据库配置

      定义数据库配置参数

  • 基于数据库配置参数定义数据库连贯配置

    • jdbcUrl: 数据库的 JDBC URL
    • jdbcDriver: 对应不同数据库类型的驱动
    • jdbcUsername: 连贯数据库的用户名
    • jdbcPassword: 连贯数据库的明码
  • 基于 JDBC 参数配置的数据库连贯 会应用默认的 MyBatis 连接池, 配置 MyBatis 连接池:

    • jdbcMaxActiveConnections: 连接池中处于被应用状态的连贯的最大值. 默认为10
    • jdbcMaxIdleConnections: 连接池中处于闲暇状态的连贯的最大值
    • jdbcMaxCheckoutTime: 连贯被取出应用的最长工夫, 超过工夫会被强制回收. 默认为20000(20 秒)
    • jdbcMaxWaitTime: 这是一个底层配置, 让连接池能够在长时间无奈取得连贯时, 打印一条日志, 并从新尝试获取一个连贯.(防止因为谬误配置导致缄默的操作失败) 默认为20000(20 秒)

      应用 javax.sql.DataSource 配置

  • Activiti 的公布包中没有这些类, 要把对应的类放到 classpath 下

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/activiti" />
    <property name="username" value="activiti" />
    <property name="password" value="activiti" />
    <property name="defaultAutoCommit" value="false" />
    </bean>
    
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    
      <property name="dataSource" ref="dataSource" />
      ...
    </bean>
  • 无论应用 JDBC 还是 DataSource, 都能够设置上面的配置:

    • databaseType:

      • 个别不必设置, 因为能够主动通过数据库连贯的元数据获取
      • 只有自动检测失败时才须要设置. 可能的值有:{h2,mysql,oracle,postgres,mssql,db2}
      • 如果没应用默认的 H2 数据库就必须设置这项. 这个配置会决定应用哪些创立 / 删除脚本和查问语句
    • databaseSchemaUpdate: 设置流程引擎启动和敞开时如何解决数据库表

      • false: 默认, 查看数据库表的版本和依赖库的版本, 如果版本不匹配就抛出异样
      • true: 构建流程引擎时, 执行查看, 如果须要就执行更新. 如果表不存在, 就创立
      • create-drop: 构建流程引擎时创立数据库表, 敞开流程引擎时删除这些表

        JNDI 数据库配置

  • 在默认状况下,Activiti 的数据库配置会放在 web 利用的 WEB-INF/classes 目录下的 db.properties 文件中. 这样做比拟繁琐, 因为要用户在每次公布时, 都 批改 Activiti 源码中的 db.properties 并从新编译 war 文件 , 或者 解压缩 war 文件, 批改其中的 db.properties
  • 应用 JNDI(Java 命名和目录接口) 来获取数据库连贯, 连贯是 由 servlet 容器治理 的, 能够 在 war 部署外边治理配置. 与 db.properties 相比, 它也容许对连贯进行更多的配置

    JNDI 的应用

  • Activiti Explorer 和 Activiti Rest 利用从 db.properties 转换为应用 JNDI 数据库配置:

    • 须要关上原始的 Spring 配置文件:

      • activiti-webapp-explorer/src/main/webapp/WEB-INF/activiti-standalone-context.xml
      • activiti-webapp-rest2/src/main/resources/activiti-context.xml
    • 删除 dbPropertiesdataSource两个 bean, 而后增加如下 bean:

      <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
      <property name="jndiName" value="java:comp/env/jdbc/activitiDB"/>
      </bean>
  • 咱们须要增加蕴含了默认的 H2 配置的 context.xml 文件
  • 如果曾经有了 JNDI 配置, 会笼罩这些配置. 对应的配置文件activiti-webapp-explorer2/src/main/webapp/META-INF/context.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context antiJARLocking="true" path="/activiti-explorer2">
      <Resource auth="Container"
                name="jdbc/activitiDB"
                type="javax.sql.DataSource"
                scope="Shareable"
                description="JDBC DataSource"
                url="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000"
                driverClassName="org.h2.Driver"
                username="sa"
                password=""defaultAutoCommit="false"initialSize="5"maxWait="5000"maxActive="120"maxIdle="5"/>
    </Context>
  • 如果是 Activiti REST 利用, 则增加activiti-webapp-rest2/src/main/webapp/META-INF/context.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context antiJARLocking="true" path="/activiti-rest2">
      <Resource auth="Container"
                name="jdbc/activitiDB"
                type="javax.sql.DataSource"
                scope="Shareable"
                description="JDBC DataSource"
                url="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=-1"
                driverClassName="org.h2.Driver"
                username="sa"
                password=""defaultAutoCommit="false"initialSize="5"maxWait="5000"maxActive="120"maxIdle="5"/>
    </Context>
  • 最初删除 Activiti Explorer 和 Activiti Rest 两个利用中不再应用的 db.properties 文件

    JNDI 的配置

  • JNDI 数据库配置会因为应用的 Servlet container 不同而不同
  • Tomcat 容器中的 JNDI 配置如下:

    • JNDI 资源配置在CATALINA_BASE/conf/[enginename]/[hostname]/[warname].xml(对于 Activiti Explorer 来说, 通常是在CATALINA_BASE/conf/Catalina/localhost/activiti-explorer.war) 当利用第一次公布时, 会把这个文件从 war 中复制进去. 所以如果这个文件曾经存在了, 须要替换它. 批改 JNDI 资源让利用连贯 mysql 而不是 H2:

      <?xml version="1.0" encoding="UTF-8"?>
      <Context antiJARLocking="true" path="/activiti-explorer2">
          <Resource auth="Container"
              name="jdbc/activitiDB"
              type="javax.sql.DataSource"
              description="JDBC DataSource"
              url="jdbc:mysql://localhost:3306/activiti"
              driverClassName="com.mysql.jdbc.Driver"
              username="sa"
              password=""defaultAutoCommit="false"initialSize="5"maxWait="5000"maxActive="120"maxIdle="5"/>
      </Context>

      Activiti 反对的数据库

  • h2: 默认配置的数据库
  • mysql
  • oracle
  • postgres
  • db2
  • mssql

    创立数据库表

  • 创立数据库表的办法:

    • activiti-engine的 jar 放到 classpath 下
    • 增加对应的数据库驱动
    • 把 Activiti 配置文件 (activiti.cfg.xml) 放到 classpath 下, 指向你的数据库
    • 执行 DbSchemaCreate 类的 main 办法
    SQL DDL 语句能够从 Activiti 下载页或 Activiti 公布目录里找到, 在 database 子目录下.
    脚本也蕴含在引擎的 jar 中:activiti-engine-x.jar 在 org/activiti/db/create 包下,drop 目录里是删除语句
  • SQL 文件的命名形式如下:
    [activiti.{db}.{create|drop}.{type}.sql]
    type 是:
  • engine: 引擎执行的表, 必须
  • identity: 蕴含用户, 群组, 用户与组之间的关系的表. 这些表是可选的, 只有应用引擎自带的默认身份治理时才须要
  • history: 蕴含历史和审计信息的表, 可选的. 历史级别设为 none 时不会应用. 留神这也会援用一些须要把数据保留到历史表中的性能

  • Activiti 的表都以 ACT_ 结尾, 第二局部是示意表的用处的两个字母标识. 用处和服务的 API 对应

    • ACT_RE_*: RE示意 repository. 这个前缀的表蕴含了 流程定义和流程动态资源
    • ACT_RU_*: RU示意 runtime. 这些是运行时的表, 蕴含 流程实例, 工作, 变量, 异步工作等运行中的数据. Activiti 只在流程实例执行过程中保留这些数据,在流程完结时就会删除这些记录. 这样运行时表能够始终很小速度很快
    • ACT_ID_*: ID 示意 identity. 这些表蕴含 身份信息. 比方用户, 组等等
    • ACT_HI_*: HI 示意 history. 这些表蕴含 历史数据. 比方历史流程实例, 变量, 工作等等
    • ACT_GE_*: 通用数据. 用于不同场景下

      数据库降级

  • 在执行更新之前要先应用数据库的 备份 性能备份数据库
  • 默认状况下, 每次构建流程引擎时都会进行版本检测. 这一切都在利用启动或 Activiti webapp 启动时产生. 如果 Activiti 发现数据库表的版本与依赖库的版本不同, 就会抛出异样
  • 对 activiti.cfg.xml 配置文件进行配置来降级:

    <beans ... >
    
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
      <!-- ... -->
      <property name="databaseSchemaUpdate" value="true" />
      <!-- ... -->
    </bean>
    
    </beans>
  • 而后, 把对应的数据库驱动放到 classpath 里. 降级利用的 Activiti 依赖, 启动一个新版本的 Activiti 指向蕴含旧版本的数据库, 将 databaseSchemaUpdate 设置为 true,Activiti 会主动将数据库表降级到新版本
  • 当发现依赖和数据库表版本不通过时, 也能够执行更新降级 DDL 语句
  • 也能够执行数据库脚本, 能够在 Activiti 下载页找到

    启用 Job 执行器

  • JobExecutor 是治理一系列线程的组件, 能够触发定时器(蕴含后续的异步音讯).
  • 在单元测试场景下, 很难应用多线程. 因而 API 容许 查问 Job(ManagementService.createJobQuery) 执行 Job (ManagementService.executeJob),
  • 因而 Job 能够在单元测试中管制, 要防止与 job 执行器抵触, 能够敞开它
  • 默认,JobExecutor 在流程引擎启动时就会激活. 如果不想在流程引擎启动后主动激活 JobExecutor, 能够设置

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

    配置邮件服务器

  • Activiti 反对在业务流程中发送邮件, 能够在配置中配置邮件服务器
  • 配置 SMTP 邮件服务器来发送邮件

    配置历史存储

  • Activiti 能够配置来定制历史存储信息

    <property name="history" value="audit" />

    表达式和脚本裸露配置

  • 默认状况下,activiti.cfg.xml和 Spring 配置文件中所有 bean 都能够在表达式和脚本中应用
  • 如果要限度配置文件中的 bean 的可见性, 能够通过配置流程引擎配置的 beans 来配置
  • ProcessEngineConfiguration的 beans 是一个 map.当指定了这个参数, 只有蕴含这个 map 中的 bean 能够在表达式和脚本中应用.通过在 map 中指定的名称来决定裸露的 bean

    配置部署缓存

  • 因为流程定义的数据是不会扭转的, 为了防止每次应用拜访数据库, 所有流程定义在解析之后都会被缓存
  • 默认状况下, 不会限度这个缓存. 如果想限度流程定义缓存, 能够增加如下配置

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

    这个配置会把默认的 HashMap 缓存替换成 LRU 缓存 来提供限度. 这个配置的最佳值跟流程定义的总数无关, 理论应用中会具体应用多少流程定义也无关

  • 也能够注入自定义的缓存实现, 这个 bean 必须实现 org.activiti.engine.impl.persistence.deploy.DeploymentCache 接口

    <property name="processDefinitionCache">
    <bean class="org.activiti.MyCache" />
    </property>
  • 相似的配置有 knowledgeBaseCacheLimitknowledgeBaseCache, 它们是配置规定缓存的. 只有 流程中应用规定工作时才用

    日志

  • 从 Activiti 5.12 开始, 所有日志 (activiti,spring,,mybatis 等等) 都转发给 slf4j 容许自定义日志实现
  • 引入 Maven 依赖 log4j 实现, 须要增加版本

    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    </dependency>
  • 应用 Maven 的实例, 疏忽版本

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

    映射诊断上下文

  • Activiti 反对 slf4j 的 MDC 性能, 如下的根底信息会传递到日志中记录:

    • 流程定义 ID: mdcProcessDefinitionID
    • 流程实例 ID: mdcProcessInstanceID
    • 分支 ID: mdcexecutionId
  • 默认不会记录这些信息, 能够配置日志应用冀望的格局来显示它们, 扩大通常的日志信息. 比方, 通过 log4j 配置定义会让日志显示下面的信息:

     log4j.appender.consoleAppender.layout.ConversionPattern =ProcessDefinitionId=%X{mdcProcessDefinitionID}
    executionId=%X{mdcExecutionId}mdcProcessInstanceID=%X{mdcProcessInstanceID} mdcBusinessKey=%X{mdcBusinessKey} %m%n"

    当零碎进行高风险工作, 日志必须严格查看时, 这个性能就十分有用, 要应用日志剖析的状况

    事件处理

  • Activiti 中实现了一种事件机制, 它容许在引擎触发事件时取得揭示
  • 为对应的事件类型注册监听器, 在这个类型的任何工夫触发时都会收到揭示:

    • 能够增加引擎范畴的事件监听器, 能够通过配置增加引擎范畴的事件监听器在运行阶段应用 API
    • 增加 event-listener 到特定流程定义的 BPMN XML 中
  • 所有散发的事件, 都是 org.activiti.engine.delegate.event.ActivitiEvent 的子类. 事件蕴含 type,executionId,processInstanceId 和 processDefinitionId. 对应的事件会蕴含 事件产生时对应上下文的额定信息

    事件监听器实现

  • 实现事件监听器要实现org.activiti.engine.delegate.event.ActivitiEventListener.
  • 上面监听器的实现会把所有监听到的事件打印到规范输入中, 包含 job 执行的事件异样:

    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;
    }
    }

    isFailOnException(): 决定了当事件散发时onEvent(..) 办法抛出异样时的行为

    • 返回 false, 会疏忽异样
    • 返回 true, 异样不会疏忽, 持续向上流传, 迅速导致以后命令失败
    • 当事件是一个 API 调用的一部分时(或其余事务性操作, 比方 job 执行), 事务就会回滚
    • 当事件监听器中的行为不是业务性时,倡议返回 false
  • activiti 提供了一些根底的实现, 实现了事件监听器的罕用场景能够用来作为基类或监听器实现的样例

    • org.activiti.engine.delegate.event.BaseEntityEventListener:

      • 这个事件监听器的基类能够用来监听实体相干的事件, 能够针对某一类型实体, 也能够是全副实体
      • 暗藏了类型检测, 并提供了三个须要重写的办法:

        • onCreate(..)
        • onUpdate(..)
        • onDelete(..)
        • 当实体创立, 更新, 或删除时调用
      • 对于其余实体相干的事件, 会调用onEntityEvent(..)

        事件监听器的配置装置

  • 把事件监听器配置到流程引擎配置中, 会在流程引擎启动时激活, 并在引擎启动过程中继续工作
  • eventListeners属性须要 org.activiti.engine.delegate.event.ActivitiEventListener 的队列

    • 通常, 咱们能够申明一个外部的 bean 定义, 或应用 ref 援用已定义的 bean. 上面的代码, 向配置增加了一个事件监听器,任何事件触发时都会揭示它,无论事件是什么类型:

      <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 参数
    • map 的 key 是逗号分隔的事件名或独自的事件名
    • map 的 value 是 org.activiti.engine.delegate.event.ActivitiEventListener 队列
  • 上面的代码演示了向配置中增加一个事件监听器, 能够监听 job 执行胜利或失败:

    <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 属性), 依照它们在 list 中的秩序
    • 而后, 会调用所有对应类型的监听器(typedEventListeners 属性), 对应类型的事件被触发

      运行阶段增加监听器

  • 通过 API:RuntimeService, 在运行阶段增加或删除额定的事件监听器:

    /**
     * Adds an event-listener which will be notified of ALL events by the dispatcher.
     * @param listenerToAdd the listener to add
     */
    void addEventListener(ActivitiEventListener listenerToAdd);
    
    /**
     * Adds an event-listener which will only be notified when an event occurs, which type is in the given types.
     * @param listenerToAdd the listener to add
     * @param types types of events the listener should be notified for
     */
    void addEventListener(ActivitiEventListener listenerToAdd, ActivitiEventType... types);
    
    /**
     * Removes the given listener from this dispatcher. The listener will no longer be notified,
     * regardless of the type(s) it was registered for in the first place.
     * @param listenerToRemove listener to remove
     */
     void removeEventListener(ActivitiEventListener listenerToRemove);
  • 运行阶段增加的监听器引擎重启后就隐没

    流程定义增加监听器

  • 特定流程定义增加监听器:

    • 监听器只会监听与这个流程定义相干的事件以及这个流程定义上发动的所有流程实例的事件
  • 监听器实现:

    • 能够应用全类名定义
    • 援用实现了监听器接口的表达式
    • 配置为抛出一个 message,signal,errorBPMN 事件

      监听器执行自定义逻辑
  • 上面代码为一个流程定义增加了两个监听器:

    • 第一个监听器会接管所有类型的事件, 它是通过全类名定义的
    • 第二个监听器只接管作业胜利或失败的事件, 它应用了定义在流程引擎配置中的 beans 属性中的一个 bean

      <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>
  • 对于实体相干的事件, 也能够设置为针对某个流程定义的监听器, 实现只监听产生在某个流程定义上的某个类型实体事件. 上面的代码演示了如何实现这种性能:

    • 第一个例子: 用于监听所有实体事件
    • 第二个例子: 用于监听特定类型的事件

      <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

      监听抛出 BPMN 事件
  • 另一种处理事件的办法是 抛出一个 BPMN 事件:

    • 只针对与抛出一个 activiti 事件类型的 BPMN 事件, 抛出一个 BPMN 事件, 在流程实例删除时, 会导致一个谬误
  • 上面的代码演示了如何在流程实例中抛出一个 signal, 把 signal 抛出到内部流程 (全局), 在流程实例中抛出一个音讯事件, 在流程实例中抛出一个谬误事件. 除了应用classdelegateExpression, 还应用了 throwEvent 属性, 通过额定属性, 指定了抛出事件的类型

    <process id="testEventListeners">
    <extensionElements>
      <activiti:eventListener throwEvent="signal" signalName="My signal" events="TASK_ASSIGNED" />
    </extensionElements>
    </process>
    <process id="testEventListeners">
    <extensionElements>
      <activiti:eventListener throwEvent="globalSignal" signalName="My signal" events="TASK_ASSIGNED" />
    </extensionElements>
    </process>
    <process id="testEventListeners">
    <extensionElements>
      <activiti:eventListener throwEvent="message" messageName="My message" events="TASK_ASSIGNED" />
    </extensionElements>
    </process>
    <process id="testEventListeners">
    <extensionElements>
      <activiti:eventListener throwEvent="error" errorCode="123" events="TASK_ASSIGNED" />
    </extensionElements>
    </process>
  • 如果须要申明额定的逻辑, 是否抛出 BPMN 事件, 能够扩大 activiti 提供的监听器类:

    • 在子类中重写isValidEvent(ActivitiEvent event), 能够避免抛出 BPMN 事件. 对应的类是:

      • org.activiti.engine.impl.bpmn.helper.MessageThrowingEventListener
      • org.activiti.engine.test.api.event.SignalThrowingEventListenerTest
      • org.activiti.engine.impl.bpmn.helper.ErrorThrowingEventListener

        流程定义监听器留神点
  • 事件监听器只能申明在 process 元素中, 作为 extensionElements 的子元素. 监听器不能定义在流程的单个 activity 下
  • delegateExpression中的表达式无法访问 execution 上下文, 这与其余表达式不同 (比方 gateway). 它 只能援用定义在流程引擎配置的 beans 属性中申明的 bean, 或者应用 spring(未应用 beans 属性)中所有 实现了监听器接口的 spring-bean
  • 应用监听器的 class 属性时, 只会创立一个实例. 监听器实现不会依赖成员变量, 是多线程平安的
  • 当一个非法的事件类型用在 events 属性或 throwEvent 中时, 流程定义公布时就会抛出异样(会导致部署失败)

    • 如果 class 或 delegateExecution 由问题: 类不存在, 不存在的 bean 援用, 或代理类没有实现监听器接口

      • 在流程启动时抛出异样
      • 在第一个无效的流程定义事件被监听器接管时
    • 所以要保障援用的类正确的放在 classpath 下, 表达式也要援用一个无效的实例

      通过 API 散发事件

  • Activiti 咱们提供了通过 API 应用事件机制的办法, 容许触发定义在引擎中的任何自定义事件
  • 倡议只触发类型为 CUSTOMActivitiEvents.能够通过 RuntimeService 触发事件:

    /**
     * Dispatches the given event to any listeners that are registered.
     * @param event event to dispatch.
     *
     * @throws ActivitiException if an exception occurs when dispatching the event or when the {@link ActivitiEventDispatcher}
     * is disabled.
     * @throws ActivitiIllegalArgumentException when the given event is not suitable for dispatching.
     */
     void dispatchEvent(ActivitiEvent event);

    反对的事件类型

  • 引擎中每个事件类型都对应 org.activiti.engine.delegate.event.ActivitiEventType 中的一个枚举值
事件名称 事件形容 事件类型
ENGINE_CREATED 监听器监听的流程引擎曾经创立, 筹备好承受 API 调用 ActivitiEvent
ENGINE_CLOSED 监听器监听的流程引擎曾经敞开, 不再承受 API 调用 ActivitiEvent
ENTITY_CREATED 创立了一个新实体, 实体蕴含在事件中 ActivitiEntityEvent
ENTITY_INITIALIZED 创立了一个新实体, 初始化也实现了. 如果这个实体的创立会蕴含子实体的创立, 这个事件会在子实体都创立 / 初始化实现后被触发, 这是与 ENTITY_CREATED 的区别 ActivitiEntityEvent
ENTITY_UPDATED 更新了已存在的实体, 实体蕴含在事件中 ActivitiEntityEvent
ENTITY_DELETED 删除了已存在的实体, 实体蕴含在事件中 ActivitiEntityEvent
ENTITY_SUSPENDED 暂停了已存在的实体, 实体蕴含在事件中. 会被 ProcessDefinitions,ProcessInstances 和 Tasks 抛出 ActivitiEntityEvent
ENTITY_ACTIVATED 激活了已存在的实体, 实体蕴含在事件中. 会被 ProcessDefinitions,ProcessInstances 和 Tasks 抛出 ActivitiEntityEvent
JOB_EXECUTION_SUCCESS 作业执行胜利,job 蕴含在事件中 ActivitiEntityEvent
JOB_EXECUTION_FAILURE 作业执行失败, 作业和异样信息蕴含在事件中 ActivitiEntityEvent
ActivitiExceptionEvent
JOB_RETRIES_DECREMENTED 因为作业执行失败, 导致重试次数缩小. 作业蕴含在事件中 ActivitiEntityEvent
TIMER_FIRED 触发了定时器,job 蕴含在事件中 ActivitiEntityEvent
JOB_CANCELED 勾销了一个作业. 事件蕴含勾销的作业. 作业能够通过 API 调用勾销, 工作实现后对应的边界定时器也会勾销, 在新流程定义公布时也会勾销 ActivitiEntityEvent
ACTIVITY_STARTED 一个节点开始执行 ActivitiActivityEvent
ACTIVITY_COMPLETED 一个节点胜利完结 ActivitiActivityEvent
ACTIVITY_SIGNALED 一个节点收到了一个信号 ActivitiSignalEvent
ACTIVITY_MESSAGE_RECEIVED 一个节点收到了一个音讯. 在节点收到音讯之前触发, 收到后, 会触发 ACTIVITY_SIGNALACTIVITY_STARTED, 这会依据节点的类型: 边界事件, 事件子流程开始事件 ActivitiMessageEvent
ACTIVITY_ERROR_RECEIVED 一个节点收到了一个谬误事件. 在节点理论处理错误之前触发, 事件的 activityId 对应着 处理错误的节点.这个事件后续会是 ACTIVITY_SIGNALLEDACTIVITY_COMPLETE, 如果谬误发送胜利的话 ActivitiErrorEvent
UNCAUGHT_BPMN_ERROR 抛出了未捕捉的 BPMN 谬误. 流程没有提供针对这个谬误的处理器.事件的 activityId 为空 ActivitiErrorEvent
ACTIVITY_COMPENSATE 一个节点将要被弥补. 事件蕴含了将要执行弥补的节点 id ActivitiActivityEvent
VARIABLE_CREATED 创立了一个变量. 事件蕴含变量名, 变量值和对应的分支或工作(如果存在) ActivitiVariableEvent
VARIABLE_UPDATED 更新了一个变量. 事件蕴含变量名, 变量值和对应的分支或工作(如果存在) ActivitiVariableEvent
VARIABLE_DELETED 删除了一个变量. 事件蕴含变量名, 变量值和对应的分支或工作(如果存在) ActivitiVariableEvent
TASK_ASSIGNED 工作被调配给了一个人员. 事件蕴含工作 ActivitiEntityEvent
TASK_CREATED 创立了新工作. 它位于 ENTITY_CREATE 事件之后. 当工作是由流程创立时, 这个事件会在 TaskListener 执行之前被执行 ActivitiEntityEvent
TASK_COMPLETED 工作实现. 它会在 ENTITY_DELETE 事件之前触发. 当工作是流程一部分时, 事件会在流程持续运行之前, 后续事件将是 ACTIVITY_COMPLETE, 对应着实现工作的节点 ActivitiEntityEvent
TASK_TIMEOUT 工作已超时. 在 TIMER_FIRED 事件之后, 会触发用户工作的超时事件, 当这个任务分配了一个定时器的时候 ActivitiEntityEvent
PROCESS_COMPLETED 流程已完结. 在最初一个节点的 ACTIVITY_COMPLETED 事件之后触发. 当流程达到的状态, 没有任何后续连线时, 流程就会完结 ActivitiEntityEvent
MEMBERSHIP_CREATED 用户被增加到一个组里. 事件蕴含了用户和组的 id ActivitiMembershipEvent
MEMBERSHIP_DELETED 用户被从一个组中删除. 事件蕴含了用户和组的 id ActivitiMembershipEvent
MEMBERSHIPS_DELETED 所有成员被从一个组中删除. 在成员删除之前触发这个事件, 所以他们都是能够拜访的. 因为性能方面的思考, 不会为每个成员触发独自的 MEMBERSHIP_DELETED 事件 ActivitiMembershipEvent
  • 引擎外部所有ENTITY_* 事件都是与实体相干的, 实体事件与实体的对应关系:

    • [ENTITY_CREATED],[ENTITY_INITIALIZED],[ENTITY_DELETED]:

      • Attachment
      • Comment
      • Deployment
      • Execution
      • Group
      • IdentityLink
      • Job
      • Model
      • ProcessDefinition
      • ProcessInstance
      • Task
      • User
    • ENTITY_UPDATED:

      • Attachment
      • Deployment
      • Execution
      • Group
      • IdentityLink
      • Job
      • Model
      • ProcessDefinition
      • ProcessInstance
      • Task
      • User
    • ENTITY_SUSPENDED, ENTITY_ACTIVATED:

      • ProcessDefinition
      • ProcessInstance
      • Execution
      • Task

        留神

  • 只有同一个流程引擎中的事件会发送给对应的监听器
  • 如果有很多引擎在同一个数据库运行, 事件只会发送给注册到对应引擎的监听器. 其余引擎产生的事件不会发送给这个监听器, 无论实际上它们运行在同一个或不同的 JVM 中
  • 对应的事件类型都蕴含对应的实体. 依据类型或事件, 这些实体不能再进行更新 (比方, 当实例以被删除). 可能的话, 应用事件提供的EngineServices 来以平安的形式来操作引擎. 即使如此, 也要小心的对事件对应的实体进行更新, 操作
  • 没有对应历史的实体事件,因为它们都有运行阶段的对应实体
退出移动版