Flowable开发--流程审批(五)

一、流程审批后涉及到的表

表名 描述
act_fo_form_instance 存储用户填充后表单实例信息,FORM_DEFINITION_ID_字段 2bb4ecac-cfb8-11e9-9f13-1a1dea14efe7
act_fo_form_resource NAME_字段 form-2bb4ecac-cfb8-11e9-9f13-1a1dea14efe7
act_hi_actinst 历史的流程实例 插入多条数据
act_hi_identitylink 历史的流程运行过程中用户关系 插入多条数据
act_hi_procinst 历史的流程实例 REV_ 1未完成 2已完成
act_hi_taskinst 历史的任务实例 REV_ 1待认领 2等审批 3已审批
act_hi_varinst 历史的流程运行中的变量信息
act_ru_actinst 存储运行时节点信息 与act_hi_actinst同时存储
act_ru_execution 执行实例表和act_run_task表,一起控制了用户任务的产生与完成等,当在并行网关和会签多实例时,它是会产生多个执行实例,IS_ACTIVE_这个字段的值都是为1,即激活状态,当每完成一个执行实例时,它会把IS_ACTIVE设为0,非激活状态,当所有执行实例完成后,它才会转移到历史,把这个多实例自动删除
act_ru_identitylink 运行时用户关系
act_ru_task 运行时任务表
act_ru_variable 运行的流程中的变量信息

当流程全部走完后,act_ru_表的数据清空了,全部移到了act_hi_

二、流程示例

  1. 创建流程图
    创建OrderApproval.bpmn20.xml文件


    创建文件

    创建文件

    改更扩展名

    流程图设计


    
    
        
        
        
        
        
        
            
                
            
        
        
        
        
        
            
        
        
        
        
        
        
        
        
        
        
        
        
            
        
    
    
        
            
                
            
            
                
            
            
                
            
            
                
            
            
                
            
            
                
            
            
                
            
            
                
                
                
                
            
            
                
                
                
                
            
            
                
                
                
                
            
            
                
                
            
            
                
                
                
                
            
            
                
                
                
                
            
        
    

流程图
  1. 创建委托
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

/**
 * 批准委托类
 */
@Slf4j
public class ReviewApprove implements JavaDelegate {

    @Override
    public void execute(DelegateExecution delegateExecution) {
        //可以发送消息给某人
        log.info("通过,userId是:{}",delegateExecution.getVariable("userId"));
    }
}

import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

/**
 * 驳回委托类
 */
@Slf4j
public class ReviewNoApprove implements JavaDelegate {
    @Override
    public void execute(DelegateExecution delegateExecution) {
        //可以发送消息给某人
        log.info("拒绝,userId是:{}",delegateExecution.getVariable("userId"));
    }
}


  1. 创建控制器
@RestController
@RequestMapping("/orderFlow")
@Slf4j
public class OrderFlowController {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Resource
    private ProcessEngine processEngine;

    /**
     * 1.提交采购订单的审批请求
     *
     * @param userId 用户id
     */
    @PostMapping("/start/{userId}/{purchaseOrderId}")
    public Result startFlow(@PathVariable String userId, @PathVariable String purchaseOrderId) {
        HashMap map = new HashMap<>();
        map.put("userId", userId);
        map.put("purchaseOrderId", purchaseOrderId);
        // 流程ID->OrderApproval
        ProcessInstance processInstance =
                runtimeService.startProcessInstanceByKey("OrderApproval", map);
        String processId = processInstance.getId();
        // 名称由布署时指定
        String name = processInstance.getName();
        log.info(processId + ":" + name);
        return Result.ok(processId + ":" + name);
    }

    /**
     * 2.获取用户的任务
     *
     * @param userId 用户id
     */
    @GetMapping("/getTasks/{userId}")
    public Result getTasks(@PathVariable String userId) {
        List tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();
        return Result.ok(tasks.toString());
    }

    /**
     * 3.审批通过
     */
    @PostMapping("/success/{taskId}")
    public Result success(@PathVariable String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return Result.error("流程不存在");
        }
        //通过审核
        HashMap map = new HashMap<>();
        // 在流程图中获取进行处理
        map.put("approved", true);
        taskService.complete(taskId, map);
        return Result.ok("流程审核通过!");
    }

    /**
     * 4.审批不通过
     */
    @PostMapping("/fail/{taskId}")
    public Result fail(@PathVariable String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return Result.error("流程不存在");
        }
        //通过审核
        HashMap map = new HashMap<>();
        // 在流程图中获取进行处理
        map.put("approved", false);
        taskService.complete(taskId, map);
        return Result.ok();
    }

    /**
     * 5. 生成流程图
     *
     * @param httpServletResponse
     * @param processId
     * @throws Exception
     */
    @PostMapping(value = "processDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) {
        /**
         * 获得当前活动的节点
         */
        String processDefinitionId = "";
        boolean isFinish = historyService.createHistoricProcessInstanceQuery().finished()
                .processInstanceId(processId).count() > 0;
        if (isFinish) {// 如果流程已经结束,则得到结束节点
            HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        } else {// 如果流程没有结束,则取当前活动节点
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        }
        List highLightedActivitis = new ArrayList();

        /**
         * 获得活动的节点
         */
        List highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();

        for (HistoricActivityInstance tempActivity : highLightedActivitList) {
            String activityId = tempActivity.getActivityId();
            highLightedActivitis.add(activityId);
        }

        List flows = new ArrayList<>();
        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();

        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        // 注意:如果是PNG格式那么输出的是背景色是黑色,如果连接线上有字不容易看清楚。可以使用bmp
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivitis, flows, engconf.getActivityFontName(),
                engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, true);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } catch (IOException e) {
            log.error("操作异常", e);
        } finally {
            IOUtils.closeQuietly(out);
            IOUtils.closeQuietly(in);
        }
    }
}

三、运行测试

  1. 提交采购订单的审批请求
    http://localhost:7001/orderFlow/start/1/1
    提交采购订单的审批请求

    返回:
{
    "msg": "3c6dc4b2-f30a-11e9-bc68-005056c00008:null",
    "code": 0
}
  1. 获取用户的任务
    http://localhost:7001/orderFlow/getTasks/1
    获取用户的任务

    返回:
{
    "msg": "[Task[id=3c6dc4b2-f30a-11e9-bc68-005056c00008, name=订单审批]]",
    "code": 0
}
  1. 审批通过
    http://localhost:7001/orderFlow/success/3c6dc4b2-f30a-11e9-bc68-005056c00008
    审批通过

    返回:
{
    "msg": "流程审核通过!",
    "code": 0
}
  1. 审批驳回
    http://localhost:7001/orderFlow/fail/fac2256e-f30e-11e9-a987-005056c00008
    任务ID: fac2256e-f30e-11e9-a987-005056c00008
    审批驳回

    返回:
{
    "msg": "success",
    "code": 0
}
  1. 生成流程图
    http://localhost:7001/orderFlow/processDiagram?processId=4fdcbade-f311-11e9-acac-005056c00008
    processId: 为流程实例ID
    生成流程图

四、事件监听器实现

事件监听器的唯一要求是实现org.flowable.engine.delegate.event.FlowableEventListener。
一个事件侦听器基类,可用于侦听特定类型的实体或所有实体的实体相关事件。它隐藏掉类型检查,并提供4种方法应覆盖:onCreate(..),onUpdate(..)并onDelete(..)创建实体时,更新或删除。

五、常见问题

  1. "code":401,"error":"Unauthorized."
    排除配置
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
  1. 流程文档部署时没生成流程图片
    如果流程文档部署时没生成流程图片,且流程定义中包含必要的“图形交换(diagram interchange)”信息,Flowable引擎会生成流程图。
    如果由于某种原因,不需要或不希望在部署时生成流程图,可以在流程引擎配置中设置isCreateDiagramOnDeploy参数:

  1. Waiting for changelog lock....
    数据库中执行:
SELECT `LOCKED` FROM workflow_flowable.ACT_DMN_DATABASECHANGELOGLOCK WHERE ID=1

UPDATE workflow_flowable.ACT_DMN_DATABASECHANGELOGLOCK 
SET locked=0 WHERE ID=1
  1. 没有生成流程图
    bpmn 任务中没有加入:
  
      
 

你可能感兴趣的:(Flowable开发--流程审批(五))