activiti 监听器动态设置审批人(activiti 任务监听器)
Activiti工作流配置创建ProcessEngineProcessEngineConfiguration bean数据库配置定义数据库配置参数使用javax.sql.DataSource配置JNDI数据库配置JNDI的使用JNDI的配置Activiti支持的数据库创建数据库表数据库表名理解数据库升级启用Job执行器配置邮件服务器配置历史存储表达式和脚本暴露配置配置部署缓存日志映射诊断上下文事件
Activiti工作流配置创建ProcessEngineProcessEngineConfiguration bean数据库配置定义数据库配置参数使用javax.sql.DataSource配置JNDI数据库配置JNDI的使用JNDI的配置Activiti支持的数据库创建数据库表数据库表名理解数据库升级启用Job执行器配置邮件服务器配置历史存储表达式和脚本暴露配置配置部署缓存日志映射诊断上下文事件处理事件监听器实现事件监听器的配置安装运行阶段添加监听器流程定义添加监听器监听器执行自定义逻辑监听抛出BPMN事件流程定义监听器注意点通过API分发事件支持的事件类型注意创建ProcessEngine
它会在classpath下搜索activiti.cfg.xml,并基于这个文件中的配置构建引擎 配置文件中使用的ProcessEngineConfiguration可以通过编程方式创建,可以配置不同的bean id 如果不使用配置文件进行配置,就会基于默认创建配置 这个bean会用来构建ProcessEngine. 有多个类可以用来定义processEngineConfiguration. 这些类对应不同的环境,并设置了对应的默认值: 这个配置会把默认的HashMap缓存替换成LRU缓存来提供限制. 这个配置的最佳值跟流程定义的总数有关,实际使用中会具体使用多少流程定义也有关 当系统进行高风险任务,日志必须严格检查时,这个功能就非常有用,要使用日志分析的情况 isFailOnException(): 决定了当事件分发时onEvent(…) 方法抛出异常时的行为 分发事件的顺序是由监听器添加时的顺序决定的 事件名称 事件描述 事件类型 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 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_SIGNAL或ACTIVITY_STARTED, 这会根据节点的类型:边界事件,事件的流程开始事件 ActivitiMessageEvent ACTIVITY_ERROR_RECEIVED 一个节点收到了一个错误事件.在节点实际处理错误之前触发, 事件的activityId对应着处理错误的节点.这个事件后续会是ACTIVITY_SIGNALLED或ACTIVITY_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
Activiti工作流配置创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine()
<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.createProcessEngineConfigurationFromResourceDefault();ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String resource);ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String resource, String beanName);// 配置不同的bean idProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(InputStream inputStream);ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(InputStream inputStream, String beanName);
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
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
数据库配置
定义数据库配置参数
使用javax.sql.DataSource配置
<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>
JNDI数据库配置
JNDI的使用
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/activitiDB"/></bean>
<?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>
<?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>
JNDI的配置
<?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支持的数据库
创建数据库表
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时不会使用. 注意这也会引用一些需要把数据保存到历史表中的功能
数据库表名理解
数据库升级
<beans ... > <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <!-- ... --> <property name="databaseSchemaUpdate" value="true" /> <!-- ... --> </bean></beans>
启用Job执行器
<property name="jobExecutorActivate" value="false" />
配置邮件服务器
配置历史存储
<property name="history" value="audit" />
表达式和脚本暴露配置
配置部署缓存
<property name="processDefinitionCacheLimit" value="10" />
<property name="processDefinitionCache"> <bean class="org.activiti.MyCache" /></property>
日志
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId></dependency>
<dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId></dependency>
映射诊断上下文
log4j.appender.consoleAppender.layout.ConversionPattern =ProcessDefinitionId=%X{mdcProcessDefinitionID}executionId=%X{mdcExecutionId}mdcProcessInstanceID=%X{mdcProcessInstanceID} mdcBusinessKey=%X{mdcBusinessKey} %m%n"
事件处理
事件监听器实现
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; }}
事件监听器的配置安装
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> ... <property name="eventListeners"> <list> <bean class="org.activiti.engine.example.MyEventListener" /> </list> </property></bean>
<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>
运行阶段添加监听器
/** * 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);
流程定义添加监听器
监听器执行自定义逻辑
<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>
监听抛出BPMN事件
<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>
流程定义监听器注意点
通过API分发事件
/** * 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);
支持的事件类型
ActivitiExceptionEvent注意