Flowable从入门到入土

作者:独钓寒江雪

一剑一酒一江湖, 便是此生

心中有图,何必点灯。装载请注明出处

前文传送门:

简介

当前周围好多人都对flowable有所了解乃至投入到生产使用,此文章作为抛砖引玉之用。引出各位大侠进行指正。

如果你对工作流引擎有所了解,那么一定知道Java领域当前主流的工作流引擎无非就是Jboss旗下的JBPM和Alfresco旗下的Activity。

Flowable是Activiti原班主创人员从Activiti分离出来的一套工作流引擎,是一个业务流程管理(BPM)和工作流系统,适用于开发人员和系统管理员。其核心是超快速、稳定的BPMN2流程引擎,易于与 Spring集成使用。

Flowable的诞生简直和Acitiviti的诞生如出一辙!当年JBMP的主创Tom已经离开Alfresco多年,后辈们也开始步前人后尘。Tijs Rademakers、Joram Barrez等Activiti的原班核心人马,由于与Alfresco公司在项目的未来发展方向上出现分歧,于是选择集体出走,创建了Flowable,并且将第一个版本定义为5.22,而且在两周前发布了6.0版本!要知道,Activiti当前版本依然还是5.22,6.0处于Beta阶段。

Flowable团队对用户说道,“如果你还在犹豫是否加入我们,请看看Activiti源码里的作者们,再看看Flowable项目的成员们。我们是最懂Activiti、在过去几年里推动了整个社区、为社区做出贡献和改革的那帮人。”

选择Flowable的要点如下:

社区强大并开源。截止文章写时,flowable已经在计划后续版本不开源使用。但是有老版本开源在手,天下我有。毕竟工作流只是业务上的辅助平台。

更新力度强大 源源不断的更新。

主力开发团队是原activity的主力团队。

相比camuda这个工作流引擎。可定制化程度高很多。

在代码风格上,Flowable是比较尊重并且推崇DDD的开发准则的。这读起来还是让人比较舒服。

任何的工作流引擎主要工作都体现为节点的流转以及表单的填写。其还是以业务为主,工作流为辅,切不可工作流为主,业务为辅进行实际生产使用。

源码下载

Flowable的GitHub官网地址

源码目录说明

modules:该文件夹下存储了Activity项目所有模块的Java源文件。因为flowable和Activity是同一波开发团队,故此处会看到和Activity非常相似的模块。

qa: 一些通用的流程配置文件样例。

scripts: Linux平台下的一些启动脚本文件。

doc: 用户操作手册,包括了基础的UserGuide和PublicApi

docker和k8s: 容器镜像和管理

pom.xml: 所有Maven工程的parent。Flowable各个子模块项目中依赖的第三方包均定义在该文件中

服务介绍

Flowable整体是通过ProcessEngine来操作的。即不管什么框架操作流程,都需要通过ProcessEngine这个类来处理。ProcessEngine是Flowable对外公开的门面。UML类图如下:

关系图如下:

介绍下如下这些实际经常使用的到的类以及关键方法。

RepositoryService

流程建立相关。比如流程定义,流程的部署,流程文件的查询,验证BpmnModel等,流程转换成bpmnModel,BpmnModel转化成流程文件(.bpm)等。关键方法如下:

//伪代码。关键代码

// 验证bpmnModel

List validationErrors = repositoryService.validateProcess(bpmnModel);

//流程的查询

repositoryService.createProcessDefinitionQuery().processDefinitionName(route.getId().toString()).singleResult();

// 通过bpmnmodel定义流程并部署流程

Deployment deployment = repositoryService.createDeployment().addBpmnModel(bpmnModel.getProcesses().get(0).getName()+".bpmn", bpmnModel).deploy();

//将流程转成bpmnModel

repositoryService.getBpmnModel(processDefinition.getId());

//根据processDef上的deploymentId获取流程定义生成的bpmn文件或者其他资源文件。

InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);

// 删除流程定义

repositoryService.deleteDeployment(processDefinition.getDeploymentId(), cascade);

复制代码

RumtimeService

流程实例管理。管理流程实例的启动,推进,删除,获取流程实例当前状态等。

// 启动实例。businessId为业务号,一般唯一。比如lotId。商品编码。业务层方便查找

runtimeService.startProcessInstanceById(processDefinition.getId(), businessId);

// trigger形式的过站 只适用于ReceiveTask S1表示当前流程所在的taskId

ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessId).singleResult();

Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).activityId("S1").singleResult();

runtimeService.trigger(execution.getId());

复制代码

HistoryService

流程历史查询,所有有关历史的查询都从这个Service中来。

// 整个业务的持续时间

List list = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(lotId).list();

String instanceId = "";

for (HistoricProcessInstance hpi : list) {

instanceId = hpi.getId();

System.out.println("流程定义文件->" + hpi.getProcessDefinitionId());

System.out.println("ProcessInstance->" + hpi.getId());

System.out.println("StartActivityId->" + hpi.getStartActivityId());

System.out.println("EndActivityId->" + hpi.getEndActivityId());

System.out.println("startTime ->" + hpi.getStartTime() + "EndTime->" + hpi.getEndTime() + "duration" + hpi.getDurationInMillis());

}

//业务流转过程中每站的记录

List list1 = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId).list().stream().sorted(Comparator.comparing(HistoricActivityInstance :: getStartTime)).collect(Collectors.toList());

for (HistoricActivityInstance historicActivityInstance : list1) {

System.out.println("------");

System.out.println(historicActivityInstance.getActivityId());

System.out.println(historicActivityInstance.getActivityName());

System.out.println(historicActivityInstance.getActivityType());

System.out.println("startTime ->" +historicActivityInstance.getStartTime() + "EndTime->" + historicActivityInstance.getEndTime() + "duration" + historicActivityInstance.getDurationInMillis());

}

复制代码

TaskService

用于指定节点任务的主要Service.比如ReceiveTask, UserTask, MailTask,HttpTask等等。不同的Task具备了不同的处理方式。

Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).activityId("S1").singleResult();

runtimeService.trigger(execution.getId());

execution = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).activityId("S2").singleResult();

runtimeService.trigger(execution.getId());

execution = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).activityId("S3").singleResult();

runtimeService.trigger(execution.getId());

复制代码其他Service会在后续的文章中在逐一讲解。

构建流程

通过流程的bpmn文件进行部署流程

可以通过flowable提供的eclipse插件,Idea插件或者webui(需引入FlowableModuler。不推荐)上进行创建流程并保存为bpmn文件。并放入项目的classpath下进行引入部署。

注意:deployment的时候ResourceName要是bpmn结尾。不然不会被解析。相关源码参考ResourcesUtils

public static final String[] BPMN_RESOURCE_SUFFIXES = new String[] { "bpmn20.xml", "bpmn" };

public static final String[] DIAGRAM_SUFFIXES = new String[] { "png", "jpg", "gif", "svg" };

复制代码

使用bpmn模型构建并部署流程

可以通过bpmn.js。其为Camuda开源的一个BPM的前端JS库。其可以直接使用并定义相应的流程。建议用此种。比较方便且快捷。bpmn.js使用后续会有相应的文章来吹牛*。敬请期待。

可以通过自己公司的前端开发进行构建传递数据。

BpmnModel bpmnModel = new BpmnModel();

StartEvent start = new StartEvent();

start.setId("start1");

start.setName("开始节点");

SequenceFlow flow1 = new SequenceFlow();

3eflow1.setId("flow1");

flow1.setName("开始节点-->任务节点1");

flow1.setSourceRef("start1");

flow1.setTargetRef("receiveTask1");

ReceiveTask receiveTask1 = vbnew ReceiveTask();

receiveTask1.setId("receiveTask1");

receiveTask1.setName("节点1");

SequenceFlow flow2 = new SequenceFlow();

flow2.setId("flow2");

flow2.setName("节点1-->结束节点");

flow2.setSourceRef("receiveTask1");

flow2ow1.setTargetRef("endEvent");

EndEvent end = new EndEvent();

endEvent.setId("endEvent");

endEvent.setName("结束节点");

Process process=new Process();

process.setId("process1");

process.setName("process1");

process.addFlowElement(start);

process.addFlowElement(flow1);

process.addFlowElement(receiveTask1);

process.addFlowElement(flow2);

process.addFlowElement(end);

bpmnModel.addProcess(process);

repositoryService.createDeployment().addBpmnModel(bpmnModel.getProcesses().get(0).getName()+".bpmn", bpmnModel).deploy();

复制代码

踩坑总结

数据库脚本创建策略

因为flowable在数据库版本管控上使用的是Liquibase进行管控。所以在自动创建完flowable的数据库之后。一定要将ProcessEngineConfiguration的database-schema-update改成false。不然当不同的人更改了flowable的版本,会自动更新表结构。会导致问题。

所有节点的ID不能是数字

Flowable在定义的节点中不能是数字作为节点的Id。数字作为节点的ID会出现异常。异常部分堆栈如下

org.flowable.bpmn.exceptions.XMLException: javax.xml.stream.XMLStreamException: org.xml.sax.SAXParseException; lineNumber: 4; columnNumber: 6; cvc-datatype-valid.1.2.1: '1' 不是 'NCName' 的有效值。

at org.flowable.bpmn.converter.BpmnXMLConverter.convertToBpmnModel(BpmnXMLConverter.java:273)

at org.flowable.engine.impl.bpmn.parser.BpmnParse.execute(BpmnParse.java:148)

at org.flowable.engine.impl.bpmn.deployer.ParsedDeploymentBuilder.createBpmnParseFromResource(ParsedDeploymentBuilder.java:97)

at org.flowable.engine.impl.bpmn.deployer.ParsedDeploymentBuilder.build(ParsedDeploymentBuilder.java:55)

at org.flowable.engine.impl.bpmn.deployer.BpmnDeployer.deploy(BpmnDeployer.java:76)

at org.flowable.engine.impl.persistence.deploy.DeploymentManager.deploy(DeploymentManager.java:62)

复制代码本期内容就到此就结束了。如有大侠指定,请不吝赐教。。。下期介绍Flowable的表结构。

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[Flowable从入门到入土(1)-初始Flowable]http://www.zyiz.net/tech/detail-120531.html

flowable画图教程_Flowable从入门到入土(1)-初始Flowable相关推荐

  1. flowable画图教程_flowable画图教程_Flowable 学习笔记

    一.Flowable 入门介绍 官网地址:https://www.flowable.org/ Flowable6.3中文教程:https://tkjohn.github.io/flowable-use ...

  2. PIXIJS超级详细教程【从入门到入土-下】

    来自GitHub教程 GitHub - Zainking/LearningPixi: ⚡️Pixi教程中文版 PIXIJS教程[从入门到入土-上]地址[https://blog.csdn.net/qq ...

  3. PixiJS超级详细教程【从入门到入土-上】

    PixiJS 来自GitHub教程 GitHub - Zainking/LearningPixi: ⚡️Pixi教程中文版 PixiJS超级详细教程[从入门到入土-下]地址[https://blog. ...

  4. flowable画图教程_JeeGit企业级快速开发平台-JeeSite4 Flowable入门教程

    注: 998元以下课程无咨询服务 该课程包含服务内容:299元含发票 在线课程观看权 购课后,教学资源联系长春叭姐QQ:3211247533 索要 教学内容 3.1 第一章 业务流程 BPM.工作流引 ...

  5. Flink 教程 gitbook 从入门到入土(详细教程)

    Flink从入门到入土(详细教程) 和其他所有的计算框架一样,flink也有一些基础的开发步骤以及基础,核心的API,从开发步骤的角度来讲,主要分为四大部分 1.Environment Flink J ...

  6. flowable画图教程_给初学者的RxJava2.0教程(七): Flowable

    作者博客http://www.jianshu.com/u/c50b715ccaeb前言上一节里我们学习了只使用Observable如何去解决上下游流速不均衡的问题,之所以学习这个是因为Observab ...

  7. 【技术文档】R语言使用教程:从入门到入土

    1. 细胞通信工作 1. VSCode 搭配使用 1.1 安装教程 推荐教程1:Mac OS 系统下配置 VS Code 的 R 运行环境 推荐教程2:在VS Code中搭建你的R语言运行环境吧 自己 ...

  8. python控制流教程_python从入门到入土教程(2)——控制流和函数

    一 内置函数和库 二 控制流 * if condition_1: statement_block_1 * elif condition_2: statement_block_2 * else: sta ...

  9. 【C++从入门到入土】第五篇:继承(爆肝画图详解)

    系列文章目录 [C++从入门到入土]第一篇:从C到C++. [C++从入门到入土]第二篇:类和对象基础. [C++从入门到入土]第三篇:类和对象提高. [C++从入门到入土]第四篇:运算符重载. 文章 ...

最新文章

  1. 独家 | 麦肯锡教我的数据科学家的五大黄金法则
  2. POJ2342-Anniversary party-树形DP入门
  3. mysql中的字典项是啥_常见数据库设计(1)——字典数据
  4. 快速了解和使用Photon Server
  5. centos7 apache2.4 测试
  6. php写文件 效率,php中读写文件与读写数据库的效率_PHP教程
  7. Preserve Whole Object(保持对象完整)
  8. python 读取csv文件转成字符串_从CSV读取到 dataframe pandas python时dict对象转换为字符串...
  9. html轮播文字上下轮播,js、jQuery实现文字上下无缝轮播、滚动效果
  10. Spring中IoC创建对象方式(构造器注入)
  11. 为什么很少人写类似金庸的武侠小说
  12. nodejs基础-函数
  13. 锐起无盘服务器优化,锐起无盘系统制作系统优化教程.docx
  14. 驱动程序安装全攻略2
  15. opengl魔方文档_基于OpenGL的3D旋转魔方的实现.doc
  16. Windows MongoDB下载 安装以及配置(一条龙到底)
  17. 『Scrapy』爬取斗鱼主播头像
  18. js身份证号校验方法(转载我的请注明哈哈)
  19. 电气专业c语言要学得非常好吗,电气自动化专业需要学C语言吗?
  20. K3 如何将物料属性中的科目代码设置默认值

热门文章

  1. 一周年创作纪念日,冲吧少年郎
  2. 中文短文本分类实例十二-HAN(Hierarchical Attention Networks for Document Classification)
  3. 01 - 如何制定性能调优标准?
  4. Linux下读取smBIOS源码,linux – 了解SMBIOS的段组,总线,设备和功能号码
  5. 微信小程序数字保留两位小数
  6. 说说捞月狗与其他电商网站的感觉
  7. Excel-函数-拆分和组合函数
  8. 美国的Open RAN遭遇挫败,证明了华为的5G设备领先优势毋庸置疑
  9. 微信错误:errcode=40164,errmsg=invalid ip xxx.x.xxx.xxx, not in whitelist
  10. linux绑定arp mac静态,arp 静态绑定Mac地址