日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Springboot-Flowable 快速开发工作流

發布時間:2024/9/27 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Springboot-Flowable 快速开发工作流 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、什么是flowable?
    • 官方文檔:
  • 二、技術選型
  • 三、Flowable與springBoot項目整合
    • 3.1. 添加依賴
    • 3.2. yml 文件配置
    • 3.3. 創建數據庫
    • 3.4. 定義流程文件
    • 3.5. 測試controller
    • 3.6. 圖片亂碼處理
  • 四、啟動項目,初始化表結構
  • 五、測試驗證
    • 5.1. 創建一個流程:
    • 5.2. 查詢待辦列表:
    • 5.3. 同意:
    • 5.4. 生成流程圖:
    • 項目源碼地址:

一、什么是flowable?

對于flowable是什么以及關于此框架的具體信息可以參看此項目的。

官方文檔:

https://www.flowable.org/docs/userguide/index.html

官網對于此項目如何使用有非常詳細的描述,只是目前還沒有對應的中文文檔。

Flowable is a light-weight business process engine written in Java.這是官網文檔對此框架的完美解釋:Flowable是一個用java語言寫的輕量級工作流引擎。

在簡單了解flowable后與activiti框架相比的第一感覺就是開發方便快速,易與springBoot等各種框架快速整合。如果項目中需要快速實現一些工作流的相關功能那么用此框架是一個不錯的選擇。

二、技術選型

框架版本
SpringBoot2.1.5.RELEASE
flowable6.4.0
mysql8.0.11

三、Flowable與springBoot項目整合

3.1. 添加依賴

將flowable的依賴加入到POM中即可,flowable使用需要一個數據庫,這里為了方便我選擇mysql

<!--springmvc啟動器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--flowable工作流依賴--><dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter-basic</artifactId><version>6.4.0</version></dependency><!--mysql依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version></dependency>

3.2. yml 文件配置

server:port: 80 spring:datasource:url: jdbc:mysql://127.0.0.1:3306/flowable?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=CTT&nullCatalogMeansCurrent=trueusername: rootpassword: root flowable:async-executor-activate: false

這樣操作后,flowable與springBoot的整個就完成了!

然后就可以運行了,初次運行時flowable會將自動執行flowable中的初始化腳本完成工作流所需要的數據表的建立,如果指定的數據庫中還未創建過flowable的相關數據表的話。

3.3. 創建數據庫

3.4. 定義流程文件

ExpenseProcess.bpmn20.xml

<?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:flowable="http://flowable.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.flowable.org/processdef"><process id="Expense" name="ExpenseProcess" isExecutable="true"><documentation>報銷流程</documentation><startEvent id="start" name="開始"></startEvent><userTask id="fillTask" name="出差報銷" flowable:assignee="${taskUser}"><extensionElements><modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete></extensionElements></userTask><exclusiveGateway id="judgeTask"></exclusiveGateway><userTask id="directorTak" name="經理審批"><extensionElements><flowable:taskListener event="create"class="com.example.demo.listen.ManagerTaskHandler"></flowable:taskListener></extensionElements></userTask><userTask id="bossTask" name="老板審批"><extensionElements><flowable:taskListener event="create"class="com.example.demo.listen.BossTaskHandler"></flowable:taskListener></extensionElements></userTask><endEvent id="end" name="結束"></endEvent><sequenceFlow id="directorNotPassFlow" name="駁回" sourceRef="directorTak" targetRef="fillTask"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='駁回'}]]></conditionExpression></sequenceFlow><sequenceFlow id="bossNotPassFlow" name="駁回" sourceRef="bossTask" targetRef="fillTask"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='駁回'}]]></conditionExpression></sequenceFlow><sequenceFlow id="flow1" sourceRef="start" targetRef="fillTask"></sequenceFlow><sequenceFlow id="flow2" sourceRef="fillTask" targetRef="judgeTask"></sequenceFlow><sequenceFlow id="judgeMore" name="大于500元" sourceRef="judgeTask" targetRef="bossTask"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${money > 500}]]></conditionExpression></sequenceFlow><sequenceFlow id="bossPassFlow" name="通過" sourceRef="bossTask" targetRef="end"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通過'}]]></conditionExpression></sequenceFlow><sequenceFlow id="directorPassFlow" name="通過" sourceRef="directorTak" targetRef="end"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通過'}]]></conditionExpression></sequenceFlow><sequenceFlow id="judgeLess" name="小于500元" sourceRef="judgeTask" targetRef="directorTak"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${money <= 500}]]></conditionExpression></sequenceFlow></process><bpmndi:BPMNDiagram id="BPMNDiagram_Expense"><bpmndi:BPMNPlane bpmnElement="Expense" id="BPMNPlane_Expense"><bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start"><omgdc:Bounds height="30.0" width="30.0" x="285.0" y="135.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="fillTask" id="BPMNShape_fillTask"><omgdc:Bounds height="80.0" width="100.0" x="405.0" y="110.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="judgeTask" id="BPMNShape_judgeTask"><omgdc:Bounds height="40.0" width="40.0" x="585.0" y="130.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="directorTak" id="BPMNShape_directorTak"><omgdc:Bounds height="80.0" width="100.0" x="735.0" y="110.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="bossTask" id="BPMNShape_bossTask"><omgdc:Bounds height="80.0" width="100.0" x="555.0" y="255.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end"><omgdc:Bounds height="28.0" width="28.0" x="771.0" y="281.0"></omgdc:Bounds></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"><omgdi:waypoint x="315.0" y="150.0"></omgdi:waypoint><omgdi:waypoint x="405.0" y="150.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"><omgdi:waypoint x="505.0" y="150.16611295681062"></omgdi:waypoint><omgdi:waypoint x="585.4333333333333" y="150.43333333333334"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="judgeLess" id="BPMNEdge_judgeLess"><omgdi:waypoint x="624.5530726256983" y="150.44692737430168"></omgdi:waypoint><omgdi:waypoint x="735.0" y="150.1392757660167"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="directorNotPassFlow" id="BPMNEdge_directorNotPassFlow"><omgdi:waypoint x="785.0" y="110.0"></omgdi:waypoint><omgdi:waypoint x="785.0" y="37.0"></omgdi:waypoint><omgdi:waypoint x="455.0" y="37.0"></omgdi:waypoint><omgdi:waypoint x="455.0" y="110.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="bossPassFlow" id="BPMNEdge_bossPassFlow"><omgdi:waypoint x="655.0" y="295.0"></omgdi:waypoint><omgdi:waypoint x="771.0" y="295.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="judgeMore" id="BPMNEdge_judgeMore"><omgdi:waypoint x="605.4340277777778" y="169.56597222222223"></omgdi:waypoint><omgdi:waypoint x="605.1384083044983" y="255.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="directorPassFlow" id="BPMNEdge_directorPassFlow"><omgdi:waypoint x="785.0" y="190.0"></omgdi:waypoint><omgdi:waypoint x="785.0" y="281.0"></omgdi:waypoint></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="bossNotPassFlow" id="BPMNEdge_bossNotPassFlow"><omgdi:waypoint x="555.0" y="295.0"></omgdi:waypoint><omgdi:waypoint x="455.0" y="295.0"></omgdi:waypoint><omgdi:waypoint x="455.0" y="190.0"></omgdi:waypoint></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram> </definitions>

其中的兩個代理類為:

package com.gblfy.flowable.listen;import org.flowable.engine.delegate.TaskListener; import org.flowable.task.service.delegate.DelegateTask;/*** @Author: gblfy* @Description:* @Date: Create in 2019/11/03 10:26*/ public class BossTaskHandler implements TaskListener {@Overridepublic void notify(DelegateTask delegateTask) {delegateTask.setAssignee("老板");} } package com.gblfy.flowable.listen;import org.flowable.engine.delegate.TaskListener; import org.flowable.task.service.delegate.DelegateTask;/*** @Author: gblfy* @Description:* @Date: Create in 2019/11/03 10:26*/ public class ManagerTaskHandler implements TaskListener {@Overridepublic void notify(DelegateTask delegateTask) {delegateTask.setAssignee("經理");} }

盡管上面的BPMN文件很長,但放心,畢竟那是通過相關的工具生成出來的,對于核心的邏輯部分也很少(主要在process 標簽內) ,如需要詳細了解的可自行學習下BPMN的標簽即可!當然,在flowable的使用文檔中也有相關的描述,詳見:Creating a ProcessEngine

這樣當此框架啟動的時候它會默認加載resource目錄下的processes時就可以將此流程配置加載到數據庫進行持久化

3.5. 測試controller

@Controller @RequestMapping(value = "expense") public class ExpenseController {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate ProcessEngine processEngine;/***************此處為業務代碼******************/ } /*** 添加報銷** @param userId 用戶Id* @param money 報銷金額* @param descption 描述*/@RequestMapping(value = "add")@ResponseBodypublic String addExpense(String userId, Integer money, String descption) {//啟動流程HashMap<String, Object> map = new HashMap<>();map.put("taskUser", userId);map.put("money", money);ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Expense", map);return "提交成功.流程Id為:" + processInstance.getId();}//上面的代碼通過接收用戶的一個請求傳入用戶的ID和金額以及描述信息來開啟一個報銷流程,并返回給用戶這個流程的Id /*** 獲取審批管理列表 */@RequestMapping(value = "/list")@ResponseBodypublic Object list(String userId) {List<Task> tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();for (Task task : tasks) {System.out.println(task.toString());}return tasks.toArray().toString();}查詢流程列表,待辦列表,通過上面的代碼獲取出此用戶需要處理的流程 /*** 批準** @param taskId 任務ID*/@RequestMapping(value = "apply")@ResponseBodypublic String apply(String taskId) {Task task = taskService.createTaskQuery().taskId(taskId).singleResult();if (task == null) {throw new RuntimeException("流程不存在");}//通過審核HashMap<String, Object> map = new HashMap<>();map.put("outcome", "通過");taskService.complete(taskId, map);return "processed ok!";}通過前端傳入的任務ID來對此流程進行同意處理 /*** 拒絕*/@ResponseBody@RequestMapping(value = "reject")public String reject(String taskId) {HashMap<String, Object> map = new HashMap<>();map.put("outcome", "駁回");taskService.complete(taskId, map);return "reject";}// 通過前端傳入的任務ID來對此流程進行駁回處理 /*** 生成流程圖 生成當前流程節點的流程圖** @param processId 任務ID*/@RequestMapping(value = "processDiagram")public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();//流程走完的不顯示圖if (pi == null) {return;}Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();//使用流程實例ID,查詢正在執行的執行對象表,返回流程實例對象String InstanceId = task.getProcessInstanceId();List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(InstanceId).list();//得到正在執行的Activity的IdList<String> activityIds = new ArrayList<>();List<String> flows = new ArrayList<>();for (Execution exe : executions) {List<String> ids = runtimeService.getActiveActivityIds(exe.getId());activityIds.addAll(ids);}//獲取流程圖BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0);OutputStream out = null;byte[] buf = new byte[1024];int legth = 0;try {out = httpServletResponse.getOutputStream();while ((legth = in.read(buf)) != -1) {out.write(buf, 0, legth);}} finally {if (in != null) {in.close();}if (out != null) {out.close();}}}

3.6. 圖片亂碼處理

通過傳入流程ID生成當前流程的流程圖給前端,如果流程中使用到中文且生成的圖片是亂碼的,則需要進配置下字體:

package com.gblfy.flowable.config;import org.flowable.spring.SpringProcessEngineConfiguration; import org.flowable.spring.boot.EngineConfigurationConfigurer; import org.springframework.context.annotation.Configuration;/*** @Author: gblfy* @Description: 為放置生成的流程圖中中文亂碼* @Date: Create in 2019/11/03 10:26*/ @Configuration public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {@Overridepublic void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) {springProcessEngineConfiguration.setActivityFontName("宋體");springProcessEngineConfiguration.setLabelFontName("宋體");springProcessEngineConfiguration.setAnnotationFontName("宋體");} }

四、啟動項目,初始化表結構

五、測試驗證

5.1. 創建一個流程:

訪問:http://localhost:80/expense/add?userId=123&money=123321

返回:提交成功.流程Id為:2b29876c-fde9-11e9-b75f-f8a2d6bfea5a

5.2. 查詢待辦列表:

訪問:http://localhost:80/expense/list?userId=123

輸出:Task[id=2b30da72-fde9-11e9-b75f-f8a2d6bfea5a, name=出差報銷]

5.3. 同意:

? 注意 : 帶的是taskid

訪問:http://localhost:80/expense/apply?taskId=2b30da72-fde9-11e9-b75f-f8a2d6bfea5a

返回:processed ok!

5.4. 生成流程圖:

訪問: http://localhost:80/expense/processDiagram?processId=2b29876c-fde9-11e9-b75f-f8a2d6bfea5a

項目源碼地址:

碼云鏈接:
https://gitee.com/gb_90/springboot-flowable

Gitlab鏈接:
https://gitlab.com/gb-heima/springboot-flowable

總結

以上是生活随笔為你收集整理的Springboot-Flowable 快速开发工作流的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。