美文网首页
activiti定时任务节点取流程表单时间执行

activiti定时任务节点取流程表单时间执行

作者: 西城丶 | 来源:发表于2021-06-04 11:18 被阅读0次

背景

小西城啊,现在有个需求,需要流程执行到某个节点的时候,根据表单的参数进行定时任务的时间设置,举个例子,到了运营主管节点,需要根据运营主管设置的表单时间字段来决定下一节点的定时任务什么时间跑,你看下怎么实现吧。

实现

顾名思义,在流程的定时任务节点,增加一个属性值,来决定取值是什么类型。目前设置三个常见的,一个是隔日的时间点,一个是自定义时间,一个是取表单字段时间。

前端设置

主要是设置定时任务节点的自定义属性


前端编辑流程设置属性

设置完之后提交上来的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底下

后端解析

  1. 自定义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);
             }
          }
       }
    }
    
  2. 增加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());
       }
    }
    
  3. 监听器设置数据

    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{
                       // ...
                   }
                }
             }
          }
       }
    
    }
    

相关文章

  • activiti定时任务节点取流程表单时间执行

    背景 小西城啊,现在有个需求,需要流程执行到某个节点的时候,根据表单的参数进行定时任务的时间设置,举个例子,到了运...

  • 流程实例,任务,执行对象控制流程的执行

    流程实例,任务,执行对象控制流程的执行 介绍activiti中流程实例、任务、执行对象之间的区别联系,并且介绍这三...

  • 工作流activiti

    BPMN流程建模开始节点/结束节点/人物/流向 以下都可以使用activiti来进行 部署activiti流程定义...

  • 工作流引擎之Activiti中的表单及应用详解

    Activiti中的表单 Activiti提供了一种方便而且灵活的方式在业务流程中以手工方式添加表单 对表单的支持...

  • Activiti 流程实例、任务的执行

    09【掌握】流程实例、任务的执行 1.流程图 2.部署流程定义 3.启动流程 4.查询个人任务 5.办理任务 6....

  • crontab定时执行任务

    crontab命令可以设置定时执行任务,比如定时执行备份,定时爬取数据等 我们需要每个小时执行一次爬虫,cront...

  • Android中 Handler延时 定时任务

    1.延时 2.定时任务,间隔固定时间执行某项任务 3.定时任务,间隔固定时间执行某项操作后关闭定时任务 参考:ht...

  • flowable实现节点超时自动跳过

    不论是flowable还是activiti,都可以快速的实现节点超时自动跳过,主要是使用边缘事件 启动定时任务在初...

  • XXL-JOB任务调度使用

    背景 系统项目采用多节点部署,由于代码中有定时任务,多节点会导致任务重复执行,会生成大量冗余数据,因此需要把定时任...

  • 7.C# 三种Timer

    简介:定时器一般用作「固定时间间隔」执行某个「任务」。 两种情况: 「固定时间间隔」执行某个「不耗时」任务 例...

网友评论

      本文标题:activiti定时任务节点取流程表单时间执行

      本文链接:https://www.haomeiwen.com/subject/dzjxeltx.html