阿麒flowable工作流
前后端开源地址:
https://gitee.com/java314/aqi-flowable
https://gitee.com/java314/aqi-flowable-web
在线体验地址: http://114.55.109.14/#/login?redirect=%2Fflow%2Ftask
体验账号密码 aqi/123456
由于是体验的账号所以权限有所限制.
初衷
工作过程中,发现很多时候都需要使用到工作流。如何有效简洁的将工作流集成到前后端的框架内是一个难题。我查看了其他开源的工作流前后端框架,都很有借鉴意义,但是还是不太符合我的预期。
前端集成工作流毫无疑问,bpmn.js是首选,后端选择有很多,主流的则是activiti、camunda和flowable。
其实在集成的过程中,如何集成bpmn.js是最大的难题。主要是因为bpmn.js本身比较难(对于我来说),其次bpmn.js的相关资料相对来说比较少,当然后面相关资料在不断增多了,但是也比较松散。
作为一个后端,前端弱鸡,只能在别人的基础上进行魔改。
其他开源的项目,基本都保留了bpmn.js所有的节点,但是他们也只是有效的集成了几个类型的节点,比如常用的用户任务,开始结束节点,网关等等,其余节点都是保持原生的bpmn.js。
但是在实际工作中,我相信对于我们来说bpmn.js中的许多类型的节点,都是用不到的,或者说用到的几率非常小。比如消息开始,条件开始,定时开始,业务规则任务,脚本任务,发送任务等等。
使用这个框架的人很可能是工作流并不太熟悉的人,所以为了简洁,尽量的让人容易理解,能快速的开发一条新的流程。我在权衡之后只保留了很少的节点。当然其他节点只是隐藏了,等到后续需要用到相应的节点了
在开放出来,并思考设计怎么和后端有效的串联起来。
对于后端来说,我最终选择了flowable,其实是因为工作流的资料其实也很少,很多都是重复的,而flowable的相关资料能覆盖我的需求。
这个工作流框架可能还是不尽人意,但是也有很多值得借鉴之处。
简介
- 采用前后端分离的模式。
- 快速的部署开发一个流程,平台提供流程管理,流程定义中止激活,流程实例挂起激活等常用功能
- 后端采用Spring Boot、Spring Cloud & Alibaba。
- 注册中心、配置中心选型Nacos。
- 数据库选型PostgreSQL 和 MYSQL。其中MYSQL只用于存储nacos数据
- 其他第三方还有redis和minio
- 前后端很大一部分参考了ruoyi: http://www.ruoyi.vip
- 前端集成bpmn.js部分则是在bpmn-process-designer基础上魔改: https://github.com/miyuesc/bpmn-process-designer
- 后端工作流处理类,参考了flowable: https://gitee.com/lwj/flow
模块总览
- aqi—admin 权限管理服务
- aqi—job 定时任务服务
- aqi-api 内部服务间调用api
- aqi-gateway 微服务网关
- aqi-provider 提供外部接口服务
- aqi-flow 流程服务
- aqi-common 基础common模块
- aqi—common-core 公共基础模块
- aqi—common-doc 公共文档模块
- aqi—common-file 公共文件上传模块(本地)
- aqi—common-log 公共日志记录模块
- aqi—common-minio 公共minio文件存储模块
- aqi—common-mongo 公共mongodb操作模块
- aqi—common-mq 公共rocket-mq操作模块
- aqi—common-mybatis 公共mybatis模块
- aqi—common-redis 公共redis操作模块
- aqi—common-secure 公共安全模块
- aqi—common-sms 公共短信模块
模块详解
aqi-admin
aqi-admin是后台权限控制的主要模块,系统管理的相关接口与处理逻辑都放在这里
aqi-job
aqi-job 是单独抽离出来的定时任务服务,所有的定时任务都在该服务的task文件夹下,具体的定时任务逻辑分布在其他微服务中,通过微服务的内部服务调用实现。
aqi-api
aqi-api 为微服务的内部服务接口,具体实现分布在各个微服务中的provider文件夹下。
aqi-provider
aqi-provider 为第三方提供接口的服务。所有的提供给外部的接口都在这个服务中,具体的接口的逻辑分布在其他微服务中,通过微服务的内部服务调用实现。
aqi-common-core
common-core 模块主要提供了基础的一些工具类、常量类、公共异常以及http响应封装
aqi-common-doc
common-doc 模块提供knife4 后端接口文档配置,如果项目需要knife4接口文档方便调试,可以引入该模块,需配合配置一起使用
knife4:
title: aqi FRAME
description: aqi FRAME
version: 1.0
aqi-common-file
common-file 模块用于本地文件上传,一般配合nginx使用,上传文件到nginx代理的文件夹内,不用借助第三方存储工具
需配合配置一起使用
@Value("${aqi.file.prefix}")
public String localFilePrefix;
/**
* 域名或本机访问地址
*/
@Value("${aqi.file.domain}")
public String domain;
/**
* 上传文件存储在本地的根路径
*/
@Value("${aqi.file.path}")
private String localFilePath;
实际效果体验即知
aqi-common-log
common-log 为操作日志记录模块,如需要记录每次接口调用的信息,可以引用该模块。配合注解@SysLog和数据库表使用。
@SysLog注解在controller层对应的接口上即可,每次调用该接口则会记录相关信息。建议只记录增删改即可。
@RequiresPermissions("system:config:add")
@ApiOperationSupport(order = 3)
@ApiOperation(value = "新增配置")
@PostMapping("/createConfig")
@SysLog
public R createConfig(@RequestBody SysConfigDTO sysConfigDTO) {
sysConfigService.createConfig(sysConfigDTO);
return R.ok();
}
aqi-common-minio
common-minio 为minio操作模块。minio为第三方存储工具,需配合配置项和minio一起使用。minio可以用docker部署
aqi-common-mongo
common-mongo 为mongo操作模块。需配合mongoDB使用,可用docker部署。
aqi-common-mq
common-mq 为rocketmq操作模块。需配合rocketmq使用,可用docker部署
aqi-common-mybatis
mybatis操作加强,当数据库表的create_by,create_time,update_by,update_time这4个字段自动填充(新增和更新时)
注意 create_by,create_time,update_by,update_time字段名字固定。
aqi-common-redis
redis操作封装,配合redis配置项和redis一起使用
aqi-common-secure
common-secure 为公共的权限控制模块。
aqi-common-sms
common-sms 为公共的短信模块封装,目前只集成了阿里云短信
权限认证
权限认证主要的模块是 common-secure
每一次请求,common-secure公共安全模块会验证token的有效期和有效性,验证通过token中的用户信息解析存入SecurityContextHolder。
每一次调用 如果后端接口上有权限验证的注解(@RequiresPermissions 和 @RequiresRoles)则会验证用户是否有对应的权限,否则会返回权限不足的报错。
为什么在前端已经有动态路由的情况下,后台也要做权限验证:因为前端无法选择调用的情况下,不加后端控制,还是可以通过postman等工具直接调用后端,绕过权限控制。
nacos 配置文件
aqi-admin服务
server:
port: 10004
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://你的ip:5432/aqi-cloud-flow
username: 账号
password: 密码
redis:
host: 你的ip
port: 6379
database: 4
ssl: false
timeout: 1000
jedis:
pool:
max-active: 100
max-wait: -1
max-idle: 10
min-idle: 0
mybatis:
mapper-locations: classpath:mapper/*.xml
mybatis-plus:
mapperPackage: com.aqi.**.mapper
aqi:
secure:
skipUrl:
- /user/login
- /user/captcha
- /client/login
- /doc.html
- /swagger-ui.html
- /webjars/**
- /swagger-resources/**
- /v2/**
knife4:
title: AQI FRAME
description: AQI FRAME
version: 1.0
dubbo:
protocol:
port: -1
registry:
address: nacos://你的ip:8848
consumer:
check: false
aqi-job服务
server:
port: 10003
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://你的ip:5432/aqi-cloud-flow
username: 账号
password: 密码
redis:
host: 你的ip
port: 6379
database: 4
ssl: false
timeout: 1000
jedis:
pool:
max-active: 100
max-wait: -1
max-idle: 10
min-idle: 0
mybatis:
mapper-locations: classpath:mapper/*.xml
mybatis-plus:
mapperPackage: com.aqi.**.mapper
aqi:
secure:
skipUrl:
- /doc.html
- /swagger-ui.html
- /webjars/**
- /swagger-resources/**
- /v2/**
knife4:
title: AQI FRAME
description: AQI FRAME
version: 1.0
dubbo:
protocol:
port: -1
registry:
address: nacos://你的ip:8848
consumer:
check: false
aqi-flow服务
server:
port: 10011
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://你的ip:5432/aqi-cloud-flow
username: 账号
password: 密码
redis:
host: 你的ip
port: 6379
database: 4
ssl: false
timeout: 1000
jedis:
pool:
max-active: 100
max-wait: -1
max-idle: 10
min-idle: 0
mybatis:
mapper-locations: classpath:mapper/*.xml
mybatis-plus:
mapperPackage: com.aqi.**.mapper
aqi:
secure:
skipUrl:
- /client/login
- /doc.html
- /swagger-ui.html
- /webjars/**
- /swagger-resources/**
- /v2/**
knife4:
title: AQI FRAME
description: AQI FRAME
version: 1.0
dubbo:
protocol:
port: -1
registry:
address: nacos://你的ip:8848
consumer:
check: false
flowable:
#自动更新数据库
database-schema-update: true
#关闭异步执行
async-executor-activate: false
database-schema: flowable
aqi-gateway服务
server:
port: 10002
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
lowerCaseServiceId: true
aqi-provider服务
server:
port: 10006
spring:
redis:
host: 你的ip
port: 6379
database: 4
ssl: false
timeout: 1000
jedis:
pool:
max-active: 100
max-wait: -1
max-idle: 10
min-idle: 0
knife4:
title: AQI FRAME
description: AQI FRAME
version: 1.0
dubbo:
protocol:
port: -1
registry:
address: nacos://你的ip:8848
consumer:
check: false
快速启动项目
前端启动
前端代码地址:https://gitee.com/java314/aqi-flowable-web.git
npm install --registry=https://registry.npm.taobao.org
npm run dev
后端启动
后端代码地址:https://gitee.com/java314/aqi-flowable.git
1、nacos配置
部署启动nacos,新建配置文件,配置文件内容参考本文档。
2、数据库配置
根据实际情况新建数据库,nacos中配置数据库地址。数据库用的pgsql,需要新建三个模式public、flowable、flow
其中public模式存储权限控制服务的表数据,flowable模式存储的是flowable流程引擎的表数据,flow模式存储的是流程服务的表数据
导入项目提供的sql。项目只提供了flow模式和public模式sql数据,flowable模式表为flowable流程引擎启动自动创建。
3、redis配置
根据实际情况部署启动redis,nacos中配置redis地址
4、启动项目
启动AQIJobApplication、AQIAdminApplication、AQIFlowApplication、AQIGatewayApplication。启动顺序不分先后。
AQIProviderApplication为对外提供接口的服务,如果对外无需提供接口服务可以不启动。
5、登录系统
系统默认账号密码
zhong/123456
6、快速部署一个简单的流程
流程设计页面打开本项目提供的bpmn文件
点击部署,部署流程
流程定义页面进行流程权限配置
配置完后就可以在待办页面进行流程申请
注意流程权限配置之后,需要重新登录,因为表单页面的路由是在登录的时候动态生成的。如果配置了A用户具有B流程申请权限,此时A已经登录没有退出,那么A在申请B流程的时候就会找不到B流程的申请表单路由。
流程服务功能介绍
流程设计页面
流程设计页面比较简单,提供导入流程文件,流程文件下载,流程文件预览和流程部署功能
流程部署后会产生流程定义。在流程定义页面进行管理。每一个流程定义可以启动多个流程实例(这都是flowable,activiti等流程引擎的概念了)
流程定义管理
流程文件在部署之后,在这里进行管理。
框架支持对流程文件的重新设计部署。支持修改流程节点的审批人,新增减少流程节点等。修改后的流程在重新部署之后,不会影响之前的流程。
举例
原请假流程如图
我们有一个在途的请假流程如下
现在我们通过流程设计去掉最终审批的节点如图
重新申请一笔新的请假流程
新的流程不会影响老的流程实例
新流程查看如下
老的在途流程如下
流程权限配置即配置那些用户有申请该流程的权限
流程定义的中止即:默认部署之后为激活状态,如果操作流程定义中止,那么用户即使配置了申请该流程的权限,也无法申请该流程定义。中止的流程定义对所有用户申请不可见。
流程定义的激活即:将中止的流程定义重新激活。
流程定义删除即:提供流程定义删除功能。删除需保证没有在途的流程实例,否则会删除失败。
流程待办页面
所有流程的所有待办任务都在这里进行操作处理。流程的申请也在这里进行处理。
新增申请即新增流程申请,需要在流程定义页面配置权限。
流程取消编辑:需要在流程设计的时候配置了该流程节点有取消或编辑功能,一般在申请节点配置。截图如下
流程取消会直接取消该流程,编辑提供对表单重新申请编辑的功能。
流程查看为查看当前流程的所在节点,知晓流程进度
流程历史页面
流程历史页面为查看所有用户申请的历史流程(包括在途和已经完成的流程),提供历史流程数据查看
流程实例管理页面
对所有在途的流程实例进行管理,一般为流程管理员才有这个权限。
提供对在途流程实例的终止,挂起,激活。
操作挂起后,流程将从用户的流程待办中消失。
操作终止后,流程将直接结束。
注意区分流程定义的中止激活和流程实例的挂起激活。
流程定义中止后,用户无法申请对应的流程。流程实例挂起后,用户无法处理对应的待办任务。