flowable的实现完整流程

画工作流

idea集成插件Flowable BPMN visualizer,这个插件可以画工作流,先在目录创建一个xxx.bpmn20.xml的文档,此文档可以放在resource下面,后期肯定和前端联调,前端可以集成bpmn.js进行勾画工作流。

画的工作流是BPMN2.0结构,里面包含了多种类型,分别为:事件,顺序流,网关,任务,子流程与调用活动,事务与并发,流程启动认证,数据对象。

如果不是空事件启动的话,在拒绝的情况下重新指回发起流程节点,带有参数的启动则不会重新填写参数,会直接到下一次审核。在这里插入图片描述
如果空事件启动,下一个用户任务启动的情况下,可以把拒绝的箭头指回到填写审核信息发起重新走流程。
在这里插入图片描述

工作流整体流程,审批流程

部署流程-》启动流程-》发起申请-》审批-》存档-》结束

联调流程

1.部署流程

2.获取当前登陆人启动流程发起申请,此处可以有两种,1.无参数启动流程事件,下一个在用户任务在提交申请参数。2.带参数启动流程,在启动的时候直接包含数据列表,下一步到审批流程。

3.查看当前人未结束的流程,此处对应的为无参数启动,目的为了找到当前任务id和流程实例的processInstanceId

4.不带参数的发起流程,下一步需要写申请,带上参数的请求,进行执行任务

5.审批(执行任务),审批有两种方式,1.查询当前的流程,获取下边的任务进行审批。2.查询当前人的审批列表,展示任务列表,对任务单独审批

6.查看需要审批的内容

7.查看流程图,可以看执行的过程图,展示的为image图片
具体代码如下:

1.部署流程

部署流程有5中实现方式,分别为

1.使用文件流部署工作流

@GetMapping("/deployInputStream")
public void deploy(@RequestParam("file") MultipartFile multipartFile, @RequestParam("name") String name) {
    try {
        Deployment deployment = repositoryService.createDeployment()
                .addInputStream(multipartFile.getOriginalFilename(), multipartFile.getInputStream())
                .name(name)
                .deploy();
        // 输出部署的一些信息
        System.out.println("流程部署ID:"+ deployment.getId());
        System.out.println("流程部署名称:"+ deployment.getName());
        System.out.println("流程部署成功");
    } catch (IOException e) {
        System.out.println("流程部署失败,文件验证失败,流程图有错误:"+ e.getMessage());
        throw new RuntimeException(e);
    }
}

2.使用classPath进行部署工作流

@GetMapping("/deployClasspath")
public void deployClasspath(@RequestParam("name") String name) {
    Deployment deployment = repositoryService.createDeployment()
            .addClasspathResource("processes/leave.bpmn20.xml")
            .name(name)
            .deploy();
    // 输出部署的一些信息
    System.out.println("流程部署ID:"+deployment.getId());
    System.out.println("流程部署名称:"+deployment.getName());
    System.out.println("流程部署成功");
}

3.使用压缩文件zipStream进行部署工作流

   /**
     * 部署流程(使用压缩文件zipStream进行部署工作流)
     * 支持批量部署多个 BPMN 文件。适合一次性部署多个流程定义。
     * 需要将 BPMN 文件打包为 ZIP 格式。
     */
@GetMapping("/deployZipStream")
public void deployZipStream(@RequestParam("file") MultipartFile multipartFile, @RequestParam("name") String name) {
    Deployment deployment = null;
    try {
        deployment = repositoryService.createDeployment()
                .addZipInputStream(new ZipInputStream(multipartFile.getInputStream()))
                .deploy();
        System.out.println("流程部署ID:"+ deployment.getId());
        System.out.println("流程部署名称:"+ deployment.getName());
        System.out.println("流程部署成功");
    } catch (IOException e) {
        System.out.println("流程部署失败,文件验证失败,流程图有错误:"+ e.getMessage());
        throw new RuntimeException(e);
    }
}

4.使用纯文本格式(text)进行部署工作流

   /**
     * 部署流程(使用纯文本格式(text)进行部署工作流)
     *
     * 如果 XML 字符串较大,可能会占用较多内存。
     */
    @GetMapping("/deployText")
    public void deployText(@RequestBody Map<String, Object> map) {
//        文件的全名称
        String resourceName = (String) map.get("resourceName");
//        符合流程图的xml文件规范
        String flowableText = (String) map.get("flowableText");
//        流程图的名称
        String name = (String) map.get("name");
        try {
            Deployment deployment = repositoryService.createDeployment()
                    .addString(resourceName, flowableText)
                    .name(name)
                    .deploy();
            // 输出部署的一些信息
            System.out.println("流程部署ID:"+ deployment.getId());
            System.out.println("流程部署名称:"+ deployment.getName());
            System.out.println("流程部署成功");
        } catch (Exception e) {
            System.out.println("流程部署失败,文件验证失败,流程图有错误:"+ e.getMessage());
            throw new RuntimeException(e);
        }
    }

5.使用字节数组进行部署工作流

   /**
     * 部署流程(使用字节数组进行部署工作流)
     * 直接使用字节数组部署,适合从二进制数据加载 BPMN 文件。性能较高,适合处理大文件。
     * 如果和前端联调,前端画图生成的话,然后传入后端进行部署流程图使其生效,使用此方法较为合适,他的灵活度和性能都属于较高的
     * 如果bpmn文件较小的话,就是用addString或者addInputStream方法,如果文件较大的话,就使用addBytes方法
     * 批量部署的话,使用addZipInputStream方法
     */
@GetMapping("/deployBytes")
public void deployBytes(@RequestParam("file") MultipartFile multipartFile, @RequestParam("name") String name) {
    try {
        Deployment deployment = repositoryService.createDeployment()
                .addBytes(multipartFile.getOriginalFilename(), multipartFile.getBytes())
                .name(name)
                .deploy();
        // 输出部署的一些信息
        System.out.println("流程部署ID:"+ deployment.getId());
        System.out.println("流程部署名称:"+ deployment.getName());
        System.out.println("流程部署成功");
    } catch (Exception e) {
        System.out.println("流程部署失败,文件验证失败,流程图有错误:"+ e.getMessage());
        throw new RuntimeException(e);
    }
}

2.启动流程

2.1 无参数启动流程

identityService.setAuthenticatedUserId设置发起人也就是当前用户的id,在act_hi_procinst表中的start_user_id_字段中看到发起人id

    @PostMapping("/start-process")
    public void startProcess(@RequestBody Map<String, Object> map) {
        try {
            identityService.setAuthenticatedUserId("xiaochen");
//        获取map里流程定义的key
            String processKey = (String) map.get("processKey");
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey);
            System.out.println("流程定义的id = " + processInstance.getProcessDefinitionId());
            System.out.println("流程实例的id = " + processInstance.getId());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            identityService.setAuthenticatedUserId(null);
        }
    }
2.2 带有参数启动流程
    @PostMapping("/lnitiate-application")
    public void initiateApplication(@RequestBody Map<String, Object> map) {
        String processKey = (String) map.get("processKey");
//        获取请求的参数
        Map<String, Object> paramMap = (Map<String, Object>) map.get("paramMap");
        identityService.setAuthenticatedUserId("xiaochen");
        runtimeService.startProcessInstanceByKey(processKey, paramMap);
    }

3.查看当前用户还未结束的流程

@PostMapping("/unfinished-process")
public void unfinishedProcess(@RequestBody Map<String, Object> map) {
    String assignee = (String) map.get("assignee");
    List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().startedBy(assignee).list();
    for (ProcessInstance processInstance : list) {
        System.out.println("流程定义的id = " + processInstance.getProcessDefinitionId());
        System.out.println("ProcessInstanceId = " + processInstance.getProcessInstanceId());
    }
}

4.不带参数的发起流程

@PostMapping("/apply-with-parameters")
public void applyWithParameters(@RequestBody Map<String, Object> map) {
    String processKey = (String) map.get("processKey");
    String processInstanceId = (String) map.get("processInstanceId");
    LinkedHashMap paramMap = (LinkedHashMap) map.get("paramMap");
    List<Task> tasks = taskService.createTaskQuery()
            .processDefinitionKey(processKey).processInstanceId(processInstanceId)
            .list();
    for (Task task : tasks) {
        taskService.complete(task.getId(), paramMap);
        System.out.println("流程定义的id = " + task.getProcessDefinitionId());
        System.out.println("流程实例的id = " + task.getProcessInstanceId());
        System.out.println("任务id = " + task.getId());
        System.out.println("任务名称 = " + task.getName());
        System.out.println("流程定义的id = " + task.getProcessDefinitionId());
    }
}

5.审批

5.1 根据流程审批
  @PostMapping("/approve")
    public void approve(@RequestBody Map<String, Object> map) {
        String processKey = (String) map.get("processKey");
        //        获取审批人
        String assignee = (String) map.get("assignee");
//        获取参数
        LinkedHashMap<String, Object> paramMap = (LinkedHashMap) map.get("paramMap");
//        获取审批状态是true还是false,添加审批备注
        boolean approved = (boolean) paramMap.get("approved");
        List<Task> list = taskService.createTaskQuery().processDefinitionKey(processKey).taskAssignee(assignee).list();
        for (Task task : list) {
            taskService.addComment(task.getId(), task.getProcessInstanceId(), assignee + (approved ? "通过" : "不通过"));
//        执行任务
            taskService.complete(task.getId(), paramMap);
        }
    }
5.2 单独审批
5.2.1 查询当前人的待审批列表
@PostMapping("/select-todo-task-list")
public void selectTodoTaskList(@RequestBody Map<String, Object> map) {
    try {
        String assignee = (String) map.get("assignee");
        String processKey = (String) map.get("processKey");
        if (assignee == null || assignee.trim().isEmpty()) {
            System.out.println("assignee不能为空");
        }
        List<Task> tasks;
        if (processKey != null && !processKey.trim().isEmpty()) {
            tasks = taskService.createTaskQuery()
                    .taskAssignee(assignee)
                    .processDefinitionKey(processKey)
                    .list();
        } else {
            tasks = taskService.createTaskQuery()
                    .taskAssignee(assignee)
                    .list();
        }
        // 日志记录
        for (Task task : tasks) {
            System.out.println("流程定义的id = " + task.getProcessDefinitionId());
            System.out.println("流程实例的id = " + task.getProcessInstanceId());
            System.out.println("任务id = " + task.getId());
        }
    } catch (Exception e) {
        System.out.println("查询待审批任务列表时发生异常" + e);
        System.out.println("系统错误,请稍后再试");
    }
}
5.2.2 单独审批
   @PostMapping("/approveTaskId")
    public void approveTaskId(@RequestBody Map<String, Object> map) {
        String taskId = (String) map.get("taskId");
        String processInstanceId = (String) map.get("processInstanceId");
        //        获取当前审批人
        String assignee = (String) map.get("assignee");
//        获取参数
        LinkedHashMap<String, Object> paramMap = (LinkedHashMap) map.get("paramMap");
//        获取审批状态是true还是false,添加审批备注
        boolean approved = (boolean) paramMap.get("approved");
        taskService.addComment(taskId, processInstanceId, assignee + (approved ? "通过" : "不通过"));
//        执行任务
        taskService.complete(taskId, paramMap);
    }
5.3 查看需要审批的内容
@PostMapping("/select-task-content")
public void selectTaskContent(@RequestBody Map<String, Object> map) {
    String taskId = (String) map.get("taskId");
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    System.out.println(task);
}

6.查看流程图

  @GetMapping("/genProcessDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, @RequestParam String processId) throws IOException {
//          获得当前活动的节点
        String processDefinitionId = "";
        boolean b = historyService.createHistoricProcessInstanceQuery().finished()
                .processInstanceId(processId).count() > 0;
        if (b) {// 如果流程已经结束,则得到结束节点
            HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        } else {// 如果流程没有结束,则取当前活动节点
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        }
        List<String> highLightedActivitis = new ArrayList<String>();
//          获得活动的节点
        List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();
        for (HistoricActivityInstance tempActivity : highLightedActivitList) {
            String activityId = tempActivity.getActivityId();
            highLightedActivitis.add(activityId);
        }
        List<String> flows = new ArrayList<>();
        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        // 设置支持中文的字体
        String activityFontName = "SimSun"; // 宋体
        String labelFontName = "SimSun"; // 宋体
        String annotationFontName = "SimSun"; // 宋体
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivitis, flows, activityFontName,
                labelFontName, annotationFontName, 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) {
            e.getMessage();
        } finally {
            IOUtils.closeQuietly(out);
            IOUtils.closeQuietly(in);
        }
    }

结果如下:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值