• SpringBoot整合Flowable工作流引擎框架


    Flowable工作流引擎框架介绍

    • 一个Java编写的轻量级业务流程引擎,为开发人员、系统管理员和业务用户提供工作流和业务流程管理(BPM)平台。
    • 不仅包括BPMN,还有DMN决策表和CMMN Case管理引擎,并且有自己的用户管理、微服务API等一系列功能,是一个服务平台。
    • 可用于部署BPMN 2.0流程定义,创建这些流程定义的流程实例,进行查询,访问运行中或历史的流程实例与相关数据。
    • Flowable源自Activiti,Flowable功能比activiti更强大,Flowable很多设计与实现,与Activiti相同的。

    官方手册:Flowable BPMN 用户手册 (v 6.3.0)

    设计流程图

    把flowable-ui里面wars下的两个war包拷贝到tomcat的webapps文件夹中,然后启动tomcat

    运行成功在浏览器输入 http://localhost:8080/flowable-ui/,进入flowable-ui界面

    初始用户名admin,初始密码test

    在此图形化界面设计流程图,可以导出为.bpmn20.xml文件

    快速开始

    导入依赖

    1. <dependency>
    2. <groupId>org.flowablegroupId>
    3. <artifactId>flowable-spring-boot-starterartifactId>
    4. <version>6.3.0version>
    5. dependency>

    安装插件

    在IDEA安装 Flowable BPMN visualizer 插件,可以把.bpmn20.xml文件可视化的展示。

    配置文件

    1. spring:
    2. datasource:
    3. url: jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useSSL=false&nullCatalogMeansCurrent=true
    4. username: root
    5. password: password
    6. driver-class-name: com.mysql.cj.jdbc.Driver
    7. flowable:
    8. standalone:
    9. server:
    10. enabled: false # standalone 模式
    11. async-executor-activate: false # 关闭定时任务JOB
    12. idm:
    13. enabled: false # 检测身份信息
    14. database-schema-update: true # 没有数据库表的时候生成数据库表

    flowable数据库必须存在(数据库名称任意),当flowable里面没有表的时候,项目运行会自动创建数据库。

    配置类

    1. import org.flowable.spring.SpringProcessEngineConfiguration;
    2. import org.flowable.spring.boot.EngineConfigurationConfigurer;
    3. import org.springframework.context.annotation.Configuration;
    4. @Configuration
    5. public class FlowableConfig implements EngineConfigurationConfigurer {
    6. @Override
    7. public void configure(SpringProcessEngineConfiguration engineConfiguration) {
    8. engineConfiguration.setActivityFontName("宋体");
    9. engineConfiguration.setLabelFontName("宋体");
    10. engineConfiguration.setAnnotationFontName("宋体");
    11. }
    12. }

    设计流程图

    在flowable-ui进行流程设计

    把流程图文件下载到本地,在resources目录下创建processes目录,在此目录下防止流程图文件

    SpringBoot项目中processes目录下的流程图会自动部署。

    人物

    • 发起流程人:多啦A
    • 组长:多啦B
    • 老板:多啦C
    • 经理:多啦D

    controller

    1. import org.flowable.engine.RuntimeService;
    2. import org.flowable.engine.TaskService;
    3. import org.flowable.engine.runtime.ProcessInstance;
    4. import org.flowable.task.api.Task;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.web.bind.annotation.GetMapping;
    7. import org.springframework.web.bind.annotation.PathVariable;
    8. import org.springframework.web.bind.annotation.RestController;
    9. import java.util.HashMap;
    10. import java.util.List;
    11. import java.util.Map;
    12. @RestController
    13. public class BXController {
    14. @Autowired
    15. private RuntimeService runtimeService;
    16. @Autowired
    17. private TaskService taskService;
    18. /**
    19. * 创建流程实例
    20. */
    21. @GetMapping("/createInstance/{username}/{money}")
    22. public String createInstance(@PathVariable String username, @PathVariable Integer money) {
    23. // 创建流程要携带的参数
    24. Map variables = new HashMap<>();
    25. variables.put("people", username);// 报销申请人
    26. variables.put("reason", "出差");// 报销原因
    27. variables.put("money", money);// 报销金额
    28. ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("报销申请", variables);
    29. // 输出相关的流程实例信息
    30. System.out.println("流程实例的ID:" + processInstance.getId());// 流程实例的Id --> 5001
    31. System.out.println("流程创建成功");
    32. return username + "创建流程实例成功";
    33. }
    34. /**
    35. * 组长同意
    36. */
    37. @GetMapping("/agree/zz/{username}")
    38. public String completeTaskZZ(@PathVariable String username) {
    39. List l = taskService.createTaskQuery()
    40. .processDefinitionKey("报销申请")
    41. .taskAssignee(username)
    42. .list();
    43. Task task = l.get(0);
    44. Map variable = new HashMap<>();
    45. variable.put("zzAgree", true);
    46. // 完成任务
    47. taskService.complete(task.getId(), variable);
    48. System.out.println(username + "同意请假");
    49. return "组长同意";
    50. }
    51. /**
    52. * 经理同意
    53. */
    54. @GetMapping("/agree/jl/{username}")
    55. public String completeTaskJL(@PathVariable String username) {
    56. List l = taskService.createTaskQuery()
    57. .processDefinitionKey("报销申请")
    58. .taskAssignee(username)
    59. .list();
    60. Task task = l.get(0);
    61. Map variable = new HashMap<>();
    62. variable.put("jlAgree", true);
    63. // 完成任务
    64. taskService.complete(task.getId(), variable);
    65. System.out.println(username + "同意请假");
    66. return "经理同意";
    67. }
    68. /**
    69. * 老板同意
    70. */
    71. @GetMapping("/agree/lb/{username}")
    72. public String completeTask(@PathVariable String username) {
    73. List l = taskService.createTaskQuery()
    74. .processDefinitionKey("报销申请")
    75. .taskAssignee(username)
    76. .list();
    77. Task task = l.get(0);
    78. Map variable = new HashMap<>();
    79. variable.put("lbAgree", true);
    80. // 完成任务
    81. taskService.complete(task.getId(), variable);
    82. System.out.println(username + "同意请假");
    83. return "老板同意";
    84. }
    85. /**
    86. * 组长拒绝
    87. */
    88. @GetMapping("/reject/zz/{username}")
    89. public String rejectTask(@PathVariable String username) {
    90. List l = taskService.createTaskQuery()
    91. .processDefinitionKey("报销申请")
    92. .taskAssignee(username)
    93. .list();
    94. Task task = l.get(0);
    95. Map variable = new HashMap<>();
    96. variable.put("zzAgree", false);
    97. // 完成任务
    98. taskService.complete(task.getId(), variable);
    99. System.out.println(username + "拒绝请假");
    100. return "组长拒绝";
    101. }
    102. /**
    103. * 经理拒绝
    104. */
    105. @GetMapping("/reject/jl/{username}")
    106. public String rejectTaskJL(@PathVariable String username) {
    107. List l = taskService.createTaskQuery()
    108. .processDefinitionKey("报销申请")
    109. .taskAssignee(username)
    110. .list();
    111. Task task = l.get(0);
    112. Map variable = new HashMap<>();
    113. variable.put("jlAgree", false);
    114. // 完成任务
    115. taskService.complete(task.getId(), variable);
    116. System.out.println(username + "拒绝请假");
    117. return "经理拒绝";
    118. }
    119. /**
    120. * 老板拒绝
    121. */
    122. @GetMapping("/reject/lb/{username}")
    123. public String rejectTaskLB(@PathVariable String username) {
    124. List l = taskService.createTaskQuery()
    125. .processDefinitionKey("报销申请")
    126. .taskAssignee(username)
    127. .list();
    128. Task task = l.get(0);
    129. Map variable = new HashMap<>();
    130. variable.put("lbAgree", false);
    131. // 完成任务
    132. taskService.complete(task.getId(), variable);
    133. System.out.println(username + "拒绝请假");
    134. return "老板拒绝";
    135. }
    136. }

    测试

    测试样例一

    创建流程实例:http://localhost:8081/createInstance/多啦A梦/400,会返回流程实例ID

    根据流程实例ID查询流程执行:http://localhost:8081/processDiagram/{processId}

    注意:必须设置配置类设置字体,不然流程图上的文字会展示乱码

    组长同意:http://localhost:8081/agree/zz/多啦B梦

    经理拒绝:http://localhost:8081/reject/jl/多啦D梦 ,流程执行结束

    测试样例二

    创建流程实例:http://localhost:8081/createInstance/多啦A梦/700,会返回流程实例ID

    组长同意:http://localhost:8081/agree/zz/多啦B梦

    老板同意:http://localhost:8081/agree/lb/多啦C梦,流程结束

  • 相关阅读:
    1.什么是软件工程?它目标和内容是什么?2.软件开发中有哪几种过程模型?哪些适用于面向对象的软件开发?
    你可能从未使用过的13个Python特性
    如何使用 TypeScript 编写“ Hello World “程序
    【Proteus仿真】【51单片机】水箱液位监控系统
    在微信公众号怎么添加电子优惠券
    arm 点灯实验代码以及现象
    【随想】每日两题Day.4
    c#找到是哪个函数调用当前函数
    三个案例带你入门Thymeleaf。模板引擎,终于不用在后端拼接前端代码了。
    Linux 入门篇
  • 原文地址:https://blog.csdn.net/m0_56750901/article/details/126625790