OpenWebFlow0.9用户手册与设计说明
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://github.com/bluejoe2008/openwebflow/blob/master/openwebflow-core/target/openwebflow-core-0.9-SNAPSHOT.jar
注意这些jar具有较多的依赖, https://github.com/bluejoe2008/openwebflow/tree/master/openwebflow-core/target/lib列举了所有的依赖包如下:
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):
l settings.properties:公共属性设置
l activiti.cfg.core.xml:用以配置工作流引擎的基本配置信息;
l activiti.cfg.mem.xml:用以定义一些用以支持OpenWebFlow工作的manager,注意名字中的mem,它暗示着仅提供了那些manager的基于内存实现的版本,类似的配置文件还可以是activiti.cfg.sql.XXX.xml;
2.2.1 settings.properties
settings.properties文件是一个正常的属性文件,用以spring IOC文件加载。如下是一个属性文件的内容:
1. mail.host=smtp.bluejoe.cn
2. mail.port=25
3. mail.username=sdb-support@cnic.cn
4. mail.password=sdbsupport
5. mail.from=sdb-support@cnic.cn
6. model.dir=../models
7. alarm.mail.template=classpath:/alarm-template.txt
8. hibernate.dialect=org.hibernate.dialect.MySQLDialect
9. hibernate.hbm2ddl.auto=none
10. activitidb.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000
11. activitidb.driver=org.h2.Driver
12. activitidb.username=sa
13. activitidb.password=
14. owfdb.url=jdbc:mysql://localhost:3306/openwebflow?useUnicode=true&characterEncoding=UTF-8
15. owfdb.driver=com.mysql.jdbc.Driver
16. owfdb.username=root
17. 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要求的那个配置文件有点相似,但可以多一些内容,如下是个例子:
1. <!--工作流核心数据库配置 -->
2. <bean id="activitiDataSource"class="org.apache.commons.dbcp.BasicDataSource"
3. destroy-method="close">
4. <property name="driverClassName"value="${activitidb.driver}" />
5. <property name="url" value="${activitidb.url}" />
6. <property name="username"value="${activitidb.username}" />
7. <property name="password"value="${activitidb.password}" />
8. <property name="initialSize"value="20" />
9. <property name="maxActive"value="50" />
10. <property name="maxIdle"value="20" />
11. <property name="minIdle"value="10" />
12. </bean>
13.
14. <!-- 任务催办配置 -->
15. <bean id="myTaskAlarmService"class="org.openwebflow.alarm.impl.TaskAlarmServiceImpl">
16. <!-- 截止日期提前量 -->
17. <property name="periodInAdvance"value="P2D" />
18. <!-- 设置消息通知机制 -->
19. <property name="messageNotifier">
20. <!-- 采用邮件发送 -->
21. <bean class="org.openwebflow.alarm.impl.MailMessageNotifier">
22. <property name="subjectTemplate"value="请尽快处理#{'$'}{task.name}任务" />
23. <property name="messageTemplateResource"value="${alarm.mail.template}" />
24. <property name="mailSender">
25. <bean class="org.openwebflow.alarm.impl.MailSender">
26. <property name="serverHost"value="${mail.host}" />
27. <property name="serverPort"value="${mail.port}" />
28. <property name="authUserName"value="${mail.username}" />
29. <property name="authPassword"value="${mail.password}" />
30. <property name="mailFrom"value="${mail.from}" />
31. </bean>
32. </property>
33. </bean>
34. </property>
35. <property name="membershipManager"ref="myMembershipManager" />
36. <property name="userDetailsManager"ref="myUserDetailsManager" />
37. <property name="taskNotificationManager"ref="myTaskNotificationManager" />
38. </bean>
39.
40. <bean id="transactionManager"
41. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
42. <property name="dataSource"ref="activitiDataSource" />
43. </bean>
44.
45. <tx:annotation-driven transaction-manager="transactionManager"/>
46.
47. <!-- 配置对象 -->
48. <bean id="processEngineConfiguration"class="org.openwebflow.cfg.ProcessEngineConfigurationEx">
49. <property name="dataSource"ref="activitiDataSource" />
50. <property name="transactionManager"ref="transactionManager" />
51. <property name="databaseSchemaUpdate"value="true" />
52. <property name="jobExecutorActivate"value="false" />
53. <property name="startEngineEventListeners">
54. <list>
55. <!-- 加载自定义表单元素类型 -->
56. <bean class="org.openwebflow.cfg.LoadDummyFormTypes">
57. <property name="typeNames"value="user" />
58. </bean>
59. <!-- 自定义成员关系管理 -->
60. <bean class="org.openwebflow.cfg.ReplaceMembershipManager">
61. <property name="customMembershipManager"ref="myMembershipManager" />
62. </bean>
63. <!-- 自定义活动权限管理 -->
64. <bean class="org.openwebflow.cfg.ReplaceTaskAssignmentHandler">
65. <!-- 授权处理器列表,会组成一个链,越靠后优先级越高(越靠外) -->
66. <property name="handlers">
67. <list>
68. <!-- 自定义授权项列表 -->
69. <bean
70. class="org.openwebflow.assign.permission.ActivityPermissionAssignmentHandler">
71. <property name="activityPermissionManager"ref="myActivityPermissionManager" />
72. </bean>
73. <!-- 允许授权代理 -->
74. <bean
75. class="org.openwebflow.assign.delegation.TaskDelagationAssignmentHandler">
76. <property name="delegationManager"ref="myDelegationManager" />
77. <property name="membershipManager"ref="myMembershipManager" />
78. <property name="hideDelegated"value="false" />
79. </bean>
80. </list>
81. </property>
82. </bean>
83. <!-- 自动导入流程模型 -->
84. <bean class="org.openwebflow.cfg.ImportDefinedProcessModels">
85. <property name="modelDir"value="${model.dir}" />
86. </bean>
87. <!-- 启动催办管理器 -->
88. <bean class="org.openwebflow.cfg.StartTaskAlarmService">
89. <property name="taskAlarmService"ref="myTaskAlarmService" />
90. <property name="runOnStartup"value="false" />
91. </bean>
92. <!-- 加载自定义activity -->
93. <bean class="org.openwebflow.cfg.LoadRuntimeActivityDefinitions">
94. <property name="activityDefinitionManager"ref="myActivityDefinitionManager" />
95. </bean>
96. </list>
97. </property>
98. </bean>
99.
100. <!--processEngine -->
101. <bean id="processEngine"class="org.activiti.spring.ProcessEngineFactoryBean">
102. <property name="processEngineConfiguration"ref="processEngineConfiguration" />
103. </bean>
104.
105. <!--工作流流转服务对象工厂 -->
106. <bean class="org.openwebflow.ctrl.impl.DefaultTaskFlowControlServiceFactory"/>
107.
108. <!--processEngineTool -->
109. <bean id="processEngineTool"class="org.openwebflow.util.ProcessEngineTool"/>
110.
111. <bean id="repositoryService"factory-bean="processEngine"
112. factory-method="getRepositoryService" />
113. <bean id="runtimeService"factory-bean="processEngine"
114. factory-method="getRuntimeService" />
115. <bean id="taskService"factory-bean="processEngine"
116. factory-method="getTaskService" />
117. <bean id="historyService"factory-bean="processEngine"
118. factory-method="getHistoryService" />
119. <bean id="managementService"factory-bean="processEngine"
120. factory-method="getManagementService" />
其中processEngineConfiguration是增强型的工作流引擎配置对象,可以设置自定义用户群组成员关系管理策略、自定义活动权限管理策略等。
完整的例子参见:https://github.com/bluejoe2008/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内容如下:
1. <!--自定义成员关系管理 -->
2. <bean id="myMembershipManager"class="org.openwebflow.mgr.mem.InMemoryMembershipManager"/>
3. <bean id="myUserDetailsManager"class="org.openwebflow.mgr.mem.InMemoryUserDetailsManager"/>
4.
5. <!--自定义的活动权限表管理 -->
6. <bean id="myActivityPermissionManager"
7. class="org.openwebflow.mgr.mem.InMemoryActivityPermissionManager"/>
8.
9. <!--代理关系管理 -->
10. <bean id="myDelegationManager"class="org.openwebflow.mgr.mem.InMemoryDelegationManager"/>
11.
12. <!-- 自定义的动态自定义活动管理 -->
13. <bean id="myActivityDefinitionManager"
14. class="org.openwebflow.mgr.mem.InMemoryRuntimeActivityDefinitionManager"/>
15.
16. <bean id="myTaskNotificationManager"class="org.openwebflow.mgr.mem.InMemoryTaskNotificationManager"/>
这里面定义了6个manager:
Manager类别 |
含义 |
|
|
|
|
|
|
|
|
|
|
|
|
完整的例子参见:https://github.com/bluejoe2008/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的定义如下:
1. <!--代理记录管理 -->
2. <bean id="myDelegationManager"
3. class="org.openwebflow.mgr.hibernate.service.SqlDelegationManager"/>
4. <!--自定义成员关系管理 -->
5. <bean id="myMembershipManager"
6. class="org.openwebflow.mgr.hibernate.service.SqlMembershipManager"/>
7. <!--自定义用户表 -->
8. <bean id="myUserDetailsManager"
9. class="org.openwebflow.mgr.hibernate.service.SqlUserDetailsManager"/>
10. <!-- 自定义的活动权限表管理 -->
11. <bean id="myActivityPermissionManager"
12. class="org.openwebflow.mgr.hibernate.service.SqlActivityPermissionManager"/>
13. <!-- 自定义的动态自定义活动管理 -->
14. <bean id="myActivityDefinitionManager"
15. class="org.openwebflow.mgr.hibernate.service.SqlRuntimeActivityDefinitionManager"/>
16. <bean id="myTaskNotificationManager"
17. class="org.openwebflow.mgr.hibernate.service.SqlTaskNotificationManager"/>
此外,还需要定义数据源、Hibernate Session工厂,以及事务。
1. <context:component-scan base-package="org.openwebflow.mgr.hibernate.dao"/>
2.
3. <!--数据库脚本见openwebflow.sql -->
4. <bean id="owfDataSource"class="org.apache.commons.dbcp.BasicDataSource"
5. destroy-method="close">
6. <property name="driverClassName"value="${owfdb.driver}" />
7. <property name="url" value="${owfdb.url}" />
8. <property name="username"value="${owfdb.username}" />
9. <property name="password"value="${owfdb.password}" />
10. <property name="initialSize"value="20" />
11. <property name="maxActive"value="50" />
12. <property name="maxIdle"value="20" />
13. <property name="minIdle"value="10" />
14. </bean>
15.
16. <!-- 配置SessionFactory -->
17. <bean id="sessionFactory"
18. class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
19. <property name="dataSource"ref="owfDataSource" />
20. <property name="hibernateProperties">
21. <props>
22. <prop key="hibernate.dialect">${hibernate.dialect}</prop>
23. <!-- <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop>-->
24. <!-- 服务启动通过实体创建数据库表信息 -->
25. <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
26. <prop key="hibernate.show_sql">true</prop>
27. <prop key="hibernate.format_sql">true</prop>
28. <prop key="hibernate.jdbc.batch_size">20</prop>
29. <prop key="hibernate.connection.release_mode">auto</prop>
30. <prop key="hibernate.autoReconnect">false</prop>
31. <prop key="hibernate.connection.autocommit">true</prop>
32. <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
33. <prop key="hibernate.jdbc.use_streams_for_binary">true</prop>
34. <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext
35. </prop>
36. <!--解决weblogic无法使用hql的问题 -->
37. <prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
38. </props>
39. </property>
40.
41. <!-- 自动扫描备注解的实体 -->
42. <property name="packagesToScan">
43. <list>
44. <value>org.openwebflow.mgr.hibernate.entity</value>
45. </list>
46. </property>
47. </bean>
48.
49. <!-- 配置一个事务管理器 -->
50. <bean id="transactionManager"
51. class="org.springframework.orm.hibernate4.HibernateTransactionManager">
52. <property name="sessionFactory"ref="sessionFactory" />
53. </bean>
54.
55. <tx:annotation-driven transaction-manager="transactionManager"/>
采用HibernateORM,openwebflow-mgr-hibernate的代码结构如下:
其中,DAO类、实体类、服务类分别存放在dao、entity、service包下面。service类的事务声明以及entity的映射皆采取注解方式。
完整的例子参见:https://github.com/bluejoe2008/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的定义如下:
1. <!--代理记录管理 -->
2. <bean id="myDelegationManager"
3. class="org.openwebflow.mgr.mybatis.service.SqlDelegationManager"/>
4. <!--自定义成员关系管理 -->
5. <bean id="myMembershipManager"
6. class="org.openwebflow.mgr.mybatis.service.SqlMembershipManager"/>
7. <!--自定义用户表 -->
8. <bean id="myUserDetailsManager"
9. class="org.openwebflow.mgr.mybatis.service.SqlUserDetailsManager"/>
10. <!-- 自定义的活动权限表管理 -->
11. <bean id="myActivityPermissionManager"
12. class="org.openwebflow.mgr.mybatis.service.SqlActivityPermissionManager"/>
13. <!-- 自定义的动态自定义活动管理 -->
14. <bean id="myActivityDefinitionManager"
15. class="org.openwebflow.mgr.mybatis.service.SqlRuntimeActivityDefinitionManager"/>
16. <bean id="myTaskNotificationManager"
17. class="org.openwebflow.mgr.mybatis.service.SqlTaskNotificationManager"/>
此外,还需要定义数据源、SqlSessionFactory,以及事务。
1. <!--数据库脚本见openwebflow.sql -->
2. <bean id="owfDataSource"class="org.apache.commons.dbcp.BasicDataSource"
3. destroy-method="close">
4. <property name="driverClassName"value="${owfdb.driver}" />
5. <property name="url" value="${owfdb.url}" />
6. <property name="username"value="${owfdb.username}" />
7. <property name="password"value="${owfdb.password}" />
8. <property name="initialSize"value="20" />
9. <property name="maxActive"value="50" />
10. <property name="maxIdle"value="20" />
11. <property name="minIdle"value="10" />
12. </bean>
13.
14. <!-- 创建SqlSessionFactory,同时指定数据源-->
15. <bean id="owlSqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
16. <property name="dataSource"ref="owfDataSource" />
17. </bean>
18.
19. <!-- 配置一个事务管理器 -->
20. <bean id="transactionManager"
21. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
22. <property name="dataSource"ref="owfDataSource" />
23. </bean>
24.
25. <tx:annotation-driven transaction-manager="transactionManager" />
采用Mybatis ORM,openwebflow-mgr-mybatis的代码结构如下:
其中,Mapper接口、实体类、服务类分别存放在mapper、entity、service包下面。service类的事务声明以及Mapper的映射皆采取注解方式。
完整的例子参见:https://github.com/bluejoe2008/openwebflow/blob/master/openwebflow-test/src/test/resources/activiti.cfg.sql.mybatis.xml
2.3 数据库设计
首先,Activiti引擎本身需要用到一系列的数据表,设置好数据源后,Activiti会自动生成这些表。
Activiti的表都以ACT_开头,第二部分是表示表的用途的两个字母标识。用途也和服务的API对应。
l ACT_RE_*: 'RE'表示repository。这个前缀的表包含了流程定义和流程静态资源(图片,规则,等等)。
l ACT_RU_*: 'RU'表示runtime。这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。这样运行时表可以一直很小速度很快。
l ACT_ID_*: 'ID'表示identity。这些表包含身份信息,比如用户,组等等。
l ACT_HI_*: 'HI'表示history。这些表包含历史数据,比如历史流程实例,变量,任务等等。
l ACT_GE_*: 通用数据, 用于不同场景下。
OpenWebFlow为一系列manager提供了基于数据库的实现,需要用到一些数据表,对应的建库脚本参见https://github.com/bluejoe2008/openwebflow/tree/master/doc目录下的:
l openwebflow-mysql4.sql:MySQL4脚本
l openwebflow-mysql5.sql:MySQL5脚本
l openwebflow-sqlserver2008.sql:SQLServer2008脚本
l openwebflow-oracle10g.sql:Oracle脚本
其中共定义了6张表格:
l OWF_ACTIVITY_CREATION:用以存储自定义的活动定义信息
l OWF_ACTIVITY_PERMISSION:用以存储自定义的活动权限信息
l OWF_DELEGATION:用以存储用户代理信息
l OWF_NOTIFICATION:用以存储催办通知记录
l OWF_MEMBERSHIP:用以存储用户组成员关系
l OWF_USER:用以存储用户信息
注意:OWF_MEMBERSHIP和OWF_USER仅为测试使用,建议用户使用自己的数据表(OpenWebFlow本身努力的一个方向就是将用户及成员关系管理与工作流引擎剥离开),并包装自己的Manager。
2.4 使用ApplicationContext定义的bean
采用Spring IoC框架加载完XML配置文件之后,ApplicationContext中会包含如下变量,可供客户程序使用:
l processEngine:工作流引擎对象,标准的Activiti对象
l processEngineTool:针对processEngine提供了一些工具方法
l defaultTaskFlowControlServiceFactory:任务流控制器的工厂对象
l repositoryService:提供了管理和控制发布包和流程定义的操作
l RuntimeService:负责启动一个流程定义的新实例
l TaskService:与任务相关相关的操作
l IdentityService:管理(创建,更新,删除,查询...)群组和用户
l FormService:提供了启动表单和任务表单两个概念
l HistoryService:提供了Activiti引擎手机的所有历史数据
l ManagementService:可以查询数据库的表和表的元数据
如下是使用OpenWebFlow的示例代码,可以看出来与Activiti的用法完全一致:
1. ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:activiti.cfg.mem.xml");
2. ProcessEngineTool tool = ctx.getBean(ProcessEngineTool.class);
3. ProcessEngine processEngine = tool.getProcessEngine();
4. // 启动流程实例
5. ProcessInstance instance = processEngine.getRuntimeService().startProcessInstanceByKey("test1");
6. TaskService taskService = processEngine.getTaskService();
7. //会自动跳转到第一个task
8. //management可以访问该task
9. Assert.assertEquals(1, taskService.createTaskQuery().taskCandidateGroup("management").count());
2.5 运行测试用例
在openwebflow-test项目源代码中,用户可以找到一组测试用例来对工作流引擎的功能进行测试,它们分别是:
l MemProcessEngineTest:基于内存的manager测试
l SqlHibernateProcessEngineTest:基于hibernateORM的manager测试
l SqlMybatisProcessEngineTest:基于mybatisORM的manager测试
以上3个测试类都继承于AbstractProcessEngineTest:
AbstractProcessEngineTest提供了测试方法:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
其中为了配合测试设计了一个复杂的流程(models/test2.bpmn)如图所示:
选择指定的测试单元(如:MemProcessEngineTest),以“JUnit测试”的方式运行(Run As…),即可观察到测试结果:
也可以选择运行测试套件AllTests:
3. 熟悉OpenWebFlow代码
3.1 下载源码
用户可以下载OpenWebFlow的zip包,下载地址为:https://github.com/bluejoe2008/openwebflow/archive/master.zip
也可以通过git方式获取到最新源码,git资源库地址为:https://github.com/bluejoe2008/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. 核心功能的设计与使用
4.1 用户管理托管
4.1.1 设计方案
OpenWebFlow通过ReplaceMembershipManager的beforeStartEngine()事件,设置ProcessEngineConfigurationImpl的sessionFactories,将自定义的用户管理器、群组管理器、用户成员关系管理器注射进去:
1. sessionFactories.add(newSessionedEntityManagerFactory(UserIdentityManager.class, new DummyUserIdentityManager(
2. _customMembershipManager)));
3. sessionFactories.add(newSessionedEntityManagerFactory(GroupIdentityManager.class,
4. new DummyGroupIdentityManager(_customMembershipManager)));
5. sessionFactories.add(newSessionedEntityManagerFactory(MembershipIdentityManager.class,
6. newDummyMembershipIdentityManager()));
DummyUserIdentityManager、DummyGroupIdentityManager和DummyMembershipIdentityManager是三个适配器,实现用户自定义Manager到Activiti所需的UserIdentityManager、GroupIdentityManager和MembershipIdentityManager的适配。
4.1.2 使用方法
如果需要挂接应用的用户成员关系管理框架,用户需要提供一个IdentityMembershipManager实现类,替换掉配置文件中的membershipManager即可。
如果需要挂接应用的用户详细信息管理框架,用户提供一个UserDetailsManager实现类,替换掉配置文件中的userDetailsManager即可。
参见“5.5用户详细信息管理”“5.6用户组成员关系管理”。
4.2 任务权限框架托管
4.2.1 设计方案
OpenWebFlow的任务权限框架托管的核心思想在于org.openwebflow.assign.TaskAssignmentHandler:
1. public interface TaskAssignmentHandler
2. {
3. void handleAssignment(TaskAssignmentHandlerChainchain, TaskEntity task, ActivityExecution execution);
4. }
TaskAssignmentHandler配合自定义的UserTaskActivityBehavior,用以篡改Activiti的任务权限分配方法:
1. public class MyUserTaskActivityBehaviorextends UserTaskActivityBehavior
2. {
3. List<TaskAssignmentHandler> _handlers;
4.
5. publicMyUserTaskActivityBehavior(List<TaskAssignmentHandler> handlers,TaskDefinition taskDefinition)
6. {
7. super(taskDefinition);
8. _handlers = handlers;
9. }
10.
11. protectedTaskAssignmentHandlerChainImpl createHandlerChain()
12. {
13. TaskAssignmentHandlerChainImplhandlerChain = new TaskAssignmentHandlerChainImpl();
14. final MyUserTaskActivityBehaviormyUserTaskActivityBehavior = this;
15. handlerChain.addHandler(new TaskAssignmentHandler()
16. {
17. @Override
18. public voidhandleAssignment(TaskAssignmentHandlerChain chain, TaskEntity task,ActivityExecution execution)
19. {
20. myUserTaskActivityBehavior.superHandleAssignments(task,execution);
21. }
22. });
23.
24. handlerChain.addHandlers(_handlers);
25. return handlerChain;
26. }
27.
28. @Override
29. protected void handleAssignments(TaskEntitytask, ActivityExecution execution)
30. {
31. createHandlerChain().resume(task,execution);
32. }
33.
34. protected voidsuperHandleAssignments(TaskEntity task, ActivityExecution execution)
35. {
36. super.handleAssignments(task,execution);
37. }
38. }
TaskAssignmentHandlerChainImpl将一系列的TaskAssignmentHandler从内到外组成一个处理链,然后再委托给MyUserTaskActivityBehavior来执行。查看配置文件可以观察到这个链的结构:
1.<!-- 授权处理器列表,会组成一个链,越靠后优先级越高(越靠外) -->
2.<property name="handlers">
3. <list>
4. <!-- 自定义授权项列表 -->
5. <bean
6. class="org.openwebflow.assign.permission.ActivityPermissionAssignmentHandler">
7. <property name="activityPermissionManager" ref="myActivityPermissionManager" />
8. </bean>
9. <!-- 允许授权代理 -->
10. <bean
11. class="org.openwebflow.assign.delegation.TaskDelagationAssignmentHandler">
12. <property name="delegationManager" ref="myDelegationManager" />
13. <property name="membershipManager" ref="myMembershipManager" />
14. <property name="hideDelegated" value="false"/>
15. </bean>
16. </list>
17.</property>
可以看出链列表里的内容依次为:
(BPMN静态模型权限定义) à ActivityPermissionAssignmentHandler à TaskDelagationAssignmentHandler
用户程序通过TaskAssignmentHandlerChainImpl访问活动的顺序如下图所示:
其中,BPMN模型权限控制由createHandlerChain()方法体内的一个匿名类包装完成,自定义权限表策略由ActivityPermissionAssignmentHandler类完成,代理策略由TaskDelagationAssignmentHandler类完成。ActivityPermissionAssignmentHandler和TaskDelagationAssignmentHandler是TaskAssignmentHandler的两个实现类,如下图所示。
ActivityPermissionAssignmentHandler会实现活动权限运行时自定义的功能,相关内容参见“5.1活动定义管理”。
TaskDelagationAssignmentHandler会实现任务代办的功能,相关内容参见“0欲使用任务权限框架托管功能,需要遵循如下步骤:
l 配置myActivityPermissionManager、myDelegationManager以及myMembershipManager;
l 在activiti.cfg.core.xml中的processEngineConfiguration里打开ReplaceTaskAssignmentHandler(默认情况下这是打开的);
接下来,不需要任何设置,在查询任务的时候,会自动根据以上授权策略进行筛选。
任务代办”。
4.2.2 使用方法
l 配置myActivityPermissionManager、myDelegationManager以及myMembershipManager;
l 在activiti.cfg.core.xml中的processEngineConfiguration里打开ReplaceTaskAssignmentHandler(默认情况下这是打开的);
接下来,不需要任何设置,在查询任务的时候,会自动根据以上授权策略进行筛选。
4.3 任务代办
Activiti本身提供了任务代办功能,TaskService具有如下方法:
void delegateTask(String taskId,
String userId)
Delegates thetask to another user. This means that the assignee is set and the delegationstate is set to DelegationState.PENDING.If no owner is set on the task, the owner is set to the current assignee of thetask.
注意OpenWebFlow关注的“任务代办”功能与上面的概念不同,它的含义是:用户A暂时委派用户B代理处理“所有可能的任务”,而不是专指“某个任务”。
4.3.1 设计方案
通过任务权限框架的托管,OpenWebFlow任务代办的实现比较简便。TaskDelagationAssignmentHandler通过DelegationManager和IdentityMembershipManager两个字段,实现了任务代理的功能。核心的实现方法如下:
1. @Override
2. public void handleAssignment(TaskAssignmentHandlerChainchain, TaskEntity task, ActivityExecution execution)
3. {
4. //先执行其它规则
5. chain.resume(task, execution);
6.
7. overwriteAssignee(task);
8.
9. Map<String, Object> userIdMap = new HashMap<String, Object>();
10. Map<String, Object> groupIdMap = new HashMap<String, Object>();
11. retrieveCandidateUserIdsAndGroupIds(task,userIdMap, groupIdMap);
12. Map<String, Object> newUserIdMap= new HashMap<String, Object>();
13. Map<String, Object>removeUserIdMap = new HashMap<String, Object>();
14.
15. //遍历所有的被代理人
16. List<DelegationEntity> entries = _delegationManager.listDelegationEntities();
17. overwriteCandicateUserIds(userIdMap,newUserIdMap, removeUserIdMap, entries);
18. overwriteCandicateGroupIds(groupIdMap,newUserIdMap, entries);
19.
20. addCandidateUsers(task,newUserIdMap.keySet());
21. removeCandidateUsers(task, removeUserIdMap.keySet());
22. }
DelegationManager的设计参见“5.4.1DelegationManager”。
4.3.2 使用方法
欲使用任务代办功能,只需要遵循如下步骤:
l 配置myDelegationManager和myMembershipManager;
l 在业务代码中通过调用DelegationManagerEx的saveDelegation()来设置一条代理规则;
l 在activiti.cfg.core.xml中的processEngineConfiguration里打开TaskDelagationAssignmentHandler(默认情况下这是打开的);
接下来,不需要任何设置,在分配任务(或者选择候选人)的时候,会自动包含被代理人。
4.4 任务催办
任务催办的功能与引擎相对独立,它负责针对未能及时处理的任务(根据任务的dueDate),给出通知,包括邮件通知、短信通知等。
4.4.1 设计方案
OpenWebFlow针对催办功能设计了一个TaskAlarmService服务,一个典型的TaskAlarmServiceImpl服务定义如下:
如下示出myTaskAlarmService的配置:
1. <!-- 任务催办配置 -->
2. <bean id="myTaskAlarmService" class="org.openwebflow.alarm.impl.TaskAlarmServiceImpl">
3. <!-- 截止日期提前量 -->
4. <property name="periodInAdvance" value="P2D" />
5. <!-- 设置消息通知机制 -->
6. <property name="messageNotifier">
7. <!-- 采用邮件发送 -->
8. <bean class="org.openwebflow.alarm.impl.MailMessageNotifier">
9. <property name="subjectTemplate" value="请尽快处理#{'$'}{task.name}任务" />
10. <property name="messageTemplateResource" value="${alarm.mail.template}" />
11. <property name="mailSender">
12. <bean class="org.openwebflow.alarm.impl.MailSender">
13. <property name="serverHost" value="${mail.host}"/>
14. <property name="serverPort" value="${mail.port}"/>
15. <property name="authUserName" value="${mail.username}"/>
16. <property name="authPassword" value="${mail.password}"/>
17. <property name="mailFrom" value="${mail.from}"/>
18. </bean>
19. </property>
20. </bean>
21. </property>
22. <property name="membershipManager" ref="myMembershipManager" />
23. <property name="userDetailsManager" ref="myUserDetailsManager" />
24. <property name="taskNotificationManager" ref="myTaskNotificationManager" />
25. </bean>
可以看到,TaskAlarmServiceImpl包含如下重要属性:
l periodInAdvance:任务催办时间提前量(相对于dueDate而言),格式采用ISO 8601时间段表示法(和Activiti的due date格式一样,参考http://en.wikipedia.org/wiki/ISO_8601#Durations),如:P2D代表提前2天
l messageNotifier:定义通知的方式,如上示例的是邮件发送的方式,用户可以改造成其它方式,如:短信方式,或者组合方式;
l membershipManager:成员关系管理器,TaskAlarmService会通知到候选组里面的所有成员;
l userDetailsManager:用户详细信息管理器,TaskAlarmService会在发送通知信息的时候用到用户相关属性,如:邮箱、手机号等;
l taskNotificationManager:任务通知信息管理;
ProcessEngine在启动时会加载StartTaskAlarmService,从而启动催办服务。
4.4.2 使用方法
欲使用任务催办功能,需要遵循如下步骤:
l 配置myTaskNotificationManager 、myUserDetailsManager和myMembershipManager;
l 配置myTaskAlarmService;
l 在activiti.cfg.core.xml中的processEngineConfiguration里打开StartTaskAlarmService(默认情况下这是打开的);
接下来,不需要任何设置,在任务即将过期(dueDate)的时候,委托人(assignee)或候选人就会收到催办通知。
4.5 任务流程控制
OpenWebFlow提供了安全的加签(包括前加签/后加签)、自由跳转(包括前进/后)、分裂节点等功能。
4.5.1 设计方案
任务流程控制功能由TaskFlowControlService提供,相关的实现在org.openwebflow.ctrl包里面,一般通过TaskFlowControlServiceFactory获取到TaskFlowControlService。
任务流程控制功能实现的关键思路是:将对既有流程的各种调整映射成“对Activity对象的更新及克隆”,并在必要的时候还要实现持久化和加载。
OpenWebFlow在实现“新流程”的持久化的时候玩了一个trick,即仅仅将“调整”的方式(活动工厂信息)做持久化,而非针对“调整之后的新版本”做持久化。譬如,我们根据step2活动创建一个step21活动,所有的信息都一样,这个时候只要持久化工厂类型(活动克隆)、模板活动ID(step2)、新活动ID(step21)就可以了。比较复杂的例子,是将某个活动分裂成N个串行的会签活动,这种情况也只需要记录模板活动ID、新活动ID数组,不需要记录更多的信息。如下示出一个创建N个用户任务活动的例子:
1. public class ChainedActivitiesCreator extends RuntimeActivityCreatorSupport implements RuntimeActivityCreator
2.{
3. public ActivityImpl[]createActivities(ProcessEngine processEngine, ProcessDefinitionEntityprocessDefinition,
4. RuntimeActivityDefinitionEntity info)
5. {
6. info.setFactoryName(ChainedActivitiesCreator.class.getName());
7. RuntimeActivityDefinitionEntityIntepreter radei = newRuntimeActivityDefinitionEntityIntepreter(info);
8.
9. if(radei.getCloneActivityIds() == null)
10. {
11. radei.setCloneActivityIds(CollectionUtils.arrayToList(new String[radei.getAssignees().size()]));
12. }
13.
14. returncreateActivities(processEngine, processDefinition, info.getProcessInstanceId(),
15. radei.getPrototypeActivityId(),radei.getNextActivityId(), radei.getAssignees(),
16. radei.getCloneActivityIds());
17. }
18.
19. private ActivityImpl[]createActivities(ProcessEngine processEngine, ProcessDefinitionEntityprocessDefinition,
20. String processInstanceId, String prototypeActivityId,String nextActivityId, List<String> assignees,
21. List<String> activityIds)
22. {
23. ActivityImpl prototypeActivity = ProcessDefinitionUtils.getActivity(processEngine,processDefinition.getId(),
24. prototypeActivityId);
25.
26. List<ActivityImpl> activities = new ArrayList<ActivityImpl>();
27. for (int i = 0; i < assignees.size(); i++)
28. {
29. if(activityIds.get(i) == null)
30. {
31. String activityId = createUniqueActivityId(processInstanceId,prototypeActivityId);
32. activityIds.set(i, activityId);
33. }
34.
35. ActivityImpl clone = createActivity(processEngine,processDefinition, prototypeActivity,
36. activityIds.get(i), assignees.get(i));
37. activities.add(clone);
38. }
39.
40. ActivityImpl nextActivity = ProcessDefinitionUtils.getActivity(processEngine,processDefinition.getId(),
41. nextActivityId);
42. createActivityChain(activities, nextActivity);
43.
44. returnactivities.toArray(newActivityImpl[0]);
45. }
46.}
活动工厂信息用RuntimeActivityDefinitionEntity类来表示,为了方便,不同活动工厂的个性化信息存成了一个JSON字符串,并会在加载的时候解析成一个Map。如下是一个节点分裂的活动工厂信息:
1. {"sequential":true,"assignees":["bluejoe","alex"],"cloneActivityId":"2520001:step2:1419823449424-8","prototypeActivityId":"step2"}
通过RuntimeActivityDefinitionEntity来调整流程,通过一系列的creator来表示。如:org.openwebflow.ctrl.creator.MultiInstanceActivityCreator用来创建多实例节点。
4.5.2 使用方法
欲使用任务流程控制功能,需要遵循如下步骤:
l 配置myActivityPermissionManager、myActivityDefinitionManager;
l 在activiti.cfg.core.xml中的processEngineConfiguration里打开LoadRuntimeActivityDefinitions(默认情况下这是打开的),该设置会自动加载持久化的活动定义;
l 配置TaskFlowControlServiceFactory;
1. <!-- 工作流流转服务对象工厂-->
2. <bean class="org.openwebflow.ctrl.impl.DefaultTaskFlowControlServiceFactory"/>
l 获取到TaskFlowControlServiceFactory,创建TaskFlowControlService:
1. _taskFlowControlServiceFactory = _ctx.getBean(DefaultTaskFlowControlServiceFactory.class);
2. ProcessInstanceinstance = _processEngine.getRuntimeService().startProcessInstanceByKey("test2");
3. TaskFlowControlServicetfcs = _taskFlowControlServiceFactory.create(instance.getId());
l 使用TaskFlowControlService:
1. ActivityImpl[]as = tfcs.insertTasksBefore("step2", "bluejoe", "alex");
4.6 模型文件导入
默认情况下,在activiti.cfg.core.xml中的processEngineConfiguration里会打开ImportDefinedProcessModels:
1. <!-- 启动催办管理器 -->
2. <bean class="org.openwebflow.cfg.StartTaskAlarmService">
3. <property name="taskAlarmService" ref="myTaskAlarmService" />
4. <property name="runOnStartup" value="false"/>
5. </bean>
该配置自动加载指定路径下(${model.dir})的BPMN模型文件(以.bpmn为后缀)至Activiti的repository库。
如果需要手动加载,可以使用ProcessEngineTool或者ModelUtils类。
5. 使用管理器接口实现自定义扩展
OpenWebFlow需要用户提供6类管理器的接口,它们分别是:
l RuntimeActivityDefinitionManager:负责获取活动的定义信息,用以支持运行时期的新建活动
l ActivityPermissionManager:负责获取活动的权限设置信息
l TaskNotificationManager:负责存取任务催办通知信息
l DelegationManager:负责获取用户的代理信息
l UserDetailsManager:负责获取用户的信息(包括E-mail、昵称、手机号等),主要用以发送催办通知
l IdentityMembershipManager:负责获取用户组成员关系,获取某用户的候选任务队列时,需要通过用户名获取到用户组
除了这些Manager之外,用户会发现OpenWebFlow还提供了一系列的ManagerEx接口:
l ActivityPermissionManagerEx:负责保存活动的权限设置信息
l TaskNotificationManagerEx:负责保存任务催办通知信息
l DelegationManagerEx:负责保存用户的代理信息
l UserDetailsManagerEx:负责保存用户的信息
l 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://github.com/bluejoe2008/openwebflow/tree/master/doc,可通过该地址及时查阅最新版本。
如果用户需要查阅OpenWebFlow的Java API,可以参考javadoc(https://github.com/bluejoe2008/openwebflow/tree/master/openwebflow-core/doc/javadoc)。
另外可以关注Wiki(https://github.com/bluejoe2008/openwebflow/wiki),提交话题(https://github.com/bluejoe2008/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
目前作者已经针对以上两个bug提交了bugfix并被master版本合并。不过考虑到版本稳定性问题,OpenWebFlow最新版本还是采用了其他方法来避免了如上bug的发生。
OpenWebFlow0.9用户手册与设计说明的更多相关文章
- Rafy 框架-发布网页版用户手册
前段时间把 Rafy 的用户手册由 CHM 格式转换为了网页格式,而且发布到了 github.io 上,即方便文档的实时更新,也方便大家查看. Rafy 用户手册网页版地址: http://zgynh ...
- sqlmap用户手册 | WooYun知识库
sqlmap用户手册 说明:本文为转载,对原文中一些明显的拼写错误进行修正,并标注对自己有用的信息. 原文:http://drops.wooyun.org/tips/143 ============ ...
- Windows Azure Web Site (1) 用户手册
<Windows Azure Platform 系列文章目录> 下载地址: Web Apps用户手册
- Windows Azure Cloud Service (1) 用户手册
<Windows Azure Platform 系列文章目录> 下载地址 Cloud Service用户手册
- Windows Azure Virtual Machine (1) IaaS用户手册
<Windows Azure Platform 系列文章目录> Azure IaaS用户手册 - Azure IaaS相关技术- Azure虚拟机成本分析- 创建Azure虚拟机- 使用 ...
- Azure SQL Database (1) 用户手册
<Windows Azure Platform 系列文章目录> 最新更新2016年6月17日 下载地址:Azure SQL Database用户手册
- AnyCAD .Net SDK 用户手册 v2013.1
AnyCAD .Net SDK 用户手册 v2013.1 1. 简介 AnyCAD .Net SDK为.Net4.0开发者提供简单易用的三维建模和三维可视化的API.SDK主要由三维建模的API和可视 ...
- EdasStudio 开发工具用户手册
EdasStudio 开发工具用户手册 Edas 开发组2015-8-14 1. 下载安装插件 EdasStudio是EDAS的开发工具,是一个Eclipse Plugins,打开Eclipse的He ...
- activitie用户手册
最近公司开发流程,学习流程开发,不停看api学习.这是做软件的额...不停的学习学习!!!天天进步中! 用户手册地址:http://www.mossle.com/docs/activiti/#acti ...
随机推荐
- 恒天云技术分享系列2 - vlan管理GUI开发
恒天云:http://www.hengtianyun.com/download-show-id-10.html 在OpenStack G版本中quantum网络模式下,horizon提供了基于quan ...
- HDU-4611 Balls Rearrangement 循环节,模拟
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4611 先求出循环节,然后比较A和B的大小模拟过去... //STATUS:C++_AC_15MS_43 ...
- Windows性能监视器之CPU、硬盘、IO等监控方法详解-摘自网络
一般操作系统性能主要涉及到的问题主要有:处理器使用情况.内存占有量.磁盘I/0操作以及网络流量等. 查看Windows性能情况,大部分情况下是通过 “Windows任务管理器”,可以通过在 ”命令行” ...
- Android NDK r8 windows环境搭建
Android NDK r8 windows环境搭建 一.默认基础环境为已经完成Android开发环境的搭建 需要的软件及插件 1. JDK-7u25 2. Eclipse 3. Android SD ...
- void类型及void指针
1.概述 许多初学者对C/C 语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并 详述void及void指针类型的使用方法与技巧. 2 ...
- hdu 1877 又一版 A+B
又一版 A+B Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- (step 4.3.5)hdu 1035(Robot Motion——DFS)
题目大意:输入三个整数n,m,k,分别表示在接下来有一个n行m列的地图.一个机器人从第一行的第k列进入.问机器人经过多少步才能出来.如果出现了循环 则输出循环的步数 解题思路:DFS 代码如下(有详细 ...
- ASP.NET奇葩说
1.form表单 在asp.net中(即runat="server"特性时)method默认值为post 在html中默认是get. 2.Web应用程序项目和网站项目:前者后台文 ...
- 【Stage3D学习笔记续】山寨Starling(九):上下文丢失处理方法
Stage3D在运行中是存在随时会丢失上下文的尴尬情况. 渲染内容丢失的问题本身就说明是因为丢失了Context3D对象.出现此问题的原因很多,通常还不是因为Stage3D应用.比如在win7系统中, ...
- JAVA js的escape函数、解析用js encodeURI编码的字符串、utf8转gb2312的函数
在使用webView时,如果url中参数有中文的话,拦截到的字符串就会类似这样的:http://api.letstar.cn/zq/news.html?id=20&cupName=%E6%B5 ...