背景
小西城啊,现在有个需求,需要流程执行到某个节点的时候,根据表单的参数进行定时任务的时间设置,举个例子,到了运营主管节点,需要根据运营主管设置的表单时间字段来决定下一节点的定时任务什么时间跑,你看下怎么实现吧。
实现
顾名思义,在流程的定时任务节点,增加一个属性值,来决定取值是什么类型。目前设置三个常见的,一个是隔日的时间点,一个是自定义时间,一个是取表单字段时间。
前端设置
主要是设置定时任务节点的自定义属性
![](https://img.haomeiwen.com/i15425090/6c72d7b5ca2cc459.png)
设置完之后提交上来的xml类似于
<boundaryEvent id="Event_06ubr62" name="定时切换" attachedToRef="Activity_0b7guuz" activiti:timeType="form" activiti:time="actual_change_time">
<outgoing>Flow_06r0pkm</outgoing>
<timerEventDefinition id="TimerEventDefinition_06tqipv" />
</boundaryEvent>
这个节点一般放在UserTask底下
后端解析
-
自定义xml解析类
public class CustomBoundaryEventXMLConverter extends BoundaryEventXMLConverter { @Override protected BaseElement convertXMLToElement(XMLStreamReader xtr, BpmnModel model) throws Exception { BoundaryEvent boundaryEvent = new BoundaryEvent(); BpmnXMLUtil.addXMLLocation(boundaryEvent, xtr); if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_BOUNDARY_CANCELACTIVITY))) { String cancelActivity = xtr.getAttributeValue(null, ATTRIBUTE_BOUNDARY_CANCELACTIVITY); if (ATTRIBUTE_VALUE_FALSE.equalsIgnoreCase(cancelActivity)) { boundaryEvent.setCancelActivity(false); } } CustomTimerEventDefinitionProps.BOUNDARY_EVENT[] boundaryEvents = CustomTimerEventDefinitionProps.BOUNDARY_EVENT.values(); for ( CustomTimerEventDefinitionProps.BOUNDARY_EVENT event : boundaryEvents ) { String attributeValue = xtr.getAttributeValue(null, event.getAttrName()); if ( StringUtils.isNotEmpty(attributeValue) ){ ExtensionAttribute extensionAttribute = new ExtensionAttribute(); extensionAttribute.setName(event.getAttrName()); extensionAttribute.setValue(attributeValue); boundaryEvent.addAttribute(extensionAttribute); } } boundaryEvent.setAttachedToRefId(xtr.getAttributeValue(null, ATTRIBUTE_BOUNDARY_ATTACHEDTOREF)); parseChildElements(getXMLElementName(), boundaryEvent, model, xtr); // Explicitly set cancel activity to false for error boundary events if (boundaryEvent.getEventDefinitions().size() == 1) { EventDefinition eventDef = boundaryEvent.getEventDefinitions().get(0); if (eventDef instanceof ErrorEventDefinition) { boundaryEvent.setCancelActivity(false); }else if (eventDef instanceof TimerEventDefinition){ String timeType = boundaryEvent.getAttributeValue(null, CustomTimerEventDefinitionProps.BOUNDARY_EVENT.TIME_TYPE.getAttrName()); if ( StringUtils.isNotEmpty(timeType) ){ // 这里设置TimerEventDefinition的变量值,我们在流程执行到这个定时任务之前,设置对应的属性值就行 if ( CustomTimerEventDefinitionProps.TIME_TYPE.diy.name().equals(timeType) ){ String time = boundaryEvent.getAttributeValue(null, CustomTimerEventDefinitionProps.BOUNDARY_EVENT.TIME.getAttrName()); ((TimerEventDefinition) eventDef).setTimeDate(time); }else if(CustomTimerEventDefinitionProps.TIME_TYPE.tomorrow.name().equals(timeType)){ ((TimerEventDefinition) eventDef).setTimeDate("${tomorrow}"); }else if(CustomTimerEventDefinitionProps.TIME_TYPE.form.name().equals(timeType)){ String time = boundaryEvent.getAttributeValue(null, CustomTimerEventDefinitionProps.BOUNDARY_EVENT.TIME.getAttrName()); ((TimerEventDefinition) eventDef).setTimeDate("${" + time + "}"); } } } } return boundaryEvent; } @Override protected void writeAdditionalAttributes(BaseElement element, BpmnModel model, XMLStreamWriter xtw) throws Exception { super.writeAdditionalAttributes(element, model, xtw); BoundaryEvent boundaryEvent = (BoundaryEvent) element; CustomTimerEventDefinitionProps.BOUNDARY_EVENT[] boundaryEvents = CustomTimerEventDefinitionProps.BOUNDARY_EVENT.values(); for ( CustomTimerEventDefinitionProps.BOUNDARY_EVENT event : boundaryEvents ) { String attributeValue = boundaryEvent.getAttributeValue(null, event.getAttrName()); if ( StringUtils.isNotEmpty(attributeValue) ){ writeDefaultAttribute("activiti:" + event.getAttrName(),attributeValue,xtw); } } } }
-
增加usertask的监听
if ("UserTask".equals(e.getClass().getSimpleName())){ //设置用户节点自动跳过参数 UserTask userTask = (UserTask)e; //设置监听器 if ( !ActivitiConstants.SUBMIT_TASK.equals(e.getId())){ if (StringUtils.isEmpty(userTask.getSkipExpression())){ userTask.setSkipExpression("${execution.getVariable('approvalPass') == true}"); } // 这里有个监听器去处理TimerEvent对应节点 userTask.getTaskListeners().addAll(CustomActivitiListeners.getUserTaskListeners()); }else{ userTask.getTaskListeners().addAll(CustomActivitiListeners.getUserTaskListeners()); } }
-
监听器设置数据
public class NextTaskTimerEventListener implements TaskListener { private Logger logger = LoggerFactory.getLogger(NextTaskTimerEventListener.class); @Override public void notify(DelegateTask delegateTask) { TaskService taskService = SpringContextUtils.getBean(TaskService.class); FlowElement currentFlowElement = delegateTask.getExecution().getCurrentFlowElement(); FlowNode flowNode = (FlowNode)currentFlowElement; List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows(); // 出口类型只有一个并且是userTask的才判断 if ( outgoingFlows != null && outgoingFlows.size() == 1 ){ SequenceFlow sequenceFlow = outgoingFlows.get(0); FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement(); if ( targetFlowElement instanceof UserTask ){ List<BoundaryEvent> boundaryEvents = ((UserTask) targetFlowElement).getBoundaryEvents(); for ( BoundaryEvent boundaryEvent : boundaryEvents ) { String timeType = boundaryEvent.getAttributeValue(null,CustomTimerEventDefinitionProps.BOUNDARY_EVENT.TIME_TYPE.getAttrName()); String time = boundaryEvent.getAttributeValue(null,CustomTimerEventDefinitionProps.BOUNDARY_EVENT.TIME.getAttrName()); // 这里根据设置的类型去设置值 if ( CustomTimerEventDefinitionProps.TIME_TYPE.tomorrow.name().equals(timeType) ){ logger.info("{}定时任务执行时间:{}",delegateTask.getId(),(LocalDate.now().plusDays(1).toString() + "T" + time)); delegateTask.setVariable(CustomTimerEventDefinitionProps.TIME_TYPE.tomorrow.name(),(LocalDate.now().plusDays(1).toString() + "T" + time)); taskService.setVariable(delegateTask.getId(),CustomTimerEventDefinitionProps.TIME_TYPE.tomorrow.name(),(LocalDate.now().plusDays(1).toString() + "T" + time)); }else{ // ... } } } } } }
网友评论