jBPM学习(七)----jBPM相关概念

七、 jBPM 相关概念

1.         JPDL 的流程定义元素
1)        第一层: GraphElement
这个容易理解 , 因为在画流程定义时 , 每个拖拉的对象都是一个 graph 的元素。 GraphElement 有四个属性:
(1)processDefine 表示当前元素属于哪个流程定义
(2)events 表示可以接收哪些 event
(3)name 名字
(4)exceptionHandlers 异常处理类集合 (List)
2)        第二层: node processDefinition Transition Task
它们都继承自 GraphElement
(1)processDefinition 表示流程定义 (implements NodeCollection), 它有下面的属性 :name version nodes startState nodes 表示流程中所有的 node startState 用于启动流程时找到首节点。
(2)Transition 表示转移,它有三个属性: from(Node) to(Node) supportedEventTypes 表示支持的 event 类型
(3)node 表示节点,它有四个属性: leaving transitions arriving transitions action superState
(4)Task 定义任务
3)        第三层:各种不同的 node
它们都继承自 node Decision EndState Fork Join Merge Milestone InterleaveEnd InterleaveStart ProcessState State
 
2.         jBPM token
jbpm 中最重要的概念,应该是令牌 (Token) 和信令 (Signal) 。在整个流程实例运行过程中,我们可以迅速的利用 token 得到其当前的 current state 。在解决“并行”等(比如 Fork )问题时, jBpm Token 对象维护了父子关系,这种关系在涉及到 Fork 的时候会产生。 jBpm Token 这个对象身兼了多种使命:
1 )快速定位 current state
2 )用于 fork join 算法
3 )用于告知任务执行者的任务索引。
如下代码 :
//pd process definition,pi process instance ProcessInstance
pi = new ProcessInstance( pd );
//
得到根令牌
Token token = pi.getRootToken();
//
发信令
token.signal();
Token signal 方法也可以传入 transition 参数 , 这个方法把信令发送给 Token, 这样 , 令牌将被激活 , 并沿指定的 transition 离开当前的状态 ( 如果没有指定 transition, 将沿缺省的 transition 离开当前状态 )
jbpm 是怎么实现的呢 ? 其实很简单 :
1)Token
记录了当前的状态( current state , 只有当前的状态 ( 或称节点 ) 拥有该令牌
2)
TOKEN signal , 当前状态收到该 signal
3)
当前状态把令牌传给 signal 中指定的 transition
4)transition
收到令牌后 , 不强占 , 马上把令牌传给下个状态 .
5)
根据令牌的位置 , 流程的状态已经发生改变 .
 
 
3.         process definition
一个 process definition 代表了一个正式的业务流程,它以一个流程图为基础。这个流程图由 许多 node transition 组成。每个 node 在这个流程图里都有着各自特殊的类型,这些不同的类型决定了 node 在运行时的不同行为。一个 process definition 只有一个 start state
4.         token
一个 token 代表了一条执行路径,它包含了这条执行路径的当前的执行状态( current state )。
5.         process instance
一个 process instance (流程实例)即一个 process definition (流程定义)的流程执行实例。一个 process definition 可以对应多个 process instance 。当一个 process instance 被创建的时候,一个主执行路径 token 同时被创建,这个 token 叫做 root token ,它指向流程定义的 start state processDefinition.getStartState()==token.getNode() )。
6.         signal
一个 signal 发送给 token 通知 token 继续流程的执行。如果 signal 没有指定 transition token 将沿缺省的 transition 离开当前状态 , 如果 signal 指定 transition token 将沿指定的 transition 离开当前的状态。看源代码可以看到发给 process instance signal 其实都是发送给了 root token
7.         Actions
jbpm 提供了灵活的 action ,当流程执行, token 进入 node transition 时,会触发相应的一些 event (事件)。在这些 event 上附上我们自己写的 action ,就会带动 action 的执行。 action 里是我们自己的相关 java 操作代码,非常方便。注意的是 event (事件)是内置的,无法扩展。另外, action 也可以直接挂在 node 上,而不依赖于 event (事件)的触发,这个很重要。
8.         node
一个流程图由许多 node transition 组成。每个 node 都有一种类型,这个类型决定了当流程执行到这个 node 时的不同行为。 jbpm 有一组 node type 可以供你选择,当然你可以定制自己 node
node 的作用
node 有两个主要的作用:
1 )执行 java 代码,比如说创建 task instance (任务实例)、发出通知、更新数据库等等。很典型的就是在 node 上挂上我们的 action
2) 控制流程的执行:
A 、等待状态:流程进入到这个 node 时将处于等待状态,直到一个 signal 的发出
B 、流程将沿着一个 leaving transition 越过这个 node ,这种情况特殊一点,需要有个 action 挂在这个 node 上(注意这个 action 不是 event 触发的!), action 中将会调用到 API executionContext.leaveNode(String transitionName) transitionName 即这里的 leaving transition 名字。
C 、创建新的执行路径:
很典型的就是 fork node 。流程在这里会分叉,产生新的执行路径。这样就创建了新的 token ,每个新的 token 代表一个新的执行路径。注意的是,这些新的 token 和产生前的 token 是父子关系!
D 、结束执行路径:一个 node 可以结束一条执行路径,这同样意味着相应的 token 的结束和流程的结束。
9.         流程图中的 node type
1)        task-node
一个 task-node 可以包含一个或多个 task ,这些 task 分配给特定的 user 。当流程执行到 task-node 时, task instance 将会被创建,一个 task 对应一个 task instance task instances 创建后, task-node 就处于等待状态。当所有的 task instances 被特定的 user 执行完毕后,将会发出一个新的 signal token ,即流程继续执行。
2)        state
state 是一个纯粹的 wait state( 等待状态)。它和 task-node 的区别就是它不会创建 task instances 。很典型的用法是,当进入这个节点时(通过绑定一个 action node-enter event ),发送一条消息到外部的系统,然后流程就处于等待状态。外部系统完成一些操作后返回一条消息,这个消息触发一个 signal token ,然后流程继续执行。(不常用)
3)        decision
当需要在流程中根据不同条件来判断执行不同路径时,就可以用 decision 节点。两种方法:最简单的是在 transitions 里增加 condition elements (条件), condition beanshell script 写的,它返回一个 boolean 。当运行的时候, decision 节点将会在它的 leaving transitions 里循环,同时比较 leaving transitions 里的 condition ,最先返回 'true' condition ,那个 leaving transitions 将会被执行;作为选择,你可以实现 DecisionHandler 接口,它有一个 decide() 方法,该方法返回一个 String(leaving transition 的名字)。
4)        fork
fork 节点把一条执行路径分离成多条同时进行(并发)的执行路径,每条离开 fork 节点的路径产生一个子 token
5)        join
默认情况下, join 节点会认为所有到达该节点的 token 都有着相同的父 token join 节点会结束每一个到达该节点的 token, 当所有的子 token 都到达该节点后,父 token 会激活。当仍然有子 token 处于活动状态时, join 节点是 wait state( 等待状态)。
6)        node
node 节点就是让你挂自己的 action 用的(注意:不是 event 触发!),当流程到达该节点时, action 会被执行。你的 action 要实现 ActionHandler 接口。同样,在你的 action 里要控制流程。
 
10.     Actions 的说明
存在两种 action ,一种是 event 触发的 action ,一种是挂在 node 节点的 action 。要注意它们的区别, event 触发的 action 无法控制流程,也就是说它无法决定流程经过这个节点后下一步将到哪一个 leaving transition ;而挂在 node 节点的 action 就不同,它可以控制流程。不管是哪一种 action 都要实现 ActionHandler 接口。
11.     Task (任务)
jbpm 一个相当重要的功能就是对任务进行管理。 Task (任务)是流程定义里的一部分,它决定了 task instance 的创建和分配。 Task (任务)可以在 task-node 节点下定义,也可以挂在 process-definition 节点下。最普遍的方式是在 task-node 节点下定义一个或多个任务。默认情况下,流程在 task-node 节点会处于等待状态,直到所有的任务被执行完毕。任务的名称在整个流程中必须是唯一的。一个 TaskNode 对应多个 Task
对于这样的流程定义:
<task-node name="a"></task-node>
xml 代码
  1. < task-node   name = 'a' >     
  2. < task   name = 'laundry'   />     
  3. < task   name = 'dishes'   />     
  4. < task   name = 'change nappy'   />     
  5. < transition   to = 'b'   />     
  6. </ task-node >     
只有当节点中的三个任务都完成后,流程才进入后面的节点

对于这样的流程定义:
xml 代码
<transition to="b"> </transition>
  1. < task-node   name = 'a'   signal = 'first' > >     
  2. < task   name = 'laundry'   />     
  3. < task   name = 'dishes'   />     
  4. < task   name = 'change nappy'   />     
  5. < transition   to = 'b'   />     
  6. </ task-node >     
当第一个任务完成后, token 就指向后面的节点

对于这样的流程定义:
<task-node name="a" signal="never"></task-node>
xml 代码
  1. < task-node   name = 'a'   signal = 'never' > >     
  2. < task   name = 'laundry'   />     
  3. < task   name = 'dishes'   />     
  4. < task   name = 'change nappy'   />     
  5. < transition   to = 'b'   />     
  6. </ task-node >     
三个任务都完成后, token 仍然不会指向后面的节点;需要自己手动调用 processInstance.signal() 才会驱动流程到下面的节点

对于这样的流程定义:
<task-node name="a" signal="unsynchronized"></task-node>
xml 代码
  1. < task-node   name = 'a'   signal = 'unsynchronized' > >     
  2. < task   name = 'laundry'   />     
  3. < task   name = 'dishes'   />     
  4. < task   name = 'change nappy'   />     
  5. < transition   to = 'b'   />     
  6. </ task-node >     
token 不会在本节点停留,而是直接到后面的节点
 
12.     jbpm 的任务管理实现
一个 Task instance (任务实例)可以被分配给一个 actorId (java.lang.String) 。所有的 Task instance 都被保存在数据库中的表 jbpm_taskinstance 里。当你想得到特定用户的任务清单时,你就可以通过一个与用户关联的 actorId 来查询这张表。
一个流程定义有一个 TaskMgmtDefinition ;一个 TaskMgmtDefinition 对应多个 swimlane, 同时对应多个 task; 一个 swimlane 有多个 task, 可以从 TaskMgmtDefinition 中通过 task 的名称直接获取相应的 task;
swimlane 对象有四个属性,分别是 name (名字)、 assignmentDelegation (分配代理类)、 taskMgmtDefinition tasks Set 对应多个 task), 可以增加 task
task 对象主要的属性: taskMgmtDefinition swimlane assignmentDelegation taskNode ,需要注意的是 swimlane assignmentDelegation 中间只是可以一个属性有值,因为它们都和任务的分配有关系。
一个流程实例有一个 TaskMgmtInstance ;一个 TaskMgmtInstance 对应多个 swimlaneInstance, 同时对应多个 taskInstance; 一个 swimlaneInstance 有多个 taskInstance, 可以从 TaskMgmtInstance 中直接获取相应的 taskInstance;
swimlaneInstance 对象主要有五个属性,分别是 name actorId pooledActors Set )、 swimlane taskMgmtInstance
taskInstance 对象的主要属性: name actorId task swimlaneInstance taskMgmtInstance pooledActors
当对任务进行分配时,一般需要实现 AssignmentHandler 这个接口,这个接口的方法只有一个:
void assign( Assignable assignable, ExecutionContext executionContext ) throws Exception;
一个典型的实现(把名字是 'change nappy' 的任务交给 NappyAssignmentHandler 这个类来分配)
xml 代码
  1. < task   name = 'change nappy' >     
  2. < assignment   class = 'org.jbpm.tutorial.taskmgmt.NappyAssignmentHandler'   />     
  3. task >     NappyAssignmentHandler 类:
    java 代码
    1. public   void  assign(Assignable assignable, ExecutionContext executionContext) {    
    2. assignable.setActorId( "papa" );    
    3. }    
    同样, Assignable 只是一个接口,它有两个方法: setActorId() setPooledActors() Assignable 的具体实现类也是两个: swimlaneInstancehe taskInstance 。这样就不不难理解整个任务分配流程了:

1 、流程进入 TaskNode 节点,执行 TaskNode 类的 execute() 方法,该方法首先获得 TaskMgmtInstance 实例,然后通过它来创建 TaskInstance taskMgmtInstance.createTaskInstance(task, executionContext);
2 、在上面的 createTaskInstance(task, executionContext) 里,该方法调用了 taskInstance.assign(executionContext) taskInstance 进行分配。
3 、在 assign(executionContext) 方法里,首先会判断 task 属性里是否存在 swimlane ,如果有的话,这个 taskInstance 就会分配给 swimlane 指定的 ActorId PooledActors ;如果不存在,再去找 task 属性里 assignmentDelegation (分配代理类)通过代理类(即我们自己写的实现 AssignmentHandler 这个接口的类)指定 ActorId PooledActors
 
13.     jbpm 的用户角色管理
jbpm 在用户角色管理上共设计了四个类: Entity Membership Group User
Entity 类是其他三个类的父类,它包含了两个属性: name(String) permissions(Set)
User 类继承 Entity 类,包含三个属性: password(String) email(String) memberships(Set)
Group 类继承 Entity 类,包含四个属性 : type(String) parent(Group) children(Set) memberships(Set)
Membership 类继承 Entity 类,包含三个属性 :role(String) user(User) group(Group)
很明显,一个 user 对应一个用户,一个 group 对应一个用户组,它们之间通过 membership 关联,并且一个 user 可以属于多个不同类型( type) group user group 之间是多对多的关系。 Membership 类的 role 属性个人感觉用途不大,反倒是 name 属性代表了 user group 里的 role (角色)。

你可能感兴趣的:(xml,算法,jbpm,活动)