一位菜鸟程序猿,学习Activiti的总结

3,494 阅读6分钟

本文是个人学习后的总结,主要总结了几个核心Api的作用以及常用配置的说明。

喜欢的朋友可以点个订阅,大家一起学习进步。

一、什么是Activiti

  activiti 是一个业务流程管理的开源框架,支持BPMN2.0流程定义协议。其主要功能有流程定义、流程部署、流程执行、用户群组管理、历史记录查询等功能。越是复杂的业务越是需要流程管理的工具,activiti就是很好的选择,从oa系统的审批到电商系统的购物,这些复杂的业务场景都能看到Activiti的身影。硬编码复杂的业务时,每一步的流转判断充满了风险,稍有不慎就得不到想要的结果,而问题追踪起来也非常麻烦。而基于activiti编写复杂的业务时,按照规范画出流程定义文件,业务可见即可得一目了然,大大降低了复杂业务出错的概率,剩下的事情就交给activiti去执行,它会严格按照流程的定义去执行。

二、为什么选Activiti

  1. actitvti支持BPMN2.0流程定义协议。
  2. activiti与Spring集成非常方便,甚至实现了Starter,集成SpringBoot更为方便。
  3. activiti的社区活跃,github提交记录频繁,不断的有开发者给他添砖加瓦。
  4. activiti的提供的api非常丰富,能够满足绝大部分的业务场景。

三、Activiti核心Api

  activiti给使用者提供了大量的接口,这些接口能够完成从流程部署、流程运行以及历史流程记录查询的所有操作。主要的api有一下七个:

  1. RepositoryService,主要作用,部署流程定义文件,管理流程定义实例。
  2. RuntimeService,主要作用,启动流程,管理流程实例,设置获取流程变量。
  3. TaskService,主要作用,处理任务、设置任务候选人(组)、指定任务处理人(组)、设置附件等。
  4. FormService,主要作用,获取任务的表单数据、提交完成一个任务、启动流程。
  5. HistoryService,主要作用,查询流程历史记录、事件记录、变量记录。
  6. IdentityService,主要作用,创建用户、创建组、查询用户(组)。
  7. ManagementService,主要作用,执行自定义命令、查询底层实体、数据表、提供更多的扩展功能。

四、Activiti配置说明

  以下的配置是与Spring集成时的XML文件,如果集成SpingBoot,对应的Bean也可以基于注解的形式在SpringBoot项目中进行配置。也可以集成activiti实现的Starter,这样的话项目会根据yml文件自动装配常用的Bean,提供核心api。

<?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">
    <!-- 设置数据源, 指定项目中配置的数据源的bean -->
    <property name="dataSource" ref="dataSource"/>

    <!-- 设置项目启动数据库表的更新策略 -->
    <!--flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。-->
    <!--true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。-->
    <!--create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。-->
    <!--drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。-->
    <property name="databaseSchemaUpdate" value="true"/>

    <!-- 为所有的表名加前缀 -->
    <!--<property name="databaseTablePrefix" value="t_" />-->

    <!-- 指定数据库类型 -->
    <property name="databaseType" value="mysql" />

    <!-- 配置历史记录保存的级别 -->
    <!--none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。-->
    <!--activity:级别高于none,保存流程实例与流程行为,其他数据不保存。-->
    <!--audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。-->
    <!--full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。-->
    <property name="history" value="full"/>

    <!-- 配置是否使用历史记录相关的表 -->
    <property name="dbHistoryUsed" value="true"/>

    <!-- 配置是否使用用户权限相关的表 -->
    <property name="dbIdentityUsed" value="true"/>

    <!--配置自定义命令拦截器,配置到默认拦截器之前执行-->
    <property name="customPreCommandInterceptors">
      <list>
        <!-- 拦截器需要实现 AbstractCommandInterceptor 抽象类 -->
        <bean class="com.fbl.activiti6spring.interceptor.ExecutionTimeInterceptor"/>
      </list>
    </property>

    <!--配置自定义命令拦截器,配置到默认拦截器之后执行-->
    <property name="customPostCommandInterceptors">
      <list>
        <bean class="com.fbl.activiti6spring.interceptor.ExecutionTimeInterceptor"/>
      </list>
    </property>

    <!-- 设置是否开启异步执行功能,开启后可以实现定时开启流程等功能 -->
    <property name="asyncExecutorActivate" value="true"/>
    <!-- 设置异步任务的线程池 -->
    <property name="asyncExecutor">
      <bean class="org.activiti.engine.impl.asyncexecutor.DefaultAsyncJobExecutor">
        <!-- 指定一个executorService(线程池)bean -->
        <property name="executorService" ref="executorService"/>
      </bean>
    </property>

    <!-- 配置自定义事件监听器,在activiti中定义了许多事件,在事件发生时会被监听器监听到,比如流程启动时间、流程结束事件。也可以自定义一个事件,runtimeService.dispatchEvent()手动发出一个事件 -->
    <property name="eventListeners">
      <list>
        <!-- 事件监听器需要实现ActivitiEventListener接口 -->
        <bean class="com.fbl.activiti6spring.event.ProcessInstanceEventListener"/>
        <bean class="com.fbl.activiti6spring.event.CustomEventListener"/>
      </list>
    </property>

    <!--只监听指定类型的事件,PROCESS_STARTED是流程开始事件-->
    <!--<property name="typedEventListeners">-->
    <!--  <map>-->
    <!--    <entry key="PROCESS_STARTED">-->
    <!--      <bean class="com.fbl.activiti.activitidome.event.ProcessInstanceEventListener"/>-->
    <!--    </entry>-->
    <!--  </map>-->
    <!--</property>-->

    <!-- 配置事务管理器 -->
    <property name="transactionManager" ref = "transactionManager"/>

  </bean>


  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/activiti6?useSSL=false&amp;characterEncoding=UTF-8" />
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="username" value="root" />
    <property name="password" value="1234" />
    <property name="initialSize" value="1" />
    <property name="maxActive" value="10" />
    <property name="filters" value="stat,slf4j" />
  </bean>

  <!-- 配置Spring事务管理器 -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
  </bean>

  <!-- 配置线程池,提供异步任务执行的环境 -->
  <bean id="executorService" class="org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean">
    <property name="threadNamePrefix" value="activiti_"/>
    <property name="corePoolSize" value="5" />
    <property name="maxPoolSize" value="10" />
    <property name="queueCapacity" value="20" />
    <property name="rejectedExecutionHandler">
      <bean class="java.util.concurrent.ThreadPoolExecutor$AbortPolicy"/>
    </property>
  </bean>

  <!-- 创建流程核心Api工厂Bean -->
  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
  </bean>
  
  <!-- 将activiti的测试Rule,注册到容器 -->
  <bean id="activitiRule" class="org.activiti.engine.test.ActivitiRule">
    <!--<property name="processEngineConfiguration" ref="processEngineConfiguration"/>-->
    <property name="processEngine" ref="processEngine" />
  </bean>

  <!-- 把想要使用的Activiti核心Api 注册到容器中 -->
  <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
  <bean id="formService" factory-bean="processEngine" factory-method="getFormService"/>
  <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
  <bean id="helloWordServices" class="com.fbl.activiti6spring.services.HelloWordServices" />

</beans>