启动节点start
每个流程里面至少有一个开始节点(到目前为止一个流程只能有一个开始节点),开始节点必须有一个向外的流向,这个流向会在流程启动时执行。
状态节点state
State是一个等待状态节点,流程实例执行到state节点后,会一直处于等待状态,直到外部触发器调用API。State节点和其他的节点不同,它没有任何属性或元素。
让我们看一个用序列连接状态 和转移的例子。
<process name="StateSequence" xmlns="http://jbpm.org/4.4/jpdl">
<start>
<transition to="a" />
</start>
<state name="a">
<transition to="b" />
</state>
<state name="b">
<transition to="c" />
</state>
<state name="c" />
</process>
创建的流程处理实例会停留在状态节点a的位置, 使用signalExecution方法就会触发 一个外部触发器。
decision决定节点
在多个选择中选择一条路径。也可以当做是一个决定。 一个决定活动拥有很多个向外的转移。当一个流向到达一个决定活动时, 会自动执行并决定交给哪个向外的转移。
一个决定节点应该配置成下面三个方式之一。
decision决定条件
decision中会运行并判断每一个transition里的判断条件。 当遇到一个嵌套条件是true或者没有设置判断条件的转移, 那么转移就会被运行。
1.EL表达式进行判断
例子:
<?xml version="1.0" encoding="UTF-8"?>
<process key="decision" name="decision" xmlns="http://jbpm.org/4.4/jpdl">
<start name="start1" g="31,162,48,48">
<transition name="提交" to="exclusive1" g="-37,-34"/>
</start>
<decision name="exclusive1" expr="${node}" g="161,162,48,48">
<transition name="大于2天,小于10天" to="科长" g="-33,-25"/>
<transition name="10天以上" to="主任" g="-21,19"/>
<transition name="小于2天" to="组长" g="-18,-32"/>
</decision>
<task assignee="zuzhang" name="组长" g="322,81,92,52">
<transition name="组长批准" to="归档" g="-25,-31"/>
</task>
<task assignee="kezhang" name="科长" g="326,171,92,52">
<transition name="科长批准" to="归档" g="-23,-20"/>
</task>
<task assignee="kezhang" name="主任" g="329,262,92,52">
<transition name="主任批准" to="归档" g="-38,-17"/>
</task>
<task assignee="caiwu" name="归档" g="501,171,92,52">
<transition name="通过" to="end1" g="-17,-26"/>
</task>
<end name="end1" g="654,174,48,48"/>
</process>
//发布流程
//启动流程实例
将流程变量node一起启动,这时流程自动流转到科长
2.使用Condition标签,将判断条件写在EL表达式中进行判断。
<?xml version="1.0" encoding="UTF-8"?>
<process key="decision" name="decision" xmlns="http://jbpm.org/4.4/jpdl">
<start name="start1" g="31,162,48,48">
<transition name="提交" to="exclusive1" g="-37,-34"/>
</start>
<decision name="exclusive1" g="161,162,48,48">
<transition name="大于2天,小于10天" to="科长" g="-33,-25">
<condition expr="${days ge 2 and days le 10}"/>
</transition>
<transition name="10天以上" to="主任" g="-21,19">
<condition expr="${days gt 10}"/>
</transition>
<transition name="小于2天" to="组长" g="-18,-32">
<condition expr="${days lt 2}"/>
</transition>
</decision>
<task assignee="zuzhang" name="组长" g="322,81,92,52">
<transition name="组长批准" to="归档" g="-25,-31"/>
</task>
<task assignee="kezhang" name="科长" g="326,171,92,52">
<transition name="科长批准" to="归档" g="-23,-20"/>
</task>
<task assignee="kezhang" name="主任" g="329,262,92,52">
<transition name="主任批准" to="归档" g="-38,-17"/>
</task>
<task assignee="caiwu" name="归档" g="501,171,92,52">
<transition name="通过" to="end1" g="-17,-26"/>
</task>
<end name="end1" g="654,174,48,48"/>
</process>
Map<String,Object> map=new HashMap<String,Object>();
map.put("days", 15);
ProcessInstance processInstance=executionService.startProcessInstanceByKey("decision",map);
此时流程自动流转到主任
3.handler方式:使用handler标签将具体的执行方向交给java类来决定
通过启动流程实例,为流程变量赋值
在上面的jpdl文件中,我们可以看到当流程启动的时候具体执行那个task是由decision决定的,而decision又将判断权交给了MyDecision类,下面来看Decision类代码:
task任务节点
任务分配的方式有以下四种:任务分配者assignee, task候选人candidate-groups, 任务分配处理器AssignmentHandler, 任务泳道swimlane
<?xml version="1.0" encoding="UTF-8"?>
<process key="task" name="task" xmlns="http://jbpm.org/4.4/jpdl">
<start name="start1" g="318,20,48,48">
<transition name="提交到任务A" to="任务A" g="-67,-9"/>
</start>
<end name="end1" g="321,374,48,48"/>
<task assignee="A" name="任务A" g="297,101,92,52">
<transition name="提交到任务B" to="任务B" g="-68,-10"/>
</task>
<task assignee="B" name="任务B" g="295,199,92,52">
<transition name="提交到任务C" to="任务C" g="-65,-6"/>
</task>
<task assignee="C" name="任务C" g="297,290,92,52">
<transition name="通过" to="end1" g="-63,-5"/>
</task>
</process>
一个简单的任务会被分配给一个指定的用户
获得A的任务列表如下:
List taskList = taskService.findPersonalTasks(“A”);
2. task候选人candidate-groups
<?xml version="1.0" encoding="UTF-8"?>
<process key="task" name="task" xmlns="http://jbpm.org/4.4/jpdl">
<start name="start1" g="318,20,48,48">
<transition name="提交到任务A" to="任务A" g="-67,-9"/>
</start>
<end name="end1" g="321,374,48,48"/>
<task candidate-groups="mgr" name="任务A" g="297,101,92,52">
<transition name="提交到任务B" to="任务B" g="-68,-10"/>
</task>
<task name="任务B" g="295,199,92,52">
<transition name="提交到任务C" to="任务C" g="-65,-6"/>
</task>
<task name="任务C" g="297,290,92,52">
<transition name="通过" to="end1" g="-63,-5"/>
</task>
</process>
candidate属性。该属性在task节点中,他的作用类似于组内工作分配,假如一个组内有两个人a1和a2,将该属性所在任务分配给两人中的一个后,则只有该任务被分配人才能看到任务,其他人都看不到。
注意上面的jpdl文件中存在candidate-groups属性,其值为“mgr”,这样在后台对应创建该组并为该组添加组员的java代码如下:
String groups=identityService.createGroup("mgr");
identityService.createUser("a1", "tom", "uu");
identityService.createUser("a2", "tom2", "uu2");
identityService.createMembership("a1", groups);
identityService.createMembership("a2", groups);
repositoryService.createDeployment().addResourceFromClasspath
("com/yashi/jbpm/node/task/task3.jpdl.xml").deploy()
把任务分配给a1
taskService.takeTask("350002", "a1");
List<Task> tasks=taskService.findPersonalTasks("a1");
需要注意的是在我们部署流程的时候就创建了两个组员a1和a2,并且将这两个人加入到了mgr组,当执行创建流程以后由于该组得到了任务,但是这个任务没有分配给具体的组员,所以凡是这个组的组员都可以看到这个任务,也就是说当执行getGroupTask()的时候,无论是a1还是a2都有共同的任务,但是当执行getTask()把任务分配给a2以后,组任务也就随之消失,这时执行getGroupTask()函数无论参数是a1还是a2都获取不到任务了。原因就在于没分配之前是组任务,分配之后变成了私人任务,组任务这个概念也就没有了。只有在执行getTask()并且参数为a2的时候才能看到此任务。
3.任务分配处理器AssignmentHandler
task节点的handler属性。该属性的作用是动态分配assignee
这时候assignmentTask的分配处理器被调用,获得userA的任务列表
4.任务泳道swimlane
从上面的jpdl配置中我们可以看到,首先有一个swimLane标签,这就是我们所建的名为“mySwim”的泳道,在“任务A”和“任务C”中都存在swimLane属性,其值都为“mySwim”,这表明这两个人都在泳道mySwim中,也就是说这两个任务的执行人为同一个人。
fork…jion节点
fork和join这两个节点总是成对出现的,有分叉必然有合并。他们所起的作用为有多个任务必须全部完成才能进入到下一个任务中。也就是说fork标签中的全部transition全部完成后才能进入到join标签中的transition。具体的jpdl文件如下:
使用fork与单个task的不同之处其实仅在task的数目,fork中的每个transition其实指向的是另外一个task,并且fork中transition指向的task并没有顺序之分,各个任务的地位是平等的。
当部署好流程并创建一个流程实例后执行getCurrentActivity()函数执行结果显示当前任务是[A,B,C],这种情况印证了fork中的任务是没有顺序之分的,当我们执行completeTask()函数完成A的任务后,再次执行getCurrentActivity()函数,结果显示当前任务是[B,C],并不是进入到了“合并”任务,当将任务B和任务C全部结束后再次执行getCurrentActivity(),结果显示此时A,B,C任务全部完成后才进入到了“合并”任务。