传智播客学习笔记5.31

传智播客学习笔记5.31

节点
不同的节点类型代表不同的行为
等待节点:与外部节点交互时使用
create-task="false" signal="last-wait":一并使用

决策节点中的表达式:
#{money gt 1000 ? "to audit" : "to end"}

断言
Assert.assertEquals("","");

事件


变量
动作

* 节点
不同的节点类型代表不同的行为。

** start-state
开始节点,标识流程开始边界。开始状态有且只有一个,就是说流程中不能有任何
transition指向开始节点。

在流程实例被创建后(启动),RootToken(根令牌)就指向start-state,并且
处于等待状态,需要给Token发信号(signal)才能使流程继续执行。

** end-state
结束节点,标识流程的结束边界。不需要transition元素。

** task-node
任务节点,可以包含任意数量的Task(任务)。当执行到一个任务节点的时候,
将会根据这个task-node中的task的定义,创建相同数量的TaskInstance(为每一
个Task都创建一个任务实例,并且分配给任务定义中指定的参与者)。然后,这
个task-node一直处于等待状态,等到这些任务实例都被完成后,才会离开当前的
节点,到达下一个节点。

如果一个task-node中没有定义任务,执行时,一进入这个节点就会马上离开,即
Token不会在这个task-node上停留,因为他发现所有的任务实例都执行完了(任
务实例的数量为0)。

调用TaskInstance.end(String transitionName)时,如果这个任务实例不是当前
任务节点中的最后完成的那个,那这个方法就只是完成任务而已,并不会使用这
指定的transition离开节点。 就是说:只有当这个任务实例完成后,Token就要
离开当前节点,到达下一个节点时,指定的transitionName才有作用。

** task-node的属性: signal 和 create-tasks
signal属性:指定完成任务实例对执行流程的影响(发信号)。

属性可取的值:

    last:默认值.当最后一个实例被完成时候发信号。当在这个入口没有任务被
生成时候,流程继续执行(发信号)
    first:当第一个实例被完成时候发信号。当在这个入口没有任务被生成时
候,执行继续.
    never:不管任务实例是否完成,都不发信号。
    unsynchronized:进入节点后就发信号,不管任务是否没建立或有没有完成。
就是说任务的执行和流程执行互不影响。
    last-wait:当进入节点时没有任务实例被创建时,就会一直处于等待状态,
直到任务实例被创建;创建任务实例后,就是当所有的实例都执行完成后发信号
(和last一样了)。
    first-wait: 和last-wait一样理解。

last-wait和first-wait的wait是分开来理解的,wait是指的等待任务实例的创建,而
到达task-node后有任务实例被创建了,wait就没有影响了,这时task-node的行为
就是wait前面那个'first'或'last'决定了,即执行完第一个任务实例就离开节点
还是所有任务实例都执行完才离开节点.

当signal设置为"last-wait"或"first-wait",并且在task-node中没有配置任务
时,流程执行到这个节点时也会等待。

create-tasks属性:指定在进入task-node时是否创建任务实例(默认为true)。
(通常在做会签等这个需要动态的创建多个任务实例的的情况下使用,可以与
signal="last-wait"配合使用)


** 动态的创建不确定数量的任务实例
实现任务分配给多个人,需要做以下工作:1, 阻止jBPM自动创建任务实例(设
置task-node的create-tasks="false");2,在流程定义中定义的相应的任务,
不指定参与者;3,在node-enter事件中定义一个动作指定用于创建
TaskInstance的类。

创建任务实例要调用方法:
  TaskMgmtInstance.createTaskInstance(Task, ExecutionContext);
其中的Task 是任务的定义,可以先得到当前的节点:
  TaskNode taskNode = (TaskNode) executionContext.getNode();
然后通过任务的名字得到任务的定义:
  Task task = taskNode.getTask("审批");


使用报销的流程,在发起报销申请的节点(第一个)中,再增加一个任务:扫描
发票。用于测试在一个task-node中定义多个task的情况。

** state
状态节点,这是一个等待节点。当执行到达这个节点的时候,就会处于等待状态,
须给token发一个信号(signal)才能使流程继续执行。

** decision
决策节点,用于计算流向。有两种计算方式:
  1> 在decision中使用DecisionHandler,或使用一个表达式。
     (都是返回要使用的transition的name);
  2> 在decision中的transition元素中使用boolean表达式。这样将使用表达式
     计算结果为真的那个transition离开节点。
     a) 只有decision节点中的transition元素的的condition可以计算。在其他
        节点是不起作用的!
     b) 如果有多个transition的condition计算为true,将会使用第一个结果为
        true的transition(按定义中的顺序);
     c) 如果所有的transition的condition的值都为false,则使用第一个。

如果以上方法同时使用,调用的顺序为:
  如果有decisionDelegation,则使用它的计算结果。否则,
  如果有decisionExpression,则使用它的计算结果。否则,
  如果使用decisionConditions(trasnition中的表达式)的计算结果。

使用报销的流程,实现报销金额小于或等于500元时只需经理批准即可,否则还需
总经理审批通过。

** expression(表达式)
和我们在jsp中使用的el表达式相似,只是${}改为#{}。

表达式中可以直接使用已设置的流程变量,并且可以直接使用以下变量:
  taskInstance
  processInstance
  processDefinition
  token
  taskMgmtInstance
  contextInstance

所有fork节点的transaction上要指定名字,否则会报空指针异常
新增token时会根据名字排序

node节点


下午---------------------

添加约束文件
<process-definition xmlns="urn:jbpm.org:jpdl-3.2">
  ...
</process-definition>

And second, the xerces parser has to be on the classpath.

The jPDL schema can be found in ${jbpm.home}/src/java.jbpm/org/jbpm/jpdl/xml/jpdl-3.2.xsd or at http://jbpm.org/jpdl-3.2.xsd.

事件的定义不能影响流程的进行(不能发信号)!

事件触发时,token是被锁定的

注意事件和node的差别

* 任务分配
任务分派有两种模式,分别是推(push)模式和拉(pull)模式。

推模式(个人任务):是在任务分派的时候,直接将任务实例分派给一个指定的
用户,任务实例进入这个用户的个人任务列表中。

拉模式(组任务):是将任务实例分派给一组用户,这个任务实例会出现在(这
个组中用户的)组任务列表中。执行组任务时,需要首先将任务实例拉到自己的
个人任务列表中,然后执行此任务。当有一个组任务被某个组用户取出后,该任
务实例就会从组任务列表中移除。(任务竞争的机制)

这两种分配任务的模式都可以使用任务分派接口AssignmentHandler来实现。任务
在定义的时候指定对应的AssignmentHandler接口实现类。引擎在创建任务实例的
时候会调用接口中的assign方法。其实现应该调用参数assignable的方法对任务
进行分派。

** push (personal task list)
分配任务的方式:
  1> 在流程定义中定义任务时,用actor-id指定(一个固定值或表达式);
  2> 在程序代码中使用TaskInstance.setActorId(String)指定;
  3> 使用AssignmentHandler,方法为assignable.setActorId(String);

查询个人任务列表的方法为:
  TaskMgmtSession.findTaskInstances(String actorId);

** pull (group task list)
分配任务的方式:
  1> 在流程定义中定义任务时,用pooled-actors指定(多个参与者用逗号隔开);
  2> 在程序代码中使用TaskInstance.setPooledActors(String[])指定;
  3> 使用AssignmentHandler,方法为assignable.setPooledActors(String[]);

查询组任务列表的方法为:
  TaskMgmtSession.findPooledTaskInstances(String actorId);

对于一个组任务,如果他的actorId为null,组中所有的用户都可以在组任务列表
中看到这个任务。如果使用TaskInstance.setActorId(String)方法设置这个任务
由指定的acrorId来办理,这时pooledActors中的其他人就看不到这个任务了,就
是说actorId会屏蔽pooledActors; 当这个用户因某些原因不能办理任务时,应
该把这个任务再退回到组任务列表中,方法是调用TaskInstance.setActorId()设
置actorId为null,这时pooledActors中的所有人又都可以看到这个任务了。

员工报销,他所在的部门有三个经理,只需其中一个(任一个)审批通过即可。
这三个经理都能够看到审批的任务,但是只能有一个经理进行审批;
如果有一个经理签收这个任务,另外的那些经理们应该看不到这个任务了;
如果占有任务的经理因某原因不能完成任务,应再把作任务退回到组任务列表中,
以便让所有的经理都看到,再次进行任务竟争。

** summary
不管使用哪种方式分配任务,参与者的计算(确定)都是由业务层负责解释的。

组任务  :pooledActors!=null && actorId == null.
个人任务:actorId != null.

pooledActor = {"A", "B", "C"};
通过查询组任务的api查不出个人任务,反之亦然。


** swimlane
泳道,是流程角色。这是用来指明 在一个流程中 要完成多个任务的 同一个参与
者的 机制。

在流程运行时,当第一次遇到任务实例分配给一个泳道的时候,引擎会创建相应
的泳道实例(swimlaneInstance),并计算对应的用户,其后所有分配给这个泳道
的任务实例都会分配给相同的用户。

前面的例子中,员工张三有两个任务:填报销单和领款。这里应该使用swimlane。

 

* 变量
org.jbpm.context.exe.ContextInstance是提供流程变量服务的中央接口。

变量分为两种:流程变量和临时变量。流程变量会被持久化到数据库中;临时变
量则不会(只是在放到内存中)。

** 流程变量
变量的访问和赋值是在某一个token上进行的,缺省时,是基于root Token。
变量名的类型为java.lang.String, 支持的变量值类型参见文档10.1节。
(如果变量值是PO,则PO的id应为long型)。

每个Token(执行路线)有它自己的一套流程变量。变量的作用域和所属的Token
的生命周期一致,不同的Token上的同名变量互不影响。

** 临时变量
临时变量的值允许使用任何类型,并且临时变量同Token无关。

graphSession:对流程实例和定义的查询
taskmgmtSession:对任务的查询


设置和获取PO类型变量的方法
// 1, 设置变量
BizForm bizForm = new BizForm();
jbpmContext.getSession().save(bizForm);
pi.getContextInstance().setVariable("bizFormId", bizForm.getId());
pi.getContextInstance().setVariable("bizFormClass", BizForm.class.getName());

// 2, 获取变量
int id = (Integer)pi.getContextInstance().getVariable("bizFormId");
String type = (String) pi.getContextInstance().getVariable("bizFormClass");
Class clazz = Class.forName(type);
BizForm bf = (BizForm)jbpmContext.getSession().get(clazz, id);

 

* Jbpm的持久化API
Jbpm中所有数据库操作的入口都是JbpmContext,这是最核心的一个类。各种的数
据库操作,JbpmContext都会委派给不同的Session(例如GraphSession,
TaskMgmtSession等)来处理。

** GraphSession
与流程图有关的数据库操作,如对流程定义和流程实例的增、删、查等操作。

** TaskMgmtSession
与任务实例有关的数据库操作,主要是任务实例的查询。

** ContextInstance
操作变量的类,可以添加或移除流程变量或临时变量,变量是就一个跟流程相关
联的key-value对。常用方法有setVariable(String key, Object value)与
getVariable(String key)。

* TaskMgmtInstance
主要是管理任务实例(TaskInstance)与角色(Swimlane)的。


汤老师讲课条理很清晰。同时,让学生自己补全代码,然后进行讲解的方法也很有效果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值