开源地址:https://github.com/bluejoe2008/openwebflow(欢迎star)
1. OpenWebFlow概述
OpenWebFlow是基于Activiti扩展的工作流引擎。Activiti (官方网站http://activiti.org/,代码托管在https://github.com/Activiti/Activiti)是一个新兴的基于 Apache 许可的支持 BPMN 2.0 标准的开源 BPM 产品,它是一个轻量级,可嵌入的 BPM 引擎,并且提供了功能丰富的开发和流程设计工具。OpenWebFlow与业务应用系统之间的关系如下图所示。
相对于Activiti,OpenWebFlow扩展的功能包括:
1) 完全接管了Activiti对活动(activity)权限的管理。
Activiti允许在设计model的时候指定每个活动的执行权限,但是,业务系统可能需要根据实际情况动态设置这些任务的执行权限(如:动态的Group)。OpenWebFlow完全实现了与流程定义时期的解耦,即用户对活动的访问控制信息单独管理(而不是在流程定义中预先写死),这样有利于动态调整权限,详见自定义活动权限管理;
2) 完全接管了Activiti对用户表(IDENTITY_XXX表)的管理。
在标准的工作流定义中,每个节点可以指定其候选人和候选用户组,但是比较惨的是,Activiti绑架了用户信息表的设计!这个是真正致命的,因为几乎每个业务系统都会属于自己的用户信息结构(包括User/Group/Membership),但不一定它存储在Activiti喜欢的那个库中,表的结构也不一定一样,有的时候,某些信息(如:动态的Group)压根儿就不采用表来存储。OpenWebFlow剥离了用户信息表的统一管理,客户程序可以忘掉Activiti的用户表、群组表、成员关系表,详见自定义用户成员关系管理;
3) 允许运行时定义activity!
彻底满足“中国特色”,并提供了安全的(同时也是优雅的)催办、代办、加签(包括前加签/后加签)、自由跳转(包括前进/后)、分裂节点等功能;
2. 快速上手
2.1 引入OpenWebFlow框架
2.1.1 以jar的方式引入OpenWebFlow
OpenWebFlow的发布形式是一组正常的jar,其中openwebflow-core.XXX.jar包含了核心的工作流控制模块,以及基于内存的管理器实现模块。
此外,OpenWebFlow还提供了几个jar:openwebflow-mgr-hibernate.XXX.jar,openwebflow-mgr-mybatis.XXX.jar,它们提供了管理器的SQL实现模块,分别选取hibernate和mybatis作为ORM模型。还有一个是openwebflow-mgr-test.XXX.jar,它包含了几个测试类。
最新版本的下载地址:
https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-core/target/openwebflow-core-0.9-SNAPSHOT.jar注意这些jar具有较多的依赖, https://gitee.com/bluejoe/openwebflow/tree/master/openwebflow-core/target/lib列举了所有的依赖包如下:
- activation-1.1.jar
- activiti-bpmn-converter-5.16.1.jar
- activiti-bpmn-layout-5.16.1.jar
- activiti-bpmn-model-5.16.1.jar
- activiti-crystalball-5.16.1.jar
- activiti-engine-5.16.1.jar
- activiti-explorer-5.16.1.jar
- activiti-image-generator-5.16.1.jar
- activiti-json-converter-5.16.1.jar
- activiti-process-validation-5.16.1.jar
- activiti-simple-workflow-5.16.1.jar
- activiti-spring-5.16.1.jar
- aopalliance-1.0.jar
- commons-collections-2.0.jar
- commons-dbcp-1.4.jar
- commons-email-1.2.jar
- commons-io-2.4.jar
- commons-lang-2.6.jar
- commons-lang3-3.3.2.jar
- commons-logging-1.1.1.jar
- commons-pool-1.5.4.jar
- dcharts-widget-0.10.0.jar
- groovy-all-2.1.3.jar
- h2-1.3.168.jar
- hamcrest-core-1.3.jar
- imgscalr-lib-4.2.jar
- jackson-annotations-2.2.3.jar
- jackson-core-2.2.3.jar
- jackson-databind-2.2.3.jar
- javaGeom-0.11.1.jar
- jcl-over-slf4j-1.7.6.jar
- jgraphx-1.10.4.1.jar
- joda-time-2.1.jar
- junit-4.12.jar
- log4j-1.2.17.jar
- mail-1.4.1.jar
- mybatis-3.2.8.jar
- mybatis-spring-1.2.2.jar
- mysql-connector-java-5.1.32.jar
- servlet-api-2.5.jar
- slf4j-api-1.7.2.jar
- slf4j-jdk14-1.7.2.jar
- slf4j-log4j12-1.7.6.jar
- spring-aop-3.2.4.RELEASE.jar
- spring-beans-3.2.4.RELEASE.jar
- spring-context-3.2.4.RELEASE.jar
- spring-core-3.2.4.RELEASE.jar
- spring-expression-3.2.4.RELEASE.jar
- spring-jdbc-3.2.4.RELEASE.jar
- spring-orm-3.2.4.RELEASE.jar
- spring-tx-3.2.4.RELEASE.jar
- spring-web-3.2.4.RELEASE.jar
- spring-webmvc-3.2.4.RELEASE.jar
- vaadin-6.8.8.jar
2.1.2 以maven的方式引入OpenWebFlow
以maven的方式引入OpenWebFlow比较简单,pom.xml中的依赖项写成:
<dependency>
<groupId>org.openwebflow</groupId>
<artifactId>openwebflow-core </artifactId>
<version>0.9-SNAPSHOT</version>
</dependency>
在引入依赖项之前可能需要先在本地仓库中安装OpenWebFlow项目。具体操作是在eclipse中选择OpenWebFlow项目,【右键菜单】【Maven】【install】。
2.2 配置文件
准备SpringIoC配置文件,分别是settings.properties 、activiti.cfg.core.xml和activiti.cfg.mem.xml(或者是activiti.cfg.sql.XXX.xml):
- settings.properties:公共属性设置
- activiti.cfg.core.xml:用以配置工作流引擎的基本配置信息;
- activiti.cfg.mem.xml:用以定义一些用以支持OpenWebFlow工作的manager,注意名字中的mem,它暗示着仅提供了那些manager的基于内存实现的版本,类似的配置文件还可以是activiti.cfg.sql.XXX.xml;
2.2.1 settings.properties
settings.properties文件是一个正常的属性文件,用以spring IOC文件加载。如下是一个属性文件的内容:
mail.host=smtp.bluejoe.cn
mail.port=25
mail.username=sdb-support@cnic.cn
mail.password=sdbsupport
mail.from=sdb-support@cnic.cn
model.dir=../models
alarm.mail.template=classpath:/alarm-template.txt
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=none
activitidb.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000
activitidb.driver=org.hDriver
activitidb.username=sa
activitidb.password=
owfdb.url=jdbc:mysql://localhost:3306/openwebflow?useUnicode=true&characterEncoding=UTF-8
owfdb.driver=com.mysql.jdbc.Driver
owfdb.username=root
owfdb.password=1
各属性的含义如下:
属性名 |
示例值 |
含义 |
mail.host |
smtp.bluejoe.cn |
催办邮件发件服务器主机地址 |
mail.port |
25 |
催办邮件发件服务器端口号 |
mail.username |
sdb-support@cnic.cn |
催办邮件发件账号名 |
mail.password |
sdbsupport |
催办邮件发件账号密码 |
mail.from |
sdb-support@cnic.cn |
催办邮件发件人 |
model.dir |
../models |
自动加载的BPMN模型路径 |
alarm.mail.template |
classpath:/alarm-template.txt |
催办邮件正文模板 |
hibernate.dialect |
org.hibernate.dialect.MySQLDialect |
Hibernate方言 |
hibernate.hbm2ddl.auto |
none |
Hibernate DDL设置 |
activitidb.url |
jdbc:h2:mem:activiti;DB_CLOSE_DELAY |
Activiti数据库JDBC URL |
activitidb.driver |
org.h2.Driver |
Activiti数据库JDBC驱动 |
activitidb.username |
sa |
Activiti数据库账号名 |
activitidb.password |
|
Activiti数据库账号密码 |
owfdb.url |
jdbc:mysql://localhost:3306/openwebflow?useUnicode |
OpenWebFlow数据库JDBC URL |
owfdb.driver |
com.mysql.jdbc.Driver |
OpenWebFlow数据库JDBC驱动 |
owfdb.username |
root |
OpenWebFlow数据库账号名 |
owfdb.password |
1 |
OpenWebFlow数据库账号密码 |
2.2.2 activiti.cfg.core.xml配置
activiti.cfg.core.xml的配置与Activiti要求的那个配置文件有点相似,但可以多一些内容,如下是个例子:
<!-- 工作流核心数据库配置 -->
<bean id="activitiDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${activitidb.driver}" />
<property name="url" value="${activitidb.url}" />
<property name="username" value="${activitidb.username}" />
<property name="password" value="${activitidb.password}" />
<property name="initialSize" value="20" />
<property name="maxActive" value="50" />
<property name="maxIdle" value="20" />
<property name="minIdle" value="10" />
</bean>
<!-- 任务催办配置 -->
<bean id="myTaskAlarmService" class="org.openwebflow.alarm.impl.TaskAlarmServiceImpl">
<!-- 截止日期提前量 -->
<property name="periodInAdvance" value="P2D" />
<!-- 设置消息通知机制 -->
<property name="messageNotifier">
<!-- 采用邮件发送 -->
<bean class="org.openwebflow.alarm.impl.MailMessageNotifier">
<property name="subjectTemplate" value="请尽快处理#{'$'}{task.name}任务" />
<property name="messageTemplateResource" value="${alarm.mail.template}" />
<property name="mailSender">
<bean class="org.openwebflow.alarm.impl.MailSender">
<property name="serverHost" value="${mail.host}" />
<property name="serverPort" value="${mail.port}" />
<property name="authUserName" value="${mail.username}" />
<property name="authPassword" value="${mail.password}" />
<property name="mailFrom" value="${mail.from}" />
</bean>
</property>
</bean>
</property>
<property name="membershipManager" ref="myMembershipManager" />
<property name="userDetailsManager" ref="myUserDetailsManager" />
<property name="taskNotificationManager" ref="myTaskNotificationManager" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="activitiDataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 配置对象 -->
<bean id="processEngineConfiguration" class="org.openwebflow.cfg.ProcessEngineConfigurationEx">
<property name="dataSource" ref="activitiDataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="false" />
<property name="startEngineEventListeners">
<list>
<!-- 加载自定义表单元素类型 -->
<bean class="org.openwebflow.cfg.LoadDummyFormTypes">
<property name="typeNames" value="user" />
</bean>
<!-- 自定义成员关系管理 -->
<bean class="org.openwebflow.cfg.ReplaceMembershipManager">
<property name="customMembershipManager" ref="myMembershipManager" />
</bean>
<!-- 自定义活动权限管理 -->
<bean class="org.openwebflow.cfg.ReplaceTaskAssignmentHandler">
<!-- 授权处理器列表,会组成一个链,越靠后优先级越高(越靠外) -->
<property name="handlers">
<list>
<!-- 自定义授权项列表 -->
<bean
class="org.openwebflow.assign.permission.ActivityPermissionAssignmentHandler">
<property name="activityPermissionManager" ref="myActivityPermissionManager" />
</bean>
<!-- 允许授权代理 -->
<bean
class="org.openwebflow.assign.delegation.TaskDelagationAssignmentHandler">
<property name="delegationManager" ref="myDelegationManager" />
<property name="membershipManager" ref="myMembershipManager" />
<property name="hideDelegated" value="false" />
</bean>
</list>
</property>
</bean>
<!-- 自动导入流程模型 -->
<bean class="org.openwebflow.cfg.ImportDefinedProcessModels">
<property name="modelDir" value="${model.dir}" />
</bean>
<!-- 启动催办管理器 -->
<bean class="org.openwebflow.cfg.StartTaskAlarmService">
<property name="taskAlarmService" ref="myTaskAlarmService" />
<property name="runOnStartup" value="false" />
</bean>
<!-- 加载自定义activity -->
<bean class="org.openwebflow.cfg.LoadRuntimeActivityDefinitions">
<property name="activityDefinitionManager" ref="myActivityDefinitionManager" />
</bean>
</list>
</property>
</bean>
<!-- processEngine -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<!-- 工作流流转服务对象工厂 -->
<bean class="org.openwebflow.ctrl.impl.DefaultTaskFlowControlServiceFactory" />
<!-- processEngineTool -->
<bean id="processEngineTool" class="org.openwebflow.util.ProcessEngineTool" />
其中processEngineConfiguration是增强型的工作流引擎配置对象,可以设置自定义用户群组成员关系管理策略、自定义活动权限管理策略等。
完整的例子参见:https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.core.xml
2.2.3 activiti.cfg.mem.xml配置
在activiti.core.xml中会用到一些manager,activiti.mem.xml定义基于内存的manager实现,默认的activiti.mem.xml内容如下:
<!-- 自定义成员关系管理 -->
<bean id="myMembershipManager" class="org.openwebflow.mgr.mem.InMemoryMembershipManager" />
<bean id="myUserDetailsManager" class="org.openwebflow.mgr.mem.InMemoryUserDetailsManager" />
<!-- 自定义的活动权限表管理 -->
<bean id="myActivityPermissionManager"
class="org.openwebflow.mgr.mem.InMemoryActivityPermissionManager" />
<!-- 代理关系管理 -->
<bean id="myDelegationManager" class="org.openwebflow.mgr.mem.InMemoryDelegationManager" />
<!-- 自定义的动态自定义活动管理 -->
<bean id="myActivityDefinitionManager"
class="org.openwebflow.mgr.mem.InMemoryRuntimeActivityDefinitionManager" />
<bean id="myTaskNotificationManager" class="org.openwebflow.mgr.mem.InMemoryTaskNotificationManager" />
这里面定义了6个manager:
Manager类别 |
含义 |
|
|
|
|
|
|
|
|
|
|
|
|
完整的例子参见:https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.mem.xml
与activiti.cfg.core.xml类似的可替代文件为activiti.cfg.sql.hibernate.xml和activiti.cfg.sql.mybatis.xml。
2.2.4 activiti.cfg.sql.hibernate.xml配置
activiti.sql.hibernate.xml提供基于SQL的manager实现,采用的ORM框架为Hibernate 4。
各manager的定义如下:
<!-- 代理记录管理 -->
<bean id="myDelegationManager"
class="org.openwebflow.mgr.hibernate.service.SqlDelegationManager" />
<!-- 自定义成员关系管理 -->
<bean id="myMembershipManager"
class="org.openwebflow.mgr.hibernate.service.SqlMembershipManager" />
<!-- 自定义用户表 -->
<bean id="myUserDetailsManager"
class="org.openwebflow.mgr.hibernate.service.SqlUserDetailsManager" />
<!-- 自定义的活动权限表管理 -->
<bean id="myActivityPermissionManager"
class="org.openwebflow.mgr.hibernate.service.SqlActivityPermissionManager" />
<!-- 自定义的动态自定义活动管理 -->
<bean id="myActivityDefinitionManager"
class="org.openwebflow.mgr.hibernate.service.SqlRuntimeActivityDefinitionManager" />
<bean id="myTaskNotificationManager"
class="org.openwebflow.mgr.hibernate.service.SqlTaskNotificationManager" />
此外,还需要定义数据源、Hibernate Session工厂,以及事务。
<!-- 数据库脚本见openwebflow.sql -->
<bean id="owfDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${owfdb.driver}" />
<property name="url" value="${owfdb.url}" />
<property name="username" value="${owfdb.username}" />
<property name="password" value="${owfdb.password}" />
<property name="initialSize" value="20" />
<property name="maxActive" value="50" />
<property name="maxIdle" value="20" />
<property name="minIdle" value="10" />
</bean>
<!-- 配置SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="owfDataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<!-- <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop> -->
<!-- 服务启动通过实体创建数据库表信息 -->
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.autoReconnect">false</prop>
<prop key="hibernate.connection.autocommit">true</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<prop key="hibernate.jdbc.use_streams_for_binary">true</prop>
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext
</prop>
<!--解决weblogic无法使用hql的问题 -->
<prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
</props>
</property>
<!-- 自动扫描备注解的实体 -->
<property name="packagesToScan">
<list>
<value>org.openwebflow.mgr.hibernate.entity</value>
</list>
</property>
</bean>
<!-- 配置一个事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
采用HibernateORM,openwebflow-mgr-hibernate的代码结构如下:
其中,DAO类、实体类、服务类分别存放在dao、entity、service包下面。service类的事务声明以及entity的映射皆采取注解方式。
完整的例子参见:https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.sql.hibernate.xml
2.2.5 activiti.cfg.sql.mybatis.xml配置
activiti.sql.mybatis.xml提供基于SQL的manager实现,采用的ORM框架为mybatis 3。
各manager的定义如下:
<!-- 代理记录管理 -->
<bean id="myDelegationManager"
class="org.openwebflow.mgr.mybatis.service.SqlDelegationManager" />
<!-- 自定义成员关系管理 -->
<bean id="myMembershipManager"
class="org.openwebflow.mgr.mybatis.service.SqlMembershipManager" />
<!-- 自定义用户表 -->
<bean id="myUserDetailsManager"
class="org.openwebflow.mgr.mybatis.service.SqlUserDetailsManager" />
<!-- 自定义的活动权限表管理 -->
<bean id="myActivityPermissionManager"
class="org.openwebflow.mgr.mybatis.service.SqlActivityPermissionManager" />
<!-- 自定义的动态自定义活动管理 -->
<bean id="myActivityDefinitionManager"
class="org.openwebflow.mgr.mybatis.service.SqlRuntimeActivityDefinitionManager" />
<bean id="myTaskNotificationManager"
class="org.openwebflow.mgr.mybatis.service.SqlTaskNotificationManager" />
此外,还需要定义数据源、SqlSessionFactory,以及事务。
<!-- 数据库脚本见openwebflow.sql -->
<bean id="owfDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${owfdb.driver}" />
<property name="url" value="${owfdb.url}" />
<property name="username" value="${owfdb.username}" />
<property name="password" value="${owfdb.password}" />
<property name="initialSize" value="20" />
<property name="maxActive" value="50" />
<property name="maxIdle" value="20" />
<property name="minIdle" value="10" />
</bean>
<!-- 创建SqlSessionFactory,同时指定数据源-->
<bean id="owlSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="owfDataSource" />
</bean>
<!-- 配置一个事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="owfDataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
采用Mybatis ORM,openwebflow-mgr-mybatis的代码结构如下:
其中,Mapper接口、实体类、服务类分别存放在mapper、entity、service包下面。service类的事务声明以及Mapper的映射皆采取注解方式。
完整的例子参见:https://gitee.com/bluejoe/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.sql.mybatis.xml
2.3 数据库设计
首先,Activiti引擎本身需要用到一系列的数据表,设置好数据源后,Activiti会自动生成这些表。
Activiti的表都以ACT_开头,第二部分是表示表的用途的两个字母标识。用途也和服务的API对应。
- ACT_RE_*: 'RE'表示repository。这个前缀的表包含了流程定义和流程静态资源(图片,规则,等等)。
- ACT_RU_*: 'RU'表示runtime。这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。这样运行时表可以一直很小速度很快。
- ACT_ID_*: 'ID'表示identity。这些表包含身份信息,比如用户,组等等。
- ACT_HI_*: 'HI'表示history。这些表包含历史数据,比如历史流程实例,变量,任务等等。
- ACT_GE_*: 通用数据, 用于不同场景下。
OpenWebFlow为一系列manager提供了基于数据库的实现,需要用到一些数据表,对应的建库脚本参见https://gitee.com/bluejoe/openwebflow/tree/master/doc目录下的:
- openwebflow-mysql4.sql:MySQL4脚本
- openwebflow-mysql5.sql:MySQL5脚本
- openwebflow-sqlserver2008.sql:SQLServer2008脚本
- openwebflow-oracle10g.sql:Oracle脚本
其中共定义了6张表格:
- OWF_ACTIVITY_CREATION:用以存储自定义的活动定义信息
- OWF_ACTIVITY_PERMISSION:用以存储自定义的活动权限信息
- OWF_DELEGATION:用以存储用户代理信息
- OWF_NOTIFICATION:用以存储催办通知记录
- OWF_MEMBERSHIP:用以存储用户组成员关系
- OWF_USER:用以存储用户信息
注意:OWF_MEMBERSHIP和OWF_USER仅为测试使用,建议用户使用自己的数据表(OpenWebFlow本身努力的一个方向就是将用户及成员关系管理与工作流引擎剥离开),并包装自己的Manager。
2.4 使用ApplicationContext定义的bean
采用Spring IoC框架加载完XML配置文件之后,ApplicationContext中会包含如下变量,可供客户程序使用:
- processEngine:工作流引擎对象,标准的Activiti对象
- processEngineTool:针对processEngine提供了一些工具方法
- defaultTaskFlowControlServiceFactory:任务流控制器的工厂对象
- repositoryService:提供了管理和控制发布包和流程定义的操作
- RuntimeService:负责启动一个流程定义的新实例
- TaskService:与任务相关相关的操作
- IdentityService:管理(创建,更新,删除,查询...)群组和用户
- FormService:提供了启动表单和任务表单两个概念
- HistoryService:提供了Activiti引擎手机的所有历史数据
- ManagementService:可以查询数据库的表和表的元数据
如下是使用OpenWebFlow的示例代码,可以看出来与Activiti的用法完全一致:
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:activiti.cfg.mem.xml");
ProcessEngineTool tool = ctx.getBean(ProcessEngineTool.class);
ProcessEngine processEngine = tool.getProcessEngine();
// 启动流程实例
ProcessInstance instance = processEngine.getRuntimeService().startProcessInstanceByKey("test1");
TaskService taskService = processEngine.getTaskService();
//会自动跳转到第一个task
//management可以访问该task
Assert.assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("management").count());
2.5 运行测试用例
在openwebflow-test项目源代码中,用户可以找到一组测试用例来对工作流引擎的功能进行测试,它们分别是:
- MemProcessEngineTest:基于内存的manager测试
- SqlHibernateProcessEngineTest:基于hibernateORM的manager测试
- SqlMybatisProcessEngineTest:基于mybatisORM的manager测试
以上3个测试类都继承于AbstractProcessEngineTest:
AbstractProcessEngineTest提供了测试方法:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
其中为了配合测试设计了一个复杂的流程(models/test2.bpmn)如图所示:
选择指定的测试单元(如:MemProcessEngineTest),以“JUnit测试”的方式运行(Run As…),即可观察到测试结果:
也可以选择运行测试套件AllTests:
3. 熟悉OpenWebFlow代码
3.1 下载源码
用户可以下载OpenWebFlow的zip包,下载地址为:https://gitee.com/bluejoe/openwebflow/archive/master.zip
也可以通过git方式获取到最新源码,git资源库地址为:https://gitee.com/bluejoe/openwebflow.git
3.2 代码结构
OpenWebFlow源码包含5个maven工程,其中openwebflow工程是父工程,它声明了包含openwebflow-core、openwebflow-mgr-hibernate、openwebflow-mgr-mybatis、openwebflow-test等4个model。
- openwebflow-core:核心工程,包含OpenWebFlow扩展引擎的所有核心内容、以及基于内存的manager实现。
- openwebflow-mgr-hibernate:依赖于openwebflow-core,提供了基于数据库的manager实现,ORM框架采用Hibernate。
- openwebflow-mgr-mybatis:依赖于openwebflow-core,提供了基于数据库的manager实现,ORM框架采用MyBatis。
- openwebflow-test:依赖于以上项目,提供了测试用例,包括配置文件、测试类等。
3.3 build项目
获取到的项目源码可以采用Maven完成build和install,如下为build截图:
3.4 核心对象
3.4.1 ProcessEngineConfigurationEx
ProcessEngineConfigurationEx是针对Activiti提供的ProcessEngineConfiguration类的派生类:
二者大部分参数完全一致,唯一不同的是,ProcessEngineConfigurationEx提供了一个属性:startEngineEventListeners。
startEngineEventListeners用以定义工作流引擎启动的时候需要同时启动的其它任务,startEngineEventListeners是个List,因此可以随意增加新的任务,默认的core.xml中会加载如下任务:LoadDummyFormTypes、ReplaceMembershipManager、ReplaceTaskAssignmentHandler、ImportDefinedProcessModels、StartTaskAlarmService、LoadRuntimeActivityDefinitions。各任务及类属性列表如下:
任务类 |
用途 |
属性名 |
属性含义 |
LoadDummyFormTypes |
加载一些无用的Form类型,用以屏蔽一些自定义Form带来的错误 |
typeNames |
需要屏蔽的Form类型名,以;分隔,如:user |
ReplaceMembershipManager |
直接接管用户组成员关系 |
customMembershipManager |
指定客户程序自定义的管理器 |
ReplaceTaskAssignmentHandler |
接管Activiti的用户权限管理,如果你想实现动态的节点权限分配,那必须要打开它。 |
handlers |
定义一个授权处理器列表,值类型为List,运行时刻各授权处理器列表会组成一个链,越靠后优先级越高(越靠外) |
ImportDefinedProcessModels |
自动从指定目录导入BPMN模型 |
modelDir |
用以指定模型的路径,可以是classpath:等路径 |
StartTaskAlarmService |
启动任务催办服务 |
taskAlarmService |
设置催办服务对象 |
|
|
runOnStartup |
是否一开始就启动(默认为true) |
LoadRuntimeActivityDefinitions |
加载运行时的节点定义,主要用来支持在运行时刻定义新的节点 |
activityDefinitionManager |
指定节点定义管理器 |
3.4.2 ProcessEngineTool
ProcessEngineTool提供了一些工具方法,这些方法的功能一般很难通过ProcessEngine直接拿到:
方法摘要 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3.4.3 各种Utils
OpenWebFlow提供了一些常见的工具类,如下所示:
类摘要 |
|
|
|
|
|
|
|
|
|
|
|
3.4.4 TaskFlowControlService
TaskFlowControlService用以实现流程的自由控制,它提供的方法如下:
方法摘要 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TaskFlowControlService需要一个TaskFlowControlServiceFactory来创建,可以从applicationcontext中获取到该工厂对象。
4. 核心功能的设计与使用【略】
5. 使用管理器接口实现自定义扩展
OpenWebFlow需要用户提供6类管理器的接口,它们分别是:
- RuntimeActivityDefinitionManager:负责获取活动的定义信息,用以支持运行时期的新建活动
- ActivityPermissionManager:负责获取活动的权限设置信息
- TaskNotificationManager:负责存取任务催办通知信息
- DelegationManager:负责获取用户的代理信息
- UserDetailsManager:负责获取用户的信息(包括E-mail、昵称、手机号等),主要用以发送催办通知
- IdentityMembershipManager:负责获取用户组成员关系,获取某用户的候选任务队列时,需要通过用户名获取到用户组
除了这些Manager之外,用户会发现OpenWebFlow还提供了一系列的ManagerEx接口:
- ActivityPermissionManagerEx:负责保存活动的权限设置信息
- TaskNotificationManagerEx:负责保存任务催办通知信息
- DelegationManagerEx:负责保存用户的代理信息
- UserDetailsManagerEx:负责保存用户的信息
- IdentityMembershipManagerEx:负责保存用户组成员关系
可以简单的认为,Manager接口主要用以信息读取(read),ManagerEx接口主要用以信息写入(write),注意使用OpenWebFlow引擎时,ManagerEx不是必须要提供相应实现的!OpenWebFlow引擎的所有操作只会调用到Manager而非ManagerEx,提供ManagerEx的唯一用处是为了测试(如果没有写入,读取返回的永远是空白,测试就无法正常进行了)。
5.1 活动定义管理
客户程序往往需要在运行时候调整某个工作流的流程,如:让活动step5执行完之后跳转至step2,这样的操作需要创建一个新的路径,为了保证后续流程的正常执行(特别是应用重启之后),这样的路径需要保存和加载。
5.1.1 RuntimeActivityDefinitionManager
RuntimeActivityDefinitionManager包含如下方法:
|
|
|
|
|
|
|
|
5.1.2 RuntimeActivityDefinitionEntity
RuntimeActivityDefinitionEntity对应于一条活动的定义信息:
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5.2 活动权限管理
5.2.1 ActivityPermissionManager
活动权限的管理接口为ActivityPermissionManager,它的定义如下:
|
|
|
|
5.2.2 ActivityPermissionEntity
非常简单,它只需要一个方法,该方法返回一个ActivityPermissionEntity,该实体的定义如下:
|
|
|
|
|
|
|
|
5.2.3 ActivityPermissionManagerEx
ActivityPermissionManagerEx实现对活动权限表的“写”操作:
|
|
|
|
|
|
5.3 任务催办通知管理
5.3.1 TaskNotificationManager
TaskNotificationManager负责读取和设置任务催办的状态,该接口也很简单:
|
|
|
|
|
|
可以理解成TaskNotificationManager维护了一个队列,记录了每个任务的通知状态(已通知为true,未通知为false)。
5.3.2 TaskNotificationManagerEx
TaskNotificationManagerEx实现了对通知记录的“写”操作:
|
|
|
|
5.4 用户代理关系管理
5.4.1 DelegationManager
DelegationManager用以维护用户之间的代理关系。接口包含2个方法:
|
|
|
|
|
|
5.4.2 DelegationEntity
DelegationEntity
描述一条代理关系:
|
|
|
|
|
|
5.4.3 DelegationManagerEx
DelegationManagerEx用以实现对代理记录的“写”操作:
|
|
|
|
|
|
5.5 用户详细信息管理
5.5.1 UserDetailsManager
UserDetailsManager负责获取用户的信息(包括E-mail、昵称、手机号等),主要用以发送催办通知。UserDetailsManager接口包含的方法如下:
|
|
|
|
5.5.2 UserDetailsEntity
UserDetailsEntity
用以描述用户详细信息,注意它没有强制要求提供诸如getName()这样的方法,而是提供了一个getProperty(Stringname)方法:
|
||
|
|
|
|
|
|
|
|
|
|
|
UserDetailsEntity
同时提供了几个字符串常量:
|
|
|
|
|
|
|
|
|
|
5.5.3 UserDetailsManagerEx
UserDetailsManagerEx用以实现用户信息的“写”操作:
|
|
|
|
|
|
5.6 用户组成员关系管理
5.6.1 IdentityMembershipManager
IdentityMembershipManager负责获取用户组成员关系,简单点,就是获取指定用户所在的组的ID列表,以及指定组内的成员ID列表。
|
|
|
|
|
|
5.6.2 IdentityMembershipManagerEx
IdentityMembershipManagerEx提供了对成员关系信息的“写”操作:
|
|
|
|
|
|
6. 其他帮助
本文档的下载地址为:https://gitee.com/bluejoe/openwebflow/tree/master/doc,可通过该地址及时查阅最新版本。
如果用户需要查阅OpenWebFlow的Java API,可以参考javadoc(https://gitee.com/bluejoe/openwebflow/tree/master/openwebflow-core/doc/javadoc)。
另外可以关注Wiki(https://gitee.com/bluejoe/openwebflow/wiki),提交话题(https://gitee.com/bluejoe/openwebflow/issues),以及与作者bluejoe2008@gmail.com直接联系。
7. Activiti的BUG及对策
目前作者发现Activiti框架存在2个bug,主要表现在:
第一个bug是在BaseBpmnJsonConverter将BPMN模型转存为JSON格式的时候,会忽略对true布尔值的输出,这个bug会造成JsonConverterUtil.getPropertyValueAsBoolean()获取到false值(因为此时的判断标准变成Yes或No)。该bug的报告地址:https://github.com/Activiti/Activiti/pull/464#event-204722250
另外一个bug是在BPMN文件加载的时候,当本地字符集为非UTF-8(如:GB2312)时,会出现模型加载的错误。该bug的报告地址:https://github.com/Activiti/Activiti/pull/486#event-220121880
目前(2014年)作者已经针对以上两个bug提交了bugfix并被master版本合并。不过考虑到版本稳定性问题,OpenWebFlow最新版本还是采用了其他方法来避免了如上bug的发生。
来源:oschina
链接:https://my.oschina.net/u/2926970/blog/1552284