Flowable6.x导出/查看/跟踪流程图

news2024/11/24 20:09:29

Flowable6.x导出/查看/跟踪流程图

项目源码仓库

Flowable诞生于Activiti,是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎可用于部署BPMN 2.0流程定义,可以十分灵活地加入你的应用/服务/构架。

本文介绍4种绘制流程图的方式,前3种是在后台绘制静态图(image/png格式),以Stream形式返回前端显示。最后1种是后端生成JSON形式的结构化数据,由前端使用Snap.svg绘制的交互式SVG动画流程图。

导入Maven依赖

        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter-basic</artifactId>
            <version>6.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-json-converter</artifactId>
            <version>6.4.1</version>
        </dependency>

导出流程定义图

适用于流程管理或启动流程时查看已经部署的流程图,流程图不包括任务办理实际流转信息。
使用流程定义(ProcessDefinition.id),通过调用flowable 的RepositoryService来导出其流程定义的图片资源。
源码:

@RestController
@Slf4j
public class ProcessController {
    @Autowired
    private MyProcessService processService;
    
    /**
     * 通过processDefinition.id和resType导出流程XML或图片资源
     * @param id processDefinition.id
     * @param resType 取值 “image/png”或“text/xml”
     * @param response
     * @throws Exception
     */
    @GetMapping(value = "/res/exp")
    @ApiOperation("通过processDefinition.id和resType导出流程XML或图片资源")
    public void resourceRead(@RequestParam("id") String id,@RequestParam("resType") String resType, HttpServletResponse response) throws Exception {
        /** resType取值 “image/png”或“text/xml” **/
        InputStream resourceAsStream = processService.resourceRead(id,resType);
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }
}

@Service
public class MyProcessServiceImpl implements MyProcessService {
    @Autowired
    private RepositoryService repositoryService;
    
    @Override
    public InputStream resourceRead(String id, String resType) throws Exception {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
        String resourceName = "";
        if (resType.equals("image/png")) {
            resourceName = processDefinition.getDiagramResourceName();
        } else if (resType.equals("text/xml")) {
            resourceName = processDefinition.getResourceName();
        }
        InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
        return resourceAsStream;
    }
}

运行效果如下:
在这里插入图片描述

绘制流程待办流图

适用于查看待办任务列表时,绘制该任务的流程图,流程图可强调显示当前待办任务所处的流程节点。使用流程实例(processInstanceId)ID,通过调用flowable引擎来绘制流程图。
源码:

@RequestMapping("/api/workflow/auth/activiti/task")
@RestController
@Slf4j
public class TaskController {
    @Autowired
    private MyTaskService myTaskService;
    
    /**
     * 绘制强调当前节点的流程图
     */
    @GetMapping(value = "/process/diagram")
    @ApiOperation("绘制强调当前节点的流程图")
    public void genProcessDiagram(@RequestParam("processInstanceId") String processInstanceId, HttpServletResponse httpServletResponse) throws Exception {
        InputStream resourceAsStream = myTaskService.genProcessDiagram(processInstanceId);
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            httpServletResponse.getOutputStream().write(b, 0, len);
        }
    }
}    
@Slf4j
@Service
public class MyTaskServiceImpl implements MyTaskService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Resource
    private ProcessEngine processEngine;

    @Override
    public InputStream genProcessDiagram(String processId) throws Exception {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();

        //流程走完的不显示图
        if (pi == null) {
            return null;
        }
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        //使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
        String InstanceId = task.getProcessInstanceId();
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(InstanceId)
                .list();

        //得到正在执行的Activity的Id
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 2.0,true);
        return in;
    }
}    

在这里插入图片描述

绘制流程已办流图

适用于查看已办任务列表时,绘制该任务的流程图,流程图可强调显示任务办理实际经过的路径。使用流程实例(processInstanceId)ID,通过调用flowable引擎来绘制流程图。
源码:

@RequestMapping("/api/workflow/auth/activiti/task")
@RestController
@Slf4j
public class TaskController {
    @Autowired
    private MyTaskService myTaskService;

    /**
     * 读取带跟踪的图片
     */
    @GetMapping(value = "/trace/photo")
    public void tracePhoto(@RequestParam("processInstanceId") String processInstanceId, HttpServletResponse response) throws Exception {
        InputStream inputStream = myTaskService.genTracePhoto(processInstanceId);

        // 输出资源内容到相应对象
        byte[] b = new byte[1024];
        int len;
        while ((len = inputStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }
}    
@Slf4j
@Service
public class MyTaskServiceImpl implements MyTaskService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;

    @Override
    public InputStream genTracePhoto(String processInstanceId) throws Exception {
        String procDefId;
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        if (processInstance == null) {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            procDefId = historicProcessInstance.getProcessDefinitionId();

        } else {
            procDefId = processInstance.getProcessDefinitionId();
        }

        BpmnModel bpmnModel = repositoryService.getBpmnModel(procDefId);
        DefaultProcessDiagramGenerator defaultProcessDiagramGenerator = new DefaultProcessDiagramGenerator(); // 创建默认的流程图生成器
        String imageType = "png"; // 生成图片的类型
        List<String> highLightedActivities = new ArrayList<>(); // 高亮节点集合
        List<String> highLightedFlows = new ArrayList<>(); // 高亮连线集合
        List<HistoricActivityInstance> hisActInsList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .list(); // 查询所有历史节点信息
        hisActInsList.forEach(historicActivityInstance -> { // 遍历
            if("sequenceFlow".equals(historicActivityInstance.getActivityType())) {
                // 添加高亮连线
                highLightedFlows.add(historicActivityInstance.getActivityId());
            } else {
                // 添加高亮节点
                highLightedActivities.add(historicActivityInstance.getActivityId());
            }
        });
        String activityFontName = "宋体"; // 节点字体
        String labelFontName = "微软雅黑"; // 连线标签字体
        String annotationFontName = "宋体"; // 连线标签字体
        ClassLoader customClassLoader = null; // 类加载器
        double scaleFactor = 1.0d; // 比例因子,默认即可
        boolean drawSequenceFlowNameWithNoLabelDI = true; // 不设置连线标签不会画
        // 生成图片
        InputStream inputStream = defaultProcessDiagramGenerator.generateDiagram(bpmnModel, imageType, highLightedActivities
                , highLightedFlows, activityFontName, labelFontName, annotationFontName, customClassLoader,
                scaleFactor, drawSequenceFlowNameWithNoLabelDI); // 获取输入流
        return inputStream;
    }
}    
    

在这里插入图片描述

前端绘制流程跟踪图和显示日志

无论是待办、已办,亦或是流转中、已结束的流程实例,通过使用JS绘制SVG格式的交互式流程图,与以上三种方式相比,在效果上都具有明显优势。
运行效果如下图所示:
在这里插入图片描述

具体内容参见下一篇博文

项目源码仓库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/432132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TryHackMe-Set(Windows渗透测试 | WinDefender免杀)

Set 您再次发现自己在Windcorp公司的内部网络上。上次你去那里的味道真好&#xff0c;你回来了 了解更多。 但是&#xff0c;这次他们设法保护了域控制器&#xff0c;因此您需要找到另一台服务器&#xff0c;并在第一次扫描时发现“Set”。 Set被用作开发人员的平台&#xf…

集团企业大数据治理解决方案word

第一章 集团企业大数据治理阶段目标 通过数据平台和BI应用建设&#xff0c;集团企业大数据将搭建统一的大数据共享和分析平台&#xff0c;对各类业务进行前瞻性预测及分析&#xff0c;为集团企业各层次用户提供统一的决策分析支持&#xff0c;提升数据共享与流转能力。 一.1、…

Redis持久化的几种方式

Redis 持久化也是 Redis 和 Memcached 的主要区别之一&#xff0c;因为 Memcached 是不具备持久化功能的。 1.持久化的几种方式 Redis 持久化拥有以下三种方式&#xff1a; 快照方式&#xff08;RDB, Redis DataBase&#xff09;将某一个时刻的内存数据&#xff0c;以二进制的…

SpringAOP入门基础银行转账实例(进阶版)------------事务处理

SpringAOP入门基础银行转账实例**&#xff08;进阶版&#xff09;**------------事务处理 由上一节讲述的通过Connection和QueryRunner对事务进行的处理(详情可以去我之前写的博客文章&#xff1a;https://blog.csdn.net/m0_56245143/article/details/130069160?spm1001.2014…

派盘为您的个人数据安家

现如今,我们的生活中有着各种各样的数据。在工作中会有各种文件、邮件;在生活中则有照片和视频等。数据的来源多,时间点不一致且混乱。 数据是否能安全、稳定、长久的存储以及便捷高效的使用对我们来说相当重要。你是否经常出差需要带上电脑或者移动硬盘,想存网盘又怕丢失或…

牛客网:HJ1 字符串最后一个单词的长度

题目部分&#xff1a; 解题思路&#xff1a; 方案一&#xff1a; 对于本题&#xff0c;看似简单&#xff0c;其实有坑。 就是在获取单词这块&#xff0c;不能直接用cin这样子操作&#xff0c;否则不能获取到完整的单词&#xff0c;因为cin这样的读到空格就不会往后续读了&…

elsticsearch与关系数据库的区别

查看所有索引&#xff08;表&#xff09; 向索引&#xff08;表&#xff09;中添加数据&#xff1a; 自定义id添加数据&#xff1a; 自定义id添加数据&#xff1a;方式二

Android12之网络共存

一.思路 所谓共存就是让两个网络同时使用,如果想让哪个网络作为外网,则该网络优先级要高于内网的网络,即可达到外网用来上网的需求,那么要想共存,就必须到从低优先级网络切换到优先级高的网络时,不要做断开操作,即可达到,两个网络同时存在的需求,做到以上两点,我们便…

MiniGPT4,开源了

简介 MiniGPT-4 旨在将来自预训练视觉编码器的视觉信息与先进的大型语言模型 (LLM) 对齐。 具体来说&#xff0c;在文本方面&#xff0c;作者利用 Vicuna 作为语言解码器&#xff0c;在视觉感知方面&#xff0c;使用了与BLIP-2相同的视觉编码器&#xff0c;并且语言和视觉模型…

数据结构(C语言实现)——二叉树的概念及二叉树顺序结构和链式结构的实现(堆排序+TOP-K问题+链式二叉树相关操作)

文章目录1. 前言2. 树的概念及结构2.1 树的概念2.2 树的相关概念2.3 树的表示3. 二叉树的概念3.1 特殊二叉树3.2 二叉树的性质4. 二叉树的顺序存储4.1 堆的概念4.2 堆的实现4.2.1 堆的结点定义4.2.2 堆的打印和销毁4.2.3 堆的插入4.2.4 堆的删除4.2.5 取堆顶数据4.2.6 堆的判空…

【Python学习笔记】cs231nPython Numpy教程

【Python学习笔记】cs231nPython Numpy教程 回顾经典教程cs231n&#xff0c;完成assignments觉得很困难&#xff0c;感觉自己python基础语法掌握的不是很熟&#xff0c;就顺藤摸瓜找了cs231n他们的官方Python个Numpy教程 如果对英文原版上手有困难&#xff0c;可以看这个&…

智慧园区水电监测系统

随着人们对环保意识的提高&#xff0c;智慧园区的建设也越来越受到关注。其中&#xff0c;水电监测系统是智慧园区的一个重要组成部分。本文将从以下几个方面介绍智慧园区水电监测系统的特点和优势。 一、智慧园区水电监测系统的特点 1.实时监测&#xff1a;智慧园区水电监测系…

某医院网络故障分析案例

1、背景 某市第一医院用户反馈&#xff0c;近期内部业务系统出现访问慢的情况&#xff0c;这种情况严重影响到用户的体验和工作效率。 针对此问题&#xff0c;我们通过NetInside流量分析系统&#xff0c;提供实时和历史原始流量。重点针对网络异常流量跟踪分析&#xff0c;找…

go数据结构(二叉树的遍历)

用数组来存储二叉树如何遍历的呢&#xff1f; 如果父节点的数组下表是i&#xff0c;那么它的左孩子就是i * 2 1&#xff0c;右孩子就是 i * 2 2。 二叉树的遍历方式&#xff1a; 二叉树有三种基本遍历方式&#xff0c;分别是前序遍历、中序遍历和后序遍历。遍历的原理是从根…

Jenkins 流水线

采用Jenkins的自由风格构建的项目&#xff0c;适合用于测试和学习&#xff0c;主要问题有&#xff1a; 构建过程中整体流程是不可见的&#xff0c;无法确认每个流程花费的时间出现问题不方便快速的定位无法进行版本化管理多个任务中有很多步骤需要重复搭建 Jenkins的Pipeline…

MYSQL Row 752 was cut by GROUP_CONCAT()

因为group_concat有个最大长度的限制&#xff0c;GROUP_CONCAT函数返回的结果大小被MySQL默认限制为1024(字节)的长度。超过最大长度就会被截断掉 解决方法&#xff1a;更改配置文件&#xff0c;修改长度。 https://blog.csdn.net/zzddada/article/details/115082236 concat…

DHCP与RIP配置实验

目录 一、实验要求与拓扑结构 1、实验要求 2、提前规划好网段的拓扑结构如下图 二、实验步骤 1、给每台路由器的各个接口配置ip 2、给路由器AR1和AR3配置dhcp服务 3、在路由器AR1和AR2上运行ripv2&#xff0c;在AR3上运行ripv1 4、更改接口的rip协议版本 一、实验要求与…

chatglm-6b模型在windows的详细安装教程

1.先是看了github的文章&#xff08;如果打不开这篇文章&#xff0c;可能需要科学上网&#xff0c;即访问外网的VPN&#xff09;&#xff1a; https://github.com/THUDM/ChatGLM-6B 2.准备&#xff1a;台式机&#xff0c;GPU是8G。&#xff08;关于是否可以在笔记本运行&#x…

【网路】-- HTTP协议

目录 HTTP协议 认识URL urlencode和urldecode Http http的宏观结构 http请求报文格式 http响应报文格式 HTTP的方法 表单 重定向 HTTP常见Header 会话管理 Cookie 实验证明 Connection选项 工具推荐 Fiddler 原理 应用层&#xff1a;就是程序员基于socket接口…

如何在大厂做好架构演进?

1 架构演进的定义 1.1 定义 通过设计新的系统架构(4R)&#xff0c;来应对业务和技术的发展变化。 1.2 关键点 新架构新的复杂度 1.3 目的 应对业务和技术的发展变化后带来新的复杂度。 案例 淘宝去IOE&#xff0c;是因为业务发展大了后&#xff0c;IOE的成本和可控性难…