背景

  • 测试案例:
  • 1. 更新配置文件
  • 2. 设置流程图
  • 3. 测试用例
  • 4. 结果
  • 5. BPMN文件内容


背景:
项目中用到工作流,其中有一个需求是,市民通过公众号上报事件,然后流程往下走,最后会回到上报人手中,但是由于是公众号,上报人可能上报之后就不关心之后怎么样了;如果市民最后没有确认流程,那么流程就不会结束;到最后会影响报表的数据;

现在这个需求需要改成:当案件回到上报人之后,如果上报人在三天之内没有处理这个案件,系统就把这个案件自动结束;

测试案例:

a)    张三提交请假单
b)    经理审批请假单。流程回到张三手中
c)    张三审批流程;如果超时则自动审批

1. 更新配置文件

如果是SSM项目,配置文件中添加

<property name="jobExecutorActivate" value="true" />
<!-- Activiti begin -->
	<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
		<property name="dataSource" ref="dataSource" />
		<property name="transactionManager" ref="transactionManager" />
		<property name="deploymentResources" value="classpath*:/act/deployments/**/*.bar"/>
		<property name="databaseSchemaUpdate" value="false" />
		<!-- 在这在这在这在这在这在这在这在这在这在这-->
		<property name="jobExecutorActivate" value="true" />
		<property name="history" value="full" />
		<property name="processDefinitionCacheLimit" value="10"/>      
	</bean>

如果是SpringBoot项目 ,在配置文件中添加此配置

spring:
  activiti:
    job-executor-activate: true

2. 设置流程图

activiti审批流 springboot 项目例子_SpringBoot


PT1M:一分钟之后,如果未处理,则自动审批;

S表示秒,M表示分,D表示天;P表示时间段,T表示精确到时间的时间段;

timeDuration。指定定时器之前要等待多长时间。 使用ISO 8601规定的格式 (由BPMN 2.0规定)。
P1D:代表1天后执行此时间定时器。
P1H:代表1小时后执行此时间定时器。
P1M:代表1分钟后执行此时间定时器。
PT1M:代表1分钟后执行此时间定时器。

3. 测试用例

/**
     * 超时自动结束测试
     */
    @Test
    public void timeOutAutoEndTest() throws InterruptedException {

        String procDefKey = "user_leave_now"; // 流程定义ID
        // 设置参数
        Map<String, Object> vars = new HashMap<>();
        vars.put("applyUserId","zhangsan");
        vars.put("manager","manager");
        vars.put("title", "超时未审批请假流程测试");
        //用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中
        identityService.setAuthenticatedUserId(String.valueOf(6));
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(procDefKey, "business_leavebu_leave:8", vars);
        String id1 = processInstance.getId(); // 流程启动实例ID
        System.out.println("流程启动后的实例ID 是 " + id1);


        // 查询待签收任务
        // 指定任务办理者
        String assignee = "manager";
        List<Task> list1 = taskService.createTaskQuery().taskCandidateUser(assignee).includeProcessVariables().active().orderByTaskCreateTime().desc().list();
        System.out.println("*******************待签收任务************************");
        for (Task task : list1) {
            System.out.println("任务ID 是 " + task.getId());
            System.out.println("任务name 是 " + task.getName());
            System.out.println("任务Assignee 是 " + task.getAssignee());
            System.out.println("任务ProcessInstanceId 是 " + task.getProcessInstanceId());
        }
        System.out.println("*******************待签收任务************************");


        // 签收任务
        Task task = list1.get(0);
        String taskId = task.getId();
        taskService.claim(taskId, assignee);
        System.out.println("*******************待签收任务已经签收************************");


        String procInsId =task.getProcessInstanceId() ;
        String comment = "生六胎";
        // 设置审批消息
        taskService.addComment(taskId,procInsId,comment);
        Map<String,Object> vars1 = new HashMap<>();
        vars1.put("title","经理已经审批");
        // 提交任务
        taskService.complete(taskId, vars);
        System.out.println("*******************待签收任务经理已经审批************************");

        System.out.println("当前处理任务名称:" + task.getName());

        System.out.println("睡眠70秒===================");
        Thread.sleep(70*1000);


        // 查询待签收任务
        // 指定任务办理者
        String zhangsan = "zhangsan";
        List<Task> listZhangsan = taskService.createTaskQuery().taskCandidateUser(zhangsan).includeProcessVariables().active().orderByTaskCreateTime().desc().list();
        System.out.println("*******************张三的待签收任务************************");
        System.out.println("*******************待签收任务************************");
        for (Task taskZ : listZhangsan) {
            System.out.println("任务ID 是 " + taskZ.getId());
            System.out.println("任务name 是 " + taskZ.getName());
            System.out.println("任务Assignee 是 " + taskZ.getAssignee());
            System.out.println("任务ProcessInstanceId 是 " + taskZ.getProcessInstanceId());
        }
        System.out.println("*******************待签收任务************************");




        ProcessInstance processInstanceStatus = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(procInsId).singleResult();
        if(processInstanceStatus != null){
            System.out.println("流程未结束************************");
            System.out.println("流程进行Name:"+ processInstanceStatus.getName());
            System.out.println("流程进行getActivityId:"+ processInstanceStatus.getActivityId());
        }else{
            System.out.println("流程已经结束************************");
        }


    }

在测试用例睡眠70秒的运行中,在数据库会产生数据分别如下;但是超时之后,数据会被删除;

activiti审批流 springboot 项目例子_工作流_02


activiti审批流 springboot 项目例子_java_03

4. 结果

测试用例执行之后,再去查表数据,会发现流程已经结束;

activiti审批流 springboot 项目例子_工作流_04

5. BPMN文件内容

<?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/processdef">
  <process id="user_leave_now" name="请假流程" isExecutable="true">
    <startEvent id="userApply" name="提交请假单" activiti:initiator="${applyUserId}">
      <documentation>用户提交请假单--</documentation>
    </startEvent>
    <userTask id="manager_made" name="经理审批" activiti:candidateUsers="${manager}"></userTask>
    <endEvent id="sid_pass" name="通过"></endEvent>
    <sequenceFlow id="sid_apply" name="提交" sourceRef="userApply" targetRef="manager_made"></sequenceFlow>
    <userTask id="backApplyUser" name="回到申请人" activiti:candidateUsers="${applyUserId}"></userTask>
    <sequenceFlow id="sid-83B6E838-BC2E-4C43-9D00-C940E58F385B" sourceRef="manager_made" targetRef="backApplyUser"></sequenceFlow>
    <sequenceFlow id="sid-92A895CA-AB71-4589-B66A-63C4B7FEED6A" sourceRef="backApplyUser" targetRef="sid_pass"></sequenceFlow>
    <boundaryEvent id="timeOutAutoAudit" name="超时自动审批" attachedToRef="backApplyUser" cancelActivity="true">
      <timerEventDefinition>
        <timeDuration>PT1M</timeDuration>
      </timerEventDefinition>
    </boundaryEvent>
    <sequenceFlow id="sid-A7CA3B3D-2D6A-4AF7-8592-82F4E08E2B93" sourceRef="timeOutAutoAudit" targetRef="sid_pass"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_user_leave_now">
    <bpmndi:BPMNPlane bpmnElement="user_leave_now" id="BPMNPlane_user_leave_now">
      <bpmndi:BPMNShape bpmnElement="userApply" id="BPMNShape_userApply">
        <omgdc:Bounds height="30.0" width="30.0" x="105.0" y="115.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="manager_made" id="BPMNShape_manager_made">
        <omgdc:Bounds height="80.0" width="100.0" x="330.0" y="90.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid_pass" id="BPMNShape_sid_pass">
        <omgdc:Bounds height="28.0" width="28.0" x="842.0" y="116.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="backApplyUser" id="BPMNShape_backApplyUser">
        <omgdc:Bounds height="80.0" width="100.0" x="613.0" y="92.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="timeOutAutoAudit" id="BPMNShape_timeOutAutoAudit">
        <omgdc:Bounds height="31.0" width="31.0" x="692.3704448753612" y="76.00715950272286"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-92A895CA-AB71-4589-B66A-63C4B7FEED6A" id="BPMNEdge_sid-92A895CA-AB71-4589-B66A-63C4B7FEED6A">
        <omgdi:waypoint x="713.0" y="131.4818652849741"></omgdi:waypoint>
        <omgdi:waypoint x="842.0007516374965" y="130.14506993121765"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-A7CA3B3D-2D6A-4AF7-8592-82F4E08E2B93" id="BPMNEdge_sid-A7CA3B3D-2D6A-4AF7-8592-82F4E08E2B93">
        <omgdi:waypoint x="723.8655478549781" y="95.99486356033142"></omgdi:waypoint>
        <omgdi:waypoint x="842.4417848928352" y="126.51075894959251"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid_apply" id="BPMNEdge_sid_apply">
        <omgdi:waypoint x="135.0" y="130.0"></omgdi:waypoint>
        <omgdi:waypoint x="330.0" y="130.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-83B6E838-BC2E-4C43-9D00-C940E58F385B" id="BPMNEdge_sid-83B6E838-BC2E-4C43-9D00-C940E58F385B">
        <omgdi:waypoint x="430.0" y="130.35335689045937"></omgdi:waypoint>
        <omgdi:waypoint x="613.0" y="131.64664310954063"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>