工作流的环境搭建与初体验

本文介绍了如何使用Docker部署Flowable的UI,并通过SpringBoot将其整合。详细步骤包括Docker安装、Flowable UI的启动、微服务环境配置、Flowable相关依赖的添加、数据库表变化及接口实现。最后展示了流程图的创建、部署和查看流程进展的过程。
摘要由CSDN通过智能技术生成

Flowable的UI

搬砖的码蚁:码农=Ctr+c/v;程序员=少量(Ctr+c/v)+ 设计思想 + 良好的代码风格。

Flowable的UI作用是帮助我们更加方便的画流程图

这里使用docker部署Flowable的UI。没有安装docker同学,可以先去看看另外一篇文章。

docker的安装教程

拉取镜像以及启动UI

docker pull flowable/all-in-one
docker run -d --name=flowable -p 8989:8989 flowable/all-in-one

访问

http://ip:port

登录(flowable默认账号密码是admin/test)
在这里插入图片描述

微服务整合Flowable

搭建环境

为了管理方便,将flowable作为一个服务。

服务名:flowable
端口:8082
flowable版本:6.4.0
springboot版本:2.5.5
springclou版本:2020.0.4
mysql版本:8.0.26
jdk版本:1.8

maven依赖

<!--SpringBoot-->
<spring-boot-dependencies.version>2.5.5</spring-boot-dependencies.version>
<!-- SpringCloud -->
<spring-cloud-dependencies.version>2020.0.4</spring-cloud-dependencies.version>
<!--        mysql-->
<mysql.version>8.0.11</mysql.version>
<!--        flowable-->
<flowable.version>6.4.0</flowable.version>
<!--            flowable-->
<dependency>
	<groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>${flowable.version}</version>
</dependency>
 <!--mysql驱动包-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.version}</version>
</dependency>
<!--                cloud-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud-dependencies.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>
<!--            boot-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>${spring-boot-dependencies.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

端口

server:
  port: 8082
flowable:
  #关闭job定时器
  async-executor-activate: false
  #关闭自动部署流程
  check-process-definitions: false

第一个flowable

使用FlowableUI画一个基本的流程图(画图的教程,后面有时间再写一篇文章)

  1. 领导审批流程
    在这里插入图片描述
  2. 保存以及下载流程图
    在这里插入图片描述
  3. 将下载好的文件复制到项目

process文件夹,自己创建,方便管理流程图文件
在这里插入图片描述

  1. 观察数据库的数据表变化
  2. 启动项目前,数据库表:可以看到现在只有一张user表
    在这里插入图片描述
  3. 启动项目后,数据库表:可以看到自动的新增了66张flowable的基础表(注意: 不同flowable版本,生产的表数目可能不一样)
    在这里插入图片描述
  4. 测试流程
  • 部署流程
  • 启动流程
  • 查看流程进展

接口

package cn.ant.service;

import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;

@Service
public interface FlowableManagerService {
    /**
     * 部署工作流
     *
     * @param flowableName
     * @return
     */
    public String deployFlowable(String flowableName);

    /**
     * 启动工作流
     *
     * @param flowableDefinitionKey
     * @return
     */
    public String startFlowable(String flowableDefinitionKey);

    /**
     * 工作流流转
     * @param flowableInstanceId
     * @param definitionKey
     */
    public void flowableComplete(String flowableInstanceId, String definitionKey);

    /**
     * 获取工作流的流程图(查看进展)
     *
     * @param flowableInstanceId
     * @param response
     */
    public void getFLowableImage(String flowableInstanceId, HttpServletResponse response);
}

实现类

package cn.ant.service.impl;

import cn.ant.service.FlowableManagerService;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.DeploymentBuilder;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class FlowableManagerServiceImpl implements FlowableManagerService {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Override
    public String deployFlowable(String flowableName) {
        log.info("deployFlowable_param_is {}", flowableName);
        String classPath = StrUtil.format("process/{}.bpmn20.xml", flowableName);
        DeploymentBuilder deploymentBuilder = repositoryService
                .createDeployment()
                .name(flowableName)
                .addClasspathResource(classPath);
        Deployment deployId = deploymentBuilder.deploy();
        return deployId.getId();
    }

    @Override
    public String startFlowable(String flowableDefinitionKey) {
        log.info("startFlowable_inParam_is {}", flowableDefinitionKey);
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey(flowableDefinitionKey);
        log.info("startFlowable_outParam_is {}", processInstance);
        return processInstance.getId();
    }

    @Override
    public void flowableComplete(String flowableInstanceId, String definitionKey) {
        String format = StrUtil.format("flowableComplete_inParam_is {}-{}", flowableInstanceId, definitionKey);
        log.info(format);
        Task task = taskService.createTaskQuery().processInstanceId(flowableInstanceId).taskDefinitionKey(definitionKey).singleResult();
        taskService.complete(task.getId());
        log.info("flowableComplete_outParam_is {}", task);
    }

    @Override
    public void getFLowableImage(String flowableInstanceId, HttpServletResponse response) {
        //获取历史流程实例
        HistoricProcessInstance historicProcessInstance = historyService
                .createHistoricProcessInstanceQuery()
                .processInstanceId(flowableInstanceId)
                .singleResult();
        //获取历史活动节点  按照id升序排序(即节点执行先后顺序)
        List<HistoricActivityInstance> historicActivityInstances = historyService
                .createHistoricActivityInstanceQuery()
                .processInstanceId(flowableInstanceId)
                .orderByHistoricActivityInstanceId()
                .asc().list();
        //获取当前活动节点
        List<Execution> executionList = runtimeService
                .createExecutionQuery()
                .processInstanceId(flowableInstanceId).list();
//        //回滚过的节点
//        List<String> rollbackActivitis = new ArrayList<String>();
        //所有历史节点
        List<String> allActivitis = new ArrayList<>();
        //过滤之后的节点
        List<String> activitis = new ArrayList<>();
        //画布
        ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();

        //活动节点的id
        List<String> runningActivitisIdList = new ArrayList<>();
        for (Execution execution : executionList) {
            if (StrUtil.isNotBlank(execution.getActivityId())) {
                runningActivitisIdList.add(execution.getActivityId());
            }
        }

        //回滚过的节点
//        for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
//            rollbackActivitis.add(historicActivityInstance.getActivityId());
//        }
//        List<String> rollbackActivitiList = rollbackActivitis.stream().distinct().collect(Collectors.toList());
        allActivitis = historicActivityInstances.stream().filter(x -> {
                    log.info("========>getDeleteReason {}", x.getDeleteReason());
                    return !"Change activity to rollback_one".equalsIgnoreCase(x.getDeleteReason());
                }
        ).map(HistoricActivityInstance::getActivityId).collect(Collectors.toList());
        log.info("allActivitis ==> {}", allActivitis);
        //获取流程图
        log.info("historicProcessInstance_getProcessDefinitionId {}", historicProcessInstance.getProcessDefinitionId());
        BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());

        InputStream in = new DefaultProcessDiagramGenerator().generateDiagram(bpmnModel, "png", allActivitis, runningActivitisIdList, "宋体", "宋体", "宋体", null, 1.0, false);
        byte[] buf = null;
        try {
            buf = IoUtil.readInputStream(in, "flow image name");
            response.getOutputStream().write(buf);
        } catch (Exception e) {
            log.error("操作异常", e);
        } finally {
            IoUtil.closeSilently(in);
        }
    }
}

流程查看,最终流程结果(当前节点为红色,当前节点的前面一个节点是灰色,这样就表示当前节点是一个未完成的节点)如下图:

在这里插入图片描述

总结

到此为止,flowable的环境已经搭建完成了,以及也跑了一个最基本的流程图。可能刚接触工作流的时候(无论是flowable,还是activiti),看到上面的流程,会有点懵逼,慢慢来就行了。接下来的文章,会持续介绍flowable(一些实际的用法,比如多实例会签、动态扩展节点,留言,权限等等),如果有需要的,可以关注一下哎。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬砖的码蚁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值