总概
定义:工作流是在计算机支持下业务流程的自动或半自动化,其通过对流程进行描述以及按一定规则执行以完成相应工作。
应用:随着计算机技术的发展以及工业生产、办公自动化等领域的需求不断提升,面向事务审批、材料提交、业务整合和数据统计等应用需求的图文工作流、业务工作流也不断涌现。利用科学工作流还可以用于研究(地理)模型的集成。
研究内容
研究工作流可从工作流模型、工作流的定义和表达、工作流引擎
1.工作流模型
1.1面向控制:通常业务工作流大多数都是面向控制的工作流,以最常见的公司请假流程为例,当请假天数小于阈值时能向主管请假,否则只能向经理审批。
编辑
1.2面向数据:通常面向数据是科学工作流处理的业务,以GIS水文分析为例,进行水文分析需要DEM数据,而且需要依次进行填挖、流向、汇流累积量等分析,通常前一步的输出结果常常为下一步的输入数据,此过程涉及到数据。因此,需选择面向数据的工作流模型。
编辑
2.工作流的定义和表达
2.1.BPMN(Business Process Modeling Notation,即业务流程建模符号):是一种流程建模的通用和标准语言,用来绘制业务流程图,以便更好地让各部门之间理解业务流程和相互关系。
学习BPMN可去官网下载BPMN2规范文档,当然文档为全英文,需要一定英语功底
BPMN官网:BPMN Specification - Business Process Model and Notation
编辑
2.1.1BPMN结构(以上述请假案例为例)
BPMN大致可以分为两部分,一部分为<process></process>标签内,对BPMN要素的描述,另一部分为<bpmndi></bpmndi>内包含其位置信息,保证个元素的相对位置与设计时一致。
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="leaveProcess" name="简单请假流程" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name="请假申请"></userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="exclusivegateway1"></sequenceFlow>
<userTask id="usertask2" name="杰里奥审批"></userTask>
<sequenceFlow id="flow3" sourceRef="exclusivegateway1" targetRef="usertask2">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${day>0&&day<=3}]]></conditionExpression>
</sequenceFlow>
<userTask id="usertask3" name="汤姆逊审批"></userTask>
<sequenceFlow id="flow4" sourceRef="exclusivegateway1" targetRef="usertask3">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${day>3}]]></conditionExpression>
</sequenceFlow>
<endEvent id="endevent2" name="End"></endEvent>
<sequenceFlow id="flow6" sourceRef="usertask3" targetRef="endevent2"></sequenceFlow>
<sequenceFlow id="flow7" sourceRef="usertask2" targetRef="endevent2"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_leaveProcess">
<bpmndi:BPMNPlane bpmnElement="leaveProcess" id="BPMNPlane_leaveProcess">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="90.0" y="220.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="280.0" y="210.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
<omgdc:Bounds height="40.0" width="40.0" x="430.0" y="218.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="610.0" y="70.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
<omgdc:Bounds height="55.0" width="105.0" x="610.0" y="370.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent2" id="BPMNShape_endevent2">
<omgdc:Bounds height="35.0" width="35.0" x="870.0" y="221.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="125.0" y="237.0"></omgdi:waypoint>
<omgdi:waypoint x="280.0" y="237.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="385.0" y="237.0"></omgdi:waypoint>
<omgdi:waypoint x="430.0" y="238.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="450.0" y="218.0"></omgdi:waypoint>
<omgdi:waypoint x="450.0" y="97.0"></omgdi:waypoint>
<omgdi:waypoint x="610.0" y="97.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="450.0" y="258.0"></omgdi:waypoint>
<omgdi:waypoint x="451.0" y="397.0"></omgdi:waypoint>
<omgdi:waypoint x="610.0" y="397.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
<omgdi:waypoint x="715.0" y="397.0"></omgdi:waypoint>
<omgdi:waypoint x="887.0" y="397.0"></omgdi:waypoint>
<omgdi:waypoint x="887.0" y="256.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
<omgdi:waypoint x="715.0" y="97.0"></omgdi:waypoint>
<omgdi:waypoint x="887.0" y="97.0"></omgdi:waypoint>
<omgdi:waypoint x="887.0" y="221.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
2.1.2 核心概念
编辑
编辑
2.1.3设计器推荐
processon:最常见的在线绘图软件,也可绘制BPMNProcessOn思维导图流程图-在线画思维导图流程图_在线作图实时协作
Camunda Modeler:Camunda工作流设计器,桌面端,支持Window和Linux系统,功能十分强大,工作流节点、任务和事件的属性非常丰富!!!
https://camunda.com/platform/modeler/
编辑
Bpmn.js:前端BPMN设计器,功能仅次于Camunda Modeler个人认为,但是需要不少前端知识没上较前两者较难。但由于是前端BPMN设计器,可以将其嵌入到自己的前后端项目中。
推荐学习教程:
官网:bpmn-js: BPMN 2.0 rendering toolkit and web modeler | Toolkits | bpmn.io
最全的BPMN.js中文教程:全网最详bpmn.js教材-基础篇 - 简书https://github.com/LinDaiDai/bpmn-chinese-document/blob/master/directory.md
项目:Bpmn.js+Vue,Gitee和Github都有不少项目
编辑
3.工作流引擎
工作流设计器设计好的BPMN,可以直接导出BPMN文件或者XML文件,而怎样控制BPMN文件执行这就得靠工作流引擎控制(图3.1)。工作流引擎的工作大致可分为:流程解释、流程执行、管理监控和调用应用这四部分(图3.2)。
编辑
图3.1 工作流设计与工作流引擎关系
编辑
图3.2工作流引擎作用
现三个主流工作流引擎Activiti、Flowable、Camunda比较与推荐:
1.开源:推荐Activiti(完全开源)、Camunda和Flowable(部分开源,分开源和商业版)
2.新颖、学习资料、功能:Camunda>Flowable>Activiti,Camunda相比更新颖强大(个人感觉)
3.集成Spring-Boot前后端分离项目:Camunda>Flowable>Activiti(个人观点)
activiti这功能较少,很多功能都需要自行开发;flowable6.5版本作为最后一个支持Spring Boot 1.5.x和Spring 4.x的版本,后续版本不在提供支持,form表单模块已经商业化,开源版已经不再维护; Ca- munda开源版的功能肯定是要比activiti7功能多些的,而且Camunda的内部运行的性能更好;
优质推文:常见的工作流引擎(osworkflow、jbpm、activiti、flowable、camunda)比较 - 知乎
Activiti:Open Source Business Automation | Activiti
Flowable:Open Source
Camunda: https://camunda.com/ Camunda 中文站 | docs.camunda.orghttps://camunda.com/
学习资料分享:
B站视频:🔍Activiti、Flowable、Camunda或工作流引擎
推荐网站:自称最全工作流文档 :仿钉钉飞书企业微信流程设计器
项目推荐:
入门:
Activiti项目:(了解工作流引擎最基本流程:部署、启动、挂载、激活等操作)
同时还可以结合B站视频或者Activiti或者Camunda自带的工作流工作可视化页面
编辑
工作流执行的最基本流程:
编辑
GitHub - jellyleo/activiti7: springboot2集成activiti7的工作流项目
集成开发:
仿钉钉系列:
dingding-mid-business-java: 仿钉钉飞书企业微信样式设计器,基于Flowable,Camunda
Ruoyi-Flowable-Plus:RuoYi-Flowable-Plus: 本项目基于 RuoYi-Vue-Plus 进行二次开发扩展Flowable工作流功能,支持在线表单设计和丰富的工作流程设计能力。如果觉得这个项目不错,麻烦点个star🌟。
更多上gitee或者github🔍类似关键词
3.1.Activiti
1.基本流程
BPMN部署(BPMN或者ZIP文件)
/**
*
* 功能描述:classpath部署流程
*
* @param request
* @param response
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/deploy")
@ResponseBody
public String deploy(HttpServletRequest request, HttpServletResponse response) {
String name = request.getParameter("name");
String resource = request.getParameter("resource");
if (StringUtils.isEmpty(resource) || StringUtils.isEmpty(name)) {
return "param error";
}
try {
// 创建一个部署对象
Deployment deploy = repositoryService.createDeployment().name(name)
.addClasspathResource("processes/" + resource).deploy();
System.out.println("部署成功:" + deploy.getId());
System.out.println("*****************************************************************************");
} catch (Exception e) {
return "fail";
}
return "success";
}
/**
*
* 功能描述:zip部署流程
*
* @param request
* @param response
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/deploy/zip")
@ResponseBody
public String deployZip(HttpServletRequest request, HttpServletResponse response) {
String name = request.getParameter("name");
String zip = request.getParameter("zip");
if (StringUtils.isEmpty(zip) || StringUtils.isEmpty(name)) {
return "param error";
}
try {
InputStream in = this.getClass().getClassLoader().getResourceAsStream("processes/" + zip);
ZipInputStream zipInputStream = new ZipInputStream(in);
Deployment deployment = repositoryService// 与流程定义和部署对象相关的Service
.createDeployment()// 创建一个部署对象
.name(name)// 添加部署名称
.addZipInputStream(zipInputStream)// 完成zip文件的部署
.deploy();// 完成部署
System.out.println("部署ID:" + deployment.getId());
System.out.println("部署名称:" + deployment.getName());
System.out.println("*****************************************************************************");
} catch (Exception e) {
return "fail";
}
return "success";
}
启动(启动流程,可得到一个流程实例)与删除流程
@RequestMapping(value = "/start")
@ResponseBody
public String start(HttpServletRequest request, HttpServletResponse response) {
String processDefinitionKey = request.getParameter("processId");
String variable = request.getParameter("variable");
if (StringUtils.isEmpty(processDefinitionKey)) {
return "param error";
}
try {
Map<String, Object> variables = new HashMap<>();
if (!StringUtils.isEmpty(variable)) {
CommonVariable variablesEntity = JSON.parseObject(variable, CommonVariable.class);
variables = BeanUtil.beanToMap(variablesEntity);
}
ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
// // Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据
// ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey,
// variables);
System.out.println("流程实例ID:" + instance.getId());
System.out.println("流程定义ID:" + instance.getProcessDefinitionId());
System.out.println("*****************************************************************************");
} catch (Exception e) {
e.printStackTrace();
return "fail";
}
return "success";
}
/**
*
* 功能描述:删除流程
*
* @param request
* @param response
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/delete")
@ResponseBody
public String deleteProcess(HttpServletRequest request, HttpServletResponse response) {
String processId = request.getParameter("processId");
if (StringUtils.isEmpty(processId)) {
return "param error";
}
try {
runtimeService.deleteProcessInstance(processId, "流程已完毕");
System.out.println("终止流程");
System.out.println("*****************************************************************************");
} catch (Exception e) {
return "fail";
}
return "success";
}
流程实例挂载与激活
/**
*
* 功能描述:流程实例挂起
*
* @param request
* @param response
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/instance/suspend")
@ResponseBody
public String suspendProcessInstance(HttpServletRequest request, HttpServletResponse response) {
String processInstanceId = request.getParameter("processInstanceId");
if (StringUtils.isEmpty(processInstanceId)) {
return "param error";
}
try {
// 根据一个流程实例的id挂起该流程实例
runtimeService.suspendProcessInstanceById(processInstanceId);
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
System.out.println("流程实例ID:" + processInstance.getId());
System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例状态:" + processInstance.isSuspended());
System.out.println("*****************************************************************************");
} catch (Exception e) {
return "fail";
}
return "success";
}
/**
*
* 功能描述:流程实例激活
*
* @param request
* @param response
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/instance/activate")
@ResponseBody
public String activateProcessInstance(HttpServletRequest request, HttpServletResponse response) {
String processInstanceId = request.getParameter("processInstanceId");
if (StringUtils.isEmpty(processInstanceId)) {
return "param error";
}
try {
// 根据一个流程实例id激活该流程
runtimeService.activateProcessInstanceById(processInstanceId);
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
System.out.println("流程实例ID:" + processInstance.getId());
System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例状态:" + processInstance.isSuspended());
System.out.println("*****************************************************************************");
} catch (Exception e) {
return "fail";
}
return "success";
}
流程定义的挂载与激活
/**
*
* 功能描述:流程定义挂起
*
* @param request
* @param response
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/definition/suspend")
@ResponseBody
public String suspendProcessDefinition(HttpServletRequest request, HttpServletResponse response) {
String processDefinitionId = request.getParameter("processDefinitionId");
if (StringUtils.isEmpty(processDefinitionId)) {
return "param error";
}
try {
// 根据一个流程定义的id挂起该流程实例
repositoryService.suspendProcessDefinitionByKey(processDefinitionId);
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(processDefinitionId).singleResult();
System.out.println("流程定义ID:" + processDefinition.getId());
System.out.println("流程定义状态:" + processDefinition.isSuspended());
System.out.println("*****************************************************************************");
} catch (Exception e) {
return "fail";
}
return "success";
}
/**
*
* 功能描述:流程实例激活
*
* @param request
* @param response
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/instance/activate")
@ResponseBody
public String activateProcessInstance(HttpServletRequest request, HttpServletResponse response) {
String processInstanceId = request.getParameter("processInstanceId");
if (StringUtils.isEmpty(processInstanceId)) {
return "param error";
}
try {
// 根据一个流程实例id激活该流程
runtimeService.activateProcessInstanceById(processInstanceId);
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
System.out.println("流程实例ID:" + processInstance.getId());
System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例状态:" + processInstance.isSuspended());
System.out.println("*****************************************************************************");
} catch (Exception e) {
return "fail";
}
return "success";
}
2.SpringBoot集成Activiti设计器
推荐推文:
Activiti6.0(十三)整合官方流程设计器_activiti6提供的web设计器-CSDN博客
Springboot+Activiti6+在线流程编辑器整合_activiti在线流程设计器-CSDN博客
3.2 Camunda
3.3Flowable