Activiti提供两种子流程实现:
1、嵌入子流程
子流程元素<subProcess>内嵌在主流程元素<process>之内,只能在该流程中使用该子流程,外部是无法访问到的。这种子流程一般作为局部通用逻辑处理,或者因为特定业务需要,使得比较复杂的单个主流程设计清晰直观;
2、调用子流程
首先实现一个流程,在另一个流程中可以调用该流程,通常可以定义一些通用的流程作为这种调用子流程,供其他多个流程定义复用。这种子流程使用<callActivity>元素来进行调用,间接地嵌入到主流程中,用起来比较方便。
下面通过实例来看下两者的实现:
一、嵌入子流程
1、流程图
以下是流程图的xml表示,可以看到主流程中有一段由标签<subprocess>包围的部分即时流程图中的
SubProcess的xml表示:
二、调用子流程
1、流程图
主流程:callProcess
主流程xml表示:
其中使用标签<callActiviti>的属性calledElement指明子流程定义,并实现主流程与子流程之间进行数据交换,<activiti:in/>由主流程传入子流程,<activiti:out/>由子流程传给主流程。
子流程:callledProcess
子流程xml表示,可以看到子流程就是一个正常的独立流程,流程id为calledProcess:
2、应用实例
首先,启动流程代码如下,在发起时给主流程加入全局变量,方便子流程获取,并且在最后记录审批日志,最终我们会看到整个业务流程的日志都是以唯一流程标识划分的:
/***
*启动流程并记录日志
*@param businessKey 流程唯一标识
*@param businessType 业务类型
*@param businessId 业务id
* */
public void start(Long businessKey, Integer businessType, Long businessId, Operator operator) {
//主流程变量
Map approveParam = new HashMap<>();
approveParam.put("businessKey", businessKey);
approveParam.put("businessType", businessType);
approveParam.put("businessId", businessId);
// 启动流程
runtimeService.startProcessInstanceByKey("callProcess", businessKey.toString(),
approveParam);
// 记录日志
approveRecordService.saveApproveRecord(businessKey, businessType, businessId, "-1",
FlowNode.Startevent.getCode(), operator.getOperatorId(), ApproveOperation.START.getCode(), "启动流程");
}执行流程代码如下:
/**
* 审核
* @param businessKey 流程唯一标识
* */
public void approve(Long businessKey){
//审核变量
Map approveParam = new HashMap<>();
approveParam.put("approve", "pass");
//获取当前任务
Task currentTask = taskService.createTaskQuery().processInstanceBusinessKey(businessKey.toString()).singleResult();
Map variables = currentTask.getProcessVariables();
// 级联结束本节点发起的会签任务
String parentTaskId = currentTask.getParentTaskId();
if (parentTaskId != null) {
List tasks = taskService.createTaskQuery().taskId(parentTaskId).taskDescription("JOINT_PROCESS").list();
for (Task task : tasks) {
taskService.setVariablesLocal(task.getId(), null);
taskService.complete(task.getId(), null);
}
}
//完成当前任务
taskService.setVariablesLocal(currentTask.getId(), approveParam);
taskService.complete(currentTask.getId(), approveParam);
// 记录日志
approveRecordService.saveApproveRecord(businessKey, (Integer)variables.get("businessType"),
(Long)variables.get("businessId"), "-1",
FlowNode.Startevent.getCode(), 888L,
ApproveOperation.START.getCode(), "启动流程");
}如主流程所示,我们发起流程后,执行beforecall,完成后将进入调用子流程Call Activiti模块中,这时子流程会自动跳过空开始结点,生成subTask用户任务的执行实例和任务,在ACT_RU_EXECUTION和ACT_RU_TASK表中各产生一条新的记录。
但是生成的执行实例缺少唯一业务标识businessKey,这个需要通过监听器实现。
如子流程xml中所示,我们给subTask和subTask2都配置了任务监听器
<activiti:taskListener event="create" delegateExpression="${subProcessTestListener}"></activiti:taskListener>
来,上监听器代码~~~~~~~~~
@Service
public class SubProcessTestListener implements TaskListener {
private static final long serialVersionUID = 1L;
@Autowired
private RuntimeService runtimeService;
@Transactional
public void notify(DelegateTask delegateTask){
System.err.println("1.子流程任务创建======delegateTask{}:" + delegateTask.getId());
//获取子流程变量
DelegateExecution execution = delegateTask.getExecution();
Long businessId = (Long)execution.getVariable("businessId");
Integer businessType = (Integer)execution.getVariable("businessType");
Long businessKey = (Long)execution.getVariable("businessKey");
System.err.println(
"2.获取子流程参数======businessId:" + businessId + ";businessType:" + businessType
+ ";businessKey:" + businessKey);
//子流程实例set业务单号和主流程保持一致
runtimeService.updateBusinessKey(delegateTask.getProcessInstanceId(), businessKey.toString());
}
}
这里可以看到主流程xml中,主流程的变量子流程都可以接到,我们利用这些变量中businessKey业务标识,在监听器中填充子流程subTask实例的BUSINESS_KEY_字段,使得子流程和主流程保持业务标识一致,我们流程就可以继续跑下去了。
<callActivity id="callactivity1" name="Call activity" calledElement="calledProcess">
<extensionElements>
<activiti:in source="businessId" target="businessId"></activiti:in>
<activiti:in source="businessType" target="businessType"></activiti:in>
<activiti:in source="businessKey" target="businessKey"></activiti:in>
</extensionElements>
</callActivity>
<extensionElements>
<activiti:in source="businessId" target="businessId"></activiti:in>
<activiti:in source="businessType" target="businessType"></activiti:in>
<activiti:in source="businessKey" target="businessKey"></activiti:in>
</extensionElements>
</callActivity>
配置监听器后,调用子流程时,生成实例set了业务标识
调用子流程执行结束,同时,子流程实例完成,工作流将重新回到主流程:
正常执行主流程,直到结束,整个业务流程如下:
Activiti子流程实现与实例解析
本文介绍了Activiti中如何调用子流程,包括主流程callProcess的定义以及子流程calledProcess的详细描述,子流程作为一个独立单元在流程图中发挥作用。
4504

被折叠的 条评论
为什么被折叠?



