JBPM工作流(七)——详解流程图
概念:
流程图的组成:
a. 活动 Activity / 节点 Node
b. 流转 Transition / 连线(单向箭头)
c. 事件
1.流转(Transition)
a) 一般情况一个活动中可以指定一个或多个Transition
i. 开始活动(Start)中只能有一个Transition。
ii. 结束活动(End)中没有Transition。
iii. 其他活动中有一条或多条Transition
b) 如果Transition只有一个,则可以不指定名称(名称是null);如果有多个,则要分别指定唯一的名称。
2.活动(Activity)
a) 流转控制活动(预定义活动)
i. start开始活动
代表流程的开始边界,一个流程有且只能有一个Start活动。开始活动只能指定一个Transition。在流程实例启动后,会 自动的使用这个唯一的Transition离开开始活动,到一下个活动。
ii. end/end-error/end-cancel(结束活动)
代表流程的结束边界,可以有多个,也可以没有。如果有多个,则到达任一个结束活动,整个流程就都结束了;如果没 有,则到达最后那个没有Transition的活动,流程就结束了。
iii. state状态活动
作用:等待。可以使用signal使其结束等待,并向后执行一步。
iv. task任务活动
-->个人任务的分配
1. 使用流程变量:assignee="#{manager}"
2. AssignmentHandler:assignable.setAssignee(userId); // 指定当前任务的办理人(分配任务)
a) 需要在.jbdl.xml的<task>元素中写
1
|
<assignment-handler class = "cn.grace.AssignmentHandlerImpl" /> |
b) 指定的AssignmentHandlerImpl类要实现AssignmentHandler接口
c) 在AssignmentHandlerImpl类中可以使用assignable.setAssignee(userId),分配个人任务。
3. TaskService.assignTask(taskId, userId)// 把指定的任务分配给指定的人
1
|
processEngine.getTaskService().assignTask(taskId, userId); |
-->组任务的分配
1. 使用流程变量:assignee="#{userIdsString}" // 要是String型的变量,多个候选人之前用','隔开
2. AssignmentHandler:assignable.addCandidateUser(userId);// 添加组任务的候选人
a) 需要在.jbdl.xml的<task>元素中写
1
|
<assignment-handler class = "cn.grace.GroupTaskAssignmentHandlerImpl" /> |
b) 指定的AssignmentHandlerImpl类要实现AssignmentHandler接口
c) 在AssignmentHandlerImpl类中可以使用assignable.addCandidateUser(userId),添加组任务候选人。
3. TaskService.addTaskParticipatingUser(taskId,userId,Participation.CANDIDATE);//添加组任务的候选人
v. Decision判断活动
1. 使用expression,如:expr="#{'to state2'}"
2. 使用Handler,在Handler Class里配置指定的DecisionHandlerImpl类的路径
DecisionHandlerImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class DecisionHandlerImpl implements DecisionHandler { // 计算离开当前节点用的Transition的名称并返回 @Override public String decide(OpenExecution execution) { System.out.println( "DecisionHandlerImpl.decide()" ); // 获取业务数据 Integer days = (Integer) execution.getVariable( "请假天数" ); // 选择Transition if (days > 7 ) { return "to 总经理审批" ; } else { return "to end1" ; } } } |
ProcessTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Test public void test() { // 1,部署流程定义 InputStream in = this .getClass().getResourceAsStream( "test.jpdl.xml" ); // 当前类所在包中的文件 processEngine.getRepositoryService() // .createDeployment() // .addResourceFromInputStream( "test.jpdl.xml" , in) // .deploy(); // 2,启动流程实例 Map<String, Object> variables = new HashMap<String, Object>(); // variables.put("请假天数", 10);启动流程实例后,进行到to 总经理审批环节。 variables.put( "请假天数" , 3 ); //启动流程实例后,进行到to end1环节。 ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey( "test" , variables); } |
此时,如果variables.put("请假天数", 3);启动流程实例后,进行到to end1环节。
此时,如果variables.put("请假天数", 10);启动流程实例后,进行到to 总经理审批环节。
3. 如果同时配置了expression与Handler,则expression有效,忽略Handler。
vi. fork、join分支/聚合活动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public class ProcessTest { private ProcessEngine processEngine = Configuration.getProcessEngine(); @Test public void test() { // 1,部署流程定义 InputStream in = this .getClass().getResourceAsStream( "test.jpdl.xml" ); // 当前类所在包中的文件 processEngine.getRepositoryService() // .createDeployment() // .addResourceFromInputStream( "test.jpdl.xml" , in) // .deploy(); // 2,启动流程实例 ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey( "test" ); System.out.println( "processInstanceId = " + pi.getId()); System.out.println( "当前正在执行的活动:" + pi.findActiveActivityNames()); } } |
输出结果为:
processInstanceId = test.330007
当前正在执行的活动:[汇款, 发货]
可以看出,汇款和发货同时执行中。并且,只有当2条路线都到join活动,流程才会继续往后执行。
b) 自定义活动(custom)
i. 在<custom>元素中指定class属性为指定的类ExternalActivityBehaviourImpl
ii. 这个类要实现ExternalActivityBehaviour接口,其中有两个方法:
1. execute(ActivityExecution):节点的功能代码
2. signal(ActivityExecution, String, Map):在当前节点等待时,外部发信号时的行为
3. 在execute()方法中,可以调用以下方法对流程进行控制
a) ActivityExecution.waitForSignal():在当前节点等待。
b) ActivityExecution.takeDefaultTransition():使用默认的Transition离开,当前节点中定义的第一个为默认的。
c) ActivityExecution.take(String transitionName):使用指定的Transition离开
d) ActivityExecution.end():结束流程实例
4. 也可以实现ActivityBehaviour接口,只有一个方法execute(ActivityExecution),这样就不能等待,否则signal时会有类转换异常。
1234567891011121314151617181920212223public
class
ExternalActivityBehaviourImpl
implements
ExternalActivityBehaviour {
// 到达这个活动时执行的方法
@Override
public
void
execute(ActivityExecution execution)
throws
Exception {
System.out.println(
"已发送信息."
);
//此处写自己要执行的事件
// 默认是执行完代码后离开当前活动,不会执行signal方法,也可以写如下代码
// execution.takeDefaultTransition(); // 离开当前活动
// // 使用指定名称的Transition离开当前活动
// execution.take(transitionName);
// 执行完后不要离开,而是要等待外部调用signal()方法时才离开
execution.waitForSignal();
}
// 调用signal()方法离开当前节点前执行的方法(如果在execute()中直接离开当前节点了,这个方法就不会被执行)
@Override
public
void
signal(ActivityExecution execution, String signalName, Map<String, ?> parameters)
throws
Exception {
System.out.println(
"ExternalActivityBehaviourImpl.signal()"
);
}
}
3.事件
a) 在根元素中,或在节点元素中,使用<on event="">元素指定事件,其中event属性代表事件的类型。
b) 在<on>中用子元素<event-listener class="EventListenerImpl" />,指定处理的类,要求指定的类要实现EventListener接口
c) 事件类型:
i. <on>元素放在根元素(<process>)中,可以指定event为start或end,表示流程的开始与结束。
ii. <on>元素放在节点元素中,可以指定event为start或end,表示节点的进入与离开
iii. 在Start节点中只有end事件,在End节点中只有start事件。
iv. 在<transition>元素中直接写<event-listener class="">,就是配置事件。(因为在这里只有一个事件,所以不用写on与类型)
v. 在<task>元素中还可以配置assign事件,是在分配任务时触发的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<?xml version= "1.0" encoding= "UTF-8" ?> <process name= "test" xmlns= "http://jbpm.org/4.4/jpdl" > <!-- 流程实例的启动事件 --> <on event= "start" > <event-listener class = "cn.grace.EventListenerImpl" ></event-listener> </on> <!-- 流程实例的结束事件 --> <on event= "end" > <event-listener class = "cn.grace.EventListenerImpl" ></event-listener> </on> <start name= "start1" g= "86,69,7,1" > <!-- 开始活动中只有离开活动的事件 --> <on event= "end" > <event-listener class = "cn.grace.EventListenerImpl" ></event-listener> </on> <transition name= "to task1" to= "task1" g= "-53,-17" /> </start> <task name= "task1" g= "61,171,92,52" assignee= "张三" > <!-- 进入活动的事件 --> <on event= "start" > <event-listener class = "cn.grace.EventListenerImpl" ></event-listener> </on> <!--离开活动的事件 --> <on event= "end" > <event-listener class = "cn.grace.EventListenerImpl" ></event-listener> </on> <transition name= "to end1" to= "end1" g= "-47,-17" /> </task> <end name= "end1" g= "86,272,48,48" > <!-- 结束活动中只有进入活动的事件 --> <on event= "start" > <event-listener class = "cn.grace.EventListenerImpl" ></event-listener> </on> </end> </process> |
根据上述.jpdl.xml和对应的.png图,启动流程实例会执行3次EventListenerImpl事件,结束流程实例也会执行3次EventListenerImpl事件。
JBPM工作流(七)——详解流程图的更多相关文章
- JBPM学习(六):详解流程图
概念: 流程图的组成: a. 活动 Activity / 节点 Node b. 流转 Transition / 连线(单向箭头) c. 事件 1.流转(Transition) a) 一般情况一个活动中 ...
- 工作流引擎详解!工作流开源框架ACtiviti的详细配置以及安装和使用
创建ProcessEngine Activiti流程引擎的配置文件是名为activiti.cfg.xml的XML文件.注意与使用Spring方式创建流程引擎是不一样的 使用org.activiti.e ...
- JBPM工作流(一)——实现一个简单的工作流例子
一.JBPM定义 JBPM,全称是Java Business Process Management(业务流程管理),它是覆盖了业务流程管理.工作流.服务协作等领域的一个开源的.灵活的.易扩展的可执行流 ...
- Activiti工作流学习之流程图应用详解
Activiti工作流学习之流程图应用详解 1.目的 了解Activiti工作流是怎样应用流程图的. 2.环境准备2.1.相关软件及版本 jdk版本:Jdk1.7及以上 IDE:eclipse ...
- 详解工作流框架Activiti的服务架构和组件
摘要:通过这篇文章,可以对工作流有一个基本的认识,为后续工作流框架Activiti的学习打下坚实的基础. 本文分享自华为云社区<BPMN工作流的基本概念!详解工作流框架Activiti的服务架构 ...
- 七牛云存储Python SDK使用教程 - 上传策略详解
文 七牛云存储Python SDK使用教程 - 上传策略详解 七牛云存储 python-sdk 七牛云存储教程 jemygraw 2015年01月04日发布 推荐 1 推荐 收藏 2 收藏,2.7k ...
- Iptables详解七层过滤
<Iptables详解七层过滤> 一.防火墙简介 防火墙其实就是一个加固主机或网络安全的一个设备或者软件而已,通过防火墙可以隔离风险区域与安全区域的连接,同时不会妨碍风险区域的访问.当然需 ...
- [Spark内核] 第40课:CacheManager彻底解密:CacheManager运行原理流程图和源码详解
本课主题 CacheManager 运行原理图 CacheManager 源码解析 CacheManager 运行原理图 [下图是CacheManager的运行原理图] 首先 RDD 是通过 iter ...
- .Net使用Redis详解之ServiceStack.Redis(七) 转载https://www.cnblogs.com/knowledgesea/p/5032101.html
.Net使用Redis详解之ServiceStack.Redis(七) 序言 本篇从.Net如何接入Reis开始,直至.Net对Redis的各种操作,为了方便学习与做为文档的查看,我做一遍注释展现 ...
随机推荐
- 转: ffmpeg循环推流方法
from: https://blog.csdn.net/weiyuefei/article/details/64125208 ffmpeg循环推流方法 You should be able to u ...
- mac的vscode配置使用zsh
配置文件 "terminal.integrated.shell.osx": "zsh"
- method.invoke(...)反射点
import java.lang.reflect.Method; import java.util.Arrays; /** * @Author: hoobey * @Description: * @D ...
- FutureTask类
FutureTask类是Future 的一个实现,并实现了Runnable. 所以可通过Executor(线程池)来运行,也可传递给Thread对象运行. 假设在主线程中须要运行比較耗时的操作时.但 ...
- golang 使用pprof和go-torch做性能分析
软件开发过程中,项目上线并不是终点.上线后,还要对程序的取样分析运行情况,并重构现有的功能,让程序执行更高效更稳写. golang的工具包内自带pprof功能,使找出程序中占内存和CPU较多的部分功能 ...
- 关于docker 意外停止,重新快速启动措施
1. 我们要重启这个镜像,需要知道这个镜像ID,类似这个: 7079ff99e10ac326726a364348853c0e508cad8ce00ae970f3c800f172a40252 那么你可以 ...
- MATLAB 按条件进行加和
用 find 命令仅仅是找到元素的序号. 这里使用sum 直接选取数组中的元素然后进行加和: a=[ ; ; ; ]; b=sum(a(a>=));
- php的Allowed memory size of 134217728 bytes exhausted问题解决办法
php的Allowed memory size of 134217728 bytes exhausted问题解决办法 报错: Fatal error: Allowed memory size of 1 ...
- 仅仅有五行的Floyd最短路算法
暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,例如以下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道随意两个城市之前的最短路程. 上图中有4个城市8条公路,公路上的数 ...
- python 中有趣的库tqdm
Tqdm 是 Python 进度条库,可以在 Python 长循环中添加一个进度提示信息用法:tqdm(iterator) # 方法1: import time from tqdm import tq ...