Flowable的UI
搬砖的码蚁:码农=Ctr+c/v;程序员=少量(Ctr+c/v)+ 设计思想 + 良好的代码风格。
Flowable的UI作用是帮助我们更加方便的画流程图
这里使用docker部署Flowable的UI。没有安装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画一个基本的流程图(画图的教程,后面有时间再写一篇文章)
- 领导审批流程
- 保存以及下载流程图
- 将下载好的文件复制到项目
process文件夹,自己创建,方便管理流程图文件
- 观察数据库的数据表变化
- 启动项目前,数据库表:可以看到现在只有一张user表
- 启动项目后,数据库表:可以看到自动的新增了66张flowable的基础表(注意: 不同flowable版本,生产的表数目可能不一样)
- 测试流程
- 部署流程
- 启动流程
- 查看流程进展
接口
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(一些实际的用法,比如多实例会签、动态扩展节点,留言,权限等等),如果有需要的,可以关注一下哎。