有时候业务需求,我们得定时或者是多久以后处理task,最近项目就有个这种场景,当流程到某个节点以后,过多久未处理自动流转到下一个节点、activiti自身
是支持这种业务场景的。
这里给个简单的示例
流程图:
xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="testTimer" name="Test timer" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name="节点1" activiti:assignee="1"></userTask>
<userTask id="usertask2" name="节点2" activiti:assignee="${userId}"></userTask>
<boundaryEvent id="boundarytimer1" name="Timer" attachedToRef="usertask1" cancelActivity="true">
<timerEventDefinition>
<timeDuration>${duTime}</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<sequenceFlow id="flow1" name="超时" sourceRef="boundarytimer1" targetRef="usertask2">
<extensionElements>
<activiti:executionListener event="take" class="FlowTakeListener"></activiti:executionListener>
</extensionElements>
</sequenceFlow>
<sequenceFlow id="flow2" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow3" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
<sequenceFlow id="flow4" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_testTimer">
<bpmndi:BPMNPlane bpmnElement="testTimer" id="BPMNPlane_testTimer">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="240.0" y="210.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="340.0" y="200.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="boundarytimer1" id="BPMNShape_boundarytimer1">
<omgdc:Bounds height="30.0" width="30.0" x="390.0" y="240.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="352.0" y="380.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="560.0" y="210.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="405.0" y="270.0"></omgdi:waypoint>
<omgdi:waypoint x="404.0" y="380.0"></omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="14.0" width="24.0" x="415.0" y="270.0"></omgdc:Bounds>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="275.0" y="227.0"></omgdi:waypoint>
<omgdi:waypoint x="340.0" y="227.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="445.0" y="227.0"></omgdi:waypoint>
<omgdi:waypoint x="560.0" y="227.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="404.0" y="380.0"></omgdi:waypoint>
<omgdi:waypoint x="577.0" y="245.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
其中关键位置
<boundaryEvent id="boundarytimer1" name="Timer" attachedToRef="usertask1" cancelActivity="true">
<timerEventDefinition>
<timeDuration>${duTime}</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<sequenceFlow id="flow1" name="超时" sourceRef="boundarytimer1" targetRef="usertask2">
<extensionElements>
<activiti:executionListener event="take" class="FlowTakeListener"></activiti:executionListener>
</extensionElements>
</sequenceFlow>
boundaryEvent :定时事件 连线 flow1
timeDuration 延迟时间 即过多久触发
连线作用: 事件类型 take 即经过的时候触发对应监听
监听类的配置有多种方式 :直接指定class,代理表达式等等
而一般我们习惯在监听类中处理相关业务逻辑 比如指定下一步审批人之类的业务,通常需要用到spring管理下的bean,这样最好将监听类交由spring管理,所以这里
选择代理表达式的方式,如图:
EL表达式中的值,对应bean id
FlowTakeListener代码类似于:
@Component
public class FlowTakeListener implements ExecutionListener {
/** @Fields serialVersionUID: */
private static final Logger log = LoggerFactory.getLogger(FlowTakeListener.class);
private static final long serialVersionUID = 1L;
@Resource
private TaskService taskService;
@Resource
private HistoryService historyService;
@Resource(name="applyFormInfoService")
private ApplyFormInfoService applyFormInfoService;
@Override
public void notify(DelegateExecution delegateExecution) throws Exception {
// TODO Auto-generated method stub
List<MyActivitiTask> myTasks = Lists.newArrayList();
log.debug("-------------------------------------over time start--------------------------");
//获取超时业务ID
//获取超时的流程实例ID
//String processInstanceId = delegateExecution.getProcessInstanceId();
//获取流程历史数据
//HistoricProcessInstance hisProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//获取业务主键ID
String businessKey = delegateExecution.getProcessBusinessKey();
log.debug("--------------------业务ID------------" + businessKey);
//获取需要执行的任务
List<Task> tasks = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).list();
for(Task task:tasks){
MyActivitiTask myTask = new MyActivitiTask();
myTask.setBussinessId(Long.parseLong(businessKey));
myTask.setCreateDate(task.getCreateTime());
myTask.setUserId(Integer.parseInt(task.getAssignee()));
myTasks.add(myTask);
}
this.applyFormInfoService.insertApproveOvertimeRecord(myTasks);
Integer approverId = this.applyFormInfoService.selectGradeAdvisorByBusId(Integer.parseInt(businessKey));
//设置审批人
log.debug("--------------年级主任--------" + approverId);
delegateExecution.setVariable("userId", approverId);
log.debug("-------------------------------------over time end--------------------------");
}
}