有時候業務需求,我們得定時或者是多久以後處理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--------------------------");
}
}