Flowable是一个用java语言写的轻量级工作流引擎。

1、相关依赖

  1. <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
  2. <dependency>
  3. <groupId>io.springfox</groupId>
  4. <artifactId>springfox-swagger2</artifactId>
  5. <version>2.9.2</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
  8. <dependency>
  9. <groupId>io.springfox</groupId>
  10. <artifactId>springfox-swagger-ui</artifactId>
  11. <version>2.9.2</version>
  12. </dependency>
  13. <!-- https://mvnrepository.com/artifact/com.github.xiaoymin/swagger-bootstrap-ui -->
  14. <dependency>
  15. <groupId>com.github.xiaoymin</groupId>
  16. <artifactId>swagger-bootstrap-ui</artifactId>
  17. <version>1.8.5</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>com.alibaba</groupId>
  21. <artifactId>druid-spring-boot-starter</artifactId>
  22. <version>1.1.13</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>mysql</groupId>
  26. <artifactId>mysql-connector-java</artifactId>
  27. <version>8.0.19</version>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.flowable</groupId>
  31. <artifactId>flowable-spring-boot-starter</artifactId>
  32. <version>6.5.0</version>
  33. </dependency>

2、flowable以及数据库的配置

  1. mysql:
  2. url: jdbc:mysql:///test?serverTimezone=UTC
  3. username: root
  4. password: 123456
  5. driverClassName: com.mysql.cj.jdbc.Driver
  6. spring:
  7. application:
  8. name: ServiceActiviti
  9. datasource:
  10. type: com.alibaba.druid.pool.DruidDataSource
  11. url: ${mysql.url}
  12. driver-class-name: ${mysql.driverClassName}
  13. username: ${mysql.username}
  14. password: ${mysql.password}
  15. druid: # #
  16. url: ${mysql.url}
  17. username: ${mysql.username}
  18. password: ${mysql.password}
  19. driver-class-name: ${mysql.driverClassName}
  20. initial-size: 10
  21. max-active: 200
  22. min-idle: 10
  23. max-wait: 60000
  24. pool-prepared-statements: false
  25. validation-query: SELECT 1 FROM DUAL
  26. test-on-borrow: false
  27. test-on-return: false
  28. test-while-idle: true
  29. time-between-eviction-runs-millis: 60000
  30. min-evictable-idle-time-millis: 30000
  31. max-pool-prepared-statement-per-connection-size: 20
  32. aop-patterns: com.msyyt.crm.activity.*
  33. filter: # 状态监控
  34. stat:
  35. enabled: true
  36. db-type: mysql
  37. log-slow-sql: true
  38. slow-sql-millis: 2000
  39. web-stat-filter: # 监控过滤器
  40. enabled: true #是否启用 默认true
  41. exclusions:
  42. - '*.js'
  43. - '*.gif'
  44. - '*.jpg'
  45. - '*.png'
  46. - '*.css'
  47. - '*.ico'
  48. - /druid/*
  49. stat-view-servlet: # druid 监控页面
  50. enabled: true
  51. url-pattern: /druid/*
  52. reset-enable: false
  53. allow: # 白名单
  54. deny: # 黑名单
  55. login-username: admin
  56. login-password: admin
  57. # 工作流
  58. flowable:
  59. #关闭定时任务JOB
  60. async-executor-activate: false
  61. # 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。
  62. database-schema-update: true

3、运行项目生成数据库表

image.png

4、定义标准的BPMN流程文件ExpenseProcess.bpmn20.xml放至resource目录下新建processes目录下

image.png

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
  4. xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
  5. typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath"
  6. targetNamespace="http://www.flowable.org/processdef">
  7. <process id="Expense" name="ExpenseProcess" isExecutable="true">
  8. <documentation>报销流程</documentation>
  9. <startEvent id="start" name="开始"></startEvent>
  10. <userTask id="fillTask" name="出差报销" flowable:assignee="${taskUser}">
  11. <extensionElements>
  12. <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler">
  13. <![CDATA[false]]></modeler:initiator-can-complete>
  14. </extensionElements>
  15. </userTask>
  16. <exclusiveGateway id="judgeTask"></exclusiveGateway>
  17. <userTask id="directorTak" name="经理审批">
  18. <extensionElements>
  19. <flowable:taskListener event="create"
  20. class="com.fcant.service_flowable.handler.ManagerTaskHandler"></flowable:taskListener>
  21. </extensionElements>
  22. </userTask>
  23. <userTask id="bossTask" name="老板审批">
  24. <extensionElements>
  25. <flowable:taskListener event="create"
  26. class="com.fcant.service_flowable.handler.BossTaskHandler"></flowable:taskListener>
  27. </extensionElements>
  28. </userTask>
  29. <endEvent id="end" name="结束"></endEvent>
  30. <sequenceFlow id="directorNotPassFlow" name="驳回" sourceRef="directorTak" targetRef="fillTask">
  31. <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='驳回'}]]></conditionExpression>
  32. </sequenceFlow>
  33. <sequenceFlow id="bossNotPassFlow" name="驳回" sourceRef="bossTask" targetRef="fillTask">
  34. <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='驳回'}]]></conditionExpression>
  35. </sequenceFlow>
  36. <sequenceFlow id="flow1" sourceRef="start" targetRef="fillTask"></sequenceFlow>
  37. <sequenceFlow id="flow2" sourceRef="fillTask" targetRef="judgeTask"></sequenceFlow>
  38. <sequenceFlow id="judgeMore" name="大于500元" sourceRef="judgeTask" targetRef="bossTask">
  39. <conditionExpression xsi:type="tFormalExpression"><![CDATA[${money > 500}]]></conditionExpression>
  40. </sequenceFlow>
  41. <sequenceFlow id="bossPassFlow" name="通过" sourceRef="bossTask" targetRef="end">
  42. <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通过'}]]></conditionExpression>
  43. </sequenceFlow>
  44. <sequenceFlow id="directorPassFlow" name="通过" sourceRef="directorTak" targetRef="end">
  45. <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通过'}]]></conditionExpression>
  46. </sequenceFlow>
  47. <sequenceFlow id="judgeLess" name="小于500元" sourceRef="judgeTask" targetRef="directorTak">
  48. <conditionExpression xsi:type="tFormalExpression"><![CDATA[${money <= 500}]]></conditionExpression>
  49. </sequenceFlow>
  50. </process>
  51. <bpmndi:BPMNDiagram id="BPMNDiagram_Expense">
  52. <bpmndi:BPMNPlane bpmnElement="Expense" id="BPMNPlane_Expense">
  53. <bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">
  54. <omgdc:Bounds height="30.0" width="30.0" x="285.0" y="135.0"></omgdc:Bounds>
  55. </bpmndi:BPMNShape>
  56. <bpmndi:BPMNShape bpmnElement="fillTask" id="BPMNShape_fillTask">
  57. <omgdc:Bounds height="80.0" width="100.0" x="405.0" y="110.0"></omgdc:Bounds>
  58. </bpmndi:BPMNShape>
  59. <bpmndi:BPMNShape bpmnElement="judgeTask" id="BPMNShape_judgeTask">
  60. <omgdc:Bounds height="40.0" width="40.0" x="585.0" y="130.0"></omgdc:Bounds>
  61. </bpmndi:BPMNShape>
  62. <bpmndi:BPMNShape bpmnElement="directorTak" id="BPMNShape_directorTak">
  63. <omgdc:Bounds height="80.0" width="100.0" x="735.0" y="110.0"></omgdc:Bounds>
  64. </bpmndi:BPMNShape>
  65. <bpmndi:BPMNShape bpmnElement="bossTask" id="BPMNShape_bossTask">
  66. <omgdc:Bounds height="80.0" width="100.0" x="555.0" y="255.0"></omgdc:Bounds>
  67. </bpmndi:BPMNShape>
  68. <bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end">
  69. <omgdc:Bounds height="28.0" width="28.0" x="771.0" y="281.0"></omgdc:Bounds>
  70. </bpmndi:BPMNShape>
  71. <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
  72. <omgdi:waypoint x="315.0" y="150.0"></omgdi:waypoint>
  73. <omgdi:waypoint x="405.0" y="150.0"></omgdi:waypoint>
  74. </bpmndi:BPMNEdge>
  75. <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
  76. <omgdi:waypoint x="505.0" y="150.16611295681062"></omgdi:waypoint>
  77. <omgdi:waypoint x="585.4333333333333" y="150.43333333333334"></omgdi:waypoint>
  78. </bpmndi:BPMNEdge>
  79. <bpmndi:BPMNEdge bpmnElement="judgeLess" id="BPMNEdge_judgeLess">
  80. <omgdi:waypoint x="624.5530726256983" y="150.44692737430168"></omgdi:waypoint>
  81. <omgdi:waypoint x="735.0" y="150.1392757660167"></omgdi:waypoint>
  82. </bpmndi:BPMNEdge>
  83. <bpmndi:BPMNEdge bpmnElement="directorNotPassFlow" id="BPMNEdge_directorNotPassFlow">
  84. <omgdi:waypoint x="785.0" y="110.0"></omgdi:waypoint>
  85. <omgdi:waypoint x="785.0" y="37.0"></omgdi:waypoint>
  86. <omgdi:waypoint x="455.0" y="37.0"></omgdi:waypoint>
  87. <omgdi:waypoint x="455.0" y="110.0"></omgdi:waypoint>
  88. </bpmndi:BPMNEdge>
  89. <bpmndi:BPMNEdge bpmnElement="bossPassFlow" id="BPMNEdge_bossPassFlow">
  90. <omgdi:waypoint x="655.0" y="295.0"></omgdi:waypoint>
  91. <omgdi:waypoint x="771.0" y="295.0"></omgdi:waypoint>
  92. </bpmndi:BPMNEdge>
  93. <bpmndi:BPMNEdge bpmnElement="judgeMore" id="BPMNEdge_judgeMore">
  94. <omgdi:waypoint x="605.4340277777778" y="169.56597222222223"></omgdi:waypoint>
  95. <omgdi:waypoint x="605.1384083044983" y="255.0"></omgdi:waypoint>
  96. </bpmndi:BPMNEdge>
  97. <bpmndi:BPMNEdge bpmnElement="directorPassFlow" id="BPMNEdge_directorPassFlow">
  98. <omgdi:waypoint x="785.0" y="190.0"></omgdi:waypoint>
  99. <omgdi:waypoint x="785.0" y="281.0"></omgdi:waypoint>
  100. </bpmndi:BPMNEdge>
  101. <bpmndi:BPMNEdge bpmnElement="bossNotPassFlow" id="BPMNEdge_bossNotPassFlow">
  102. <omgdi:waypoint x="555.0" y="295.0"></omgdi:waypoint>
  103. <omgdi:waypoint x="455.0" y="295.0"></omgdi:waypoint>
  104. <omgdi:waypoint x="455.0" y="190.0"></omgdi:waypoint>
  105. </bpmndi:BPMNEdge>
  106. </bpmndi:BPMNPlane>
  107. </bpmndi:BPMNDiagram>
  108. </definitions>

5、添加代理类

A.ManagerTaskHandler.java

  1. package com.fcant.service_flowable.handler;
  2. import org.flowable.engine.delegate.TaskListener;
  3. import org.flowable.task.service.delegate.DelegateTask;
  4. /**
  5. * ManagerTaskHandler
  6. * <p>
  7. * encoding:UTF-8
  8. *
  9. * @author Fcant 下午 19:42 2020/8/2/0002
  10. */
  11. public class ManagerTaskHandler implements TaskListener {
  12. @Override
  13. public void notify(DelegateTask delegateTask) {
  14. delegateTask.setAssignee("经理");
  15. }
  16. }

B.BossTaskHandler.java

  1. package com.fcant.service_flowable.handler;
  2. import org.flowable.engine.delegate.TaskListener;
  3. import org.flowable.task.service.delegate.DelegateTask;
  4. /**
  5. * BossTaskHandler
  6. * <p>
  7. * encoding:UTF-8
  8. *
  9. * @author Fcant 下午 19:43 2020/8/2/0002
  10. */
  11. public class BossTaskHandler implements TaskListener {
  12. @Override
  13. public void notify(DelegateTask delegateTask) {
  14. delegateTask.setAssignee("老板");
  15. }
  16. }

C.以上代理类可以使用标签进行替换

  1. <userTask id="holidayApprovedTask" name="Holiday approved" flowable:assignee="${employee}"/>

D.代理类完成后需要在BPMN进行类指定

image.png

6、业务逻辑层以及测试接口

A.ExpenseService.java

  1. package com.fcant.service_flowable.service;
  2. import javax.servlet.http.HttpServletResponse;
  3. /**
  4. * ExpenseService
  5. * <p>
  6. * encoding:UTF-8
  7. *
  8. * @author Fcant 下午 20:10 2020/8/2/0002
  9. */
  10. public interface ExpenseService {
  11. /**
  12. * 添加报销
  13. *
  14. * @param userId 用户Id
  15. * @param money 报销金额
  16. * @param descption 描述
  17. * @return String
  18. * @author Fcant 下午 20:02 2020/8/2/0002
  19. */
  20. public String addExpense(String userId, Integer money, String descption);
  21. /**
  22. * 获取审批管理列表
  23. *
  24. * @param userId 对应用户的审批列表
  25. * @return Object
  26. * @author Fcant 下午 20:01 2020/8/2/0002
  27. */
  28. public Object list(String userId);
  29. /**
  30. * 批准
  31. *
  32. * @param taskId 批准的工作流ID
  33. * @return
  34. * @author Fcant 下午 20:01 2020/8/2/0002
  35. */
  36. public String apply(String taskId);
  37. /**
  38. * 拒绝
  39. *
  40. * @param taskId 拒绝的工作流ID
  41. * @return String
  42. * @author Fcant 下午 20:00 2020/8/2/0002
  43. */
  44. public String reject(String taskId);
  45. /**
  46. * 生成流程图
  47. *
  48. * @param processId 任务ID
  49. * @author Fcant 下午 19:59 2020/8/2/0002
  50. */
  51. public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception;
  52. }

B.ExpenseServiceImpl.java

  1. package com.fcant.service_flowable.service.impl;
  2. import com.fcant.service_flowable.service.ExpenseService;
  3. import org.flowable.bpmn.model.BpmnModel;
  4. import org.flowable.engine.*;
  5. import org.flowable.engine.runtime.Execution;
  6. import org.flowable.engine.runtime.ProcessInstance;
  7. import org.flowable.image.ProcessDiagramGenerator;
  8. import org.flowable.task.api.Task;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Service;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.InputStream;
  13. import java.io.OutputStream;
  14. import java.util.ArrayList;
  15. import java.util.HashMap;
  16. import java.util.List;
  17. /**
  18. * ExpenseServiceImpl
  19. * <p>
  20. * encoding:UTF-8
  21. *
  22. * @author Fcant 下午 20:10 2020/8/2/0002
  23. */
  24. @Service
  25. public class ExpenseServiceImpl implements ExpenseService {
  26. @Autowired
  27. private RuntimeService runtimeService;
  28. @Autowired
  29. private TaskService taskService;
  30. @Autowired
  31. private RepositoryService repositoryService;
  32. @Autowired
  33. private ProcessEngine processEngine;
  34. /**
  35. * 添加报销
  36. *
  37. * @param userId 用户Id
  38. * @param money 报销金额
  39. * @param descption 描述
  40. * @return String
  41. * @author Fcant 下午 20:02 2020/8/2/0002
  42. */
  43. @Override
  44. public String addExpense(String userId, Integer money, String descption) {
  45. //启动流程
  46. HashMap<String, Object> map = new HashMap<>();
  47. map.put("taskUser", userId);
  48. map.put("money", money);
  49. ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Expense", map);
  50. return "提交成功.流程Id为:" + processInstance.getId();
  51. }
  52. /**
  53. * 获取审批管理列表
  54. *
  55. * @param userId 对应用户的审批列表
  56. * @return Object
  57. * @author Fcant 下午 20:01 2020/8/2/0002
  58. */
  59. @Override
  60. public Object list(String userId) {
  61. List<Task> tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();
  62. for (Task task : tasks) {
  63. System.out.println(task.toString());
  64. }
  65. return tasks.toArray().toString();
  66. }
  67. /**
  68. * 批准
  69. *
  70. * @param taskId 批准的工作流ID
  71. * @return
  72. * @author Fcant 下午 20:01 2020/8/2/0002
  73. */
  74. @Override
  75. public String apply(String taskId) {
  76. Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
  77. if (task == null) {
  78. throw new RuntimeException("流程不存在");
  79. }
  80. //通过审核
  81. HashMap<String, Object> map = new HashMap<>();
  82. map.put("outcome", "通过");
  83. taskService.complete(taskId, map);
  84. return "processed ok!";
  85. }
  86. /**
  87. * 拒绝
  88. *
  89. * @param taskId 拒绝的工作流ID
  90. * @return String
  91. * @author Fcant 下午 20:00 2020/8/2/0002
  92. */
  93. @Override
  94. public String reject(String taskId) {
  95. HashMap<String, Object> map = new HashMap<>();
  96. map.put("outcome", "驳回");
  97. taskService.complete(taskId, map);
  98. return "reject";
  99. }
  100. /**
  101. * 生成流程图
  102. *
  103. * @param processId 任务ID
  104. * @author Fcant 下午 19:59 2020/8/2/0002
  105. */
  106. @Override
  107. public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
  108. ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
  109. //流程走完的不显示图
  110. if (pi == null) {
  111. return;
  112. }
  113. Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
  114. //使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
  115. String InstanceId = task.getProcessInstanceId();
  116. List<Execution> executions = runtimeService
  117. .createExecutionQuery()
  118. .processInstanceId(InstanceId)
  119. .list();
  120. //得到正在执行的Activity的Id
  121. List<String> activityIds = new ArrayList<>();
  122. List<String> flows = new ArrayList<>();
  123. for (Execution exe : executions) {
  124. List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
  125. activityIds.addAll(ids);
  126. }
  127. //获取流程图
  128. BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
  129. ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
  130. ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
  131. InputStream in = diagramGenerator.generateDiagram(bpmnModel,
  132. "png", activityIds, flows, engconf.getActivityFontName(),
  133. engconf.getLabelFontName(), engconf.getAnnotationFontName(),
  134. engconf.getClassLoader(), 1.0, true);
  135. OutputStream out = null;
  136. byte[] buf = new byte[1024];
  137. int legth = 0;
  138. try {
  139. out = httpServletResponse.getOutputStream();
  140. while ((legth = in.read(buf)) != -1) {
  141. out.write(buf, 0, legth);
  142. }
  143. } finally {
  144. if (in != null) {
  145. in.close();
  146. }
  147. if (out != null) {
  148. out.close();
  149. }
  150. }
  151. }
  152. }

C.ExpenseController.java

  1. package com.fcant.service_flowable.controller;
  2. import com.fcant.service_flowable.service.ExpenseService;
  3. import io.swagger.annotations.Api;
  4. import io.swagger.annotations.ApiOperation;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.ResponseBody;
  9. import javax.servlet.http.HttpServletResponse;
  10. /**
  11. * ExpenseController
  12. * <p>
  13. * encoding:UTF-8
  14. *
  15. * @author Fcant 下午 19:46 2020/8/2/0002
  16. */
  17. @Api(tags = "expense",value = "工作流控制器")
  18. @Controller
  19. @RequestMapping("/expense")
  20. public class ExpenseController {
  21. @Autowired
  22. ExpenseService expenseService;
  23. /**
  24. * 添加报销
  25. *
  26. * @param userId 用户Id
  27. * @param money 报销金额
  28. * @param descption 描述
  29. * @return String
  30. * @author Fcant 下午 20:02 2020/8/2/0002
  31. */
  32. @ApiOperation(value="添加报销")
  33. @RequestMapping(value = "/add")
  34. @ResponseBody
  35. public String addExpense(String userId, Integer money, String descption) {
  36. return expenseService.addExpense(userId, money, descption);
  37. }
  38. /**
  39. * 获取审批管理列表
  40. *
  41. * @param userId 对应用户的审批列表
  42. * @return Object
  43. * @author Fcant 下午 20:01 2020/8/2/0002
  44. */
  45. @ApiOperation(value="获取审批管理列表")
  46. @RequestMapping(value = "/list")
  47. @ResponseBody
  48. public Object list(String userId) {
  49. return expenseService.list(userId);
  50. }
  51. /**
  52. * 批准
  53. *
  54. * @param taskId 批准的工作流ID
  55. * @return
  56. * @author Fcant 下午 20:01 2020/8/2/0002
  57. */
  58. @ApiOperation(value="批准")
  59. @RequestMapping(value = "/apply")
  60. @ResponseBody
  61. public String apply(String taskId) {
  62. expenseService.apply(taskId);
  63. return "processed ok!";
  64. }
  65. /**
  66. * 拒绝
  67. *
  68. * @param taskId 拒绝的工作流ID
  69. * @return String
  70. * @author Fcant 下午 20:00 2020/8/2/0002
  71. */
  72. @ApiOperation(value="拒绝")
  73. @ResponseBody
  74. @RequestMapping(value = "/reject")
  75. public String reject(String taskId) {
  76. expenseService.reject(taskId);
  77. return "reject";
  78. }
  79. /**
  80. * 生成流程图
  81. *
  82. * @param processId 任务ID
  83. * @author Fcant 下午 19:59 2020/8/2/0002
  84. */
  85. @ApiOperation(value="生成流程图")
  86. @RequestMapping(value = "/processDiagram")
  87. public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
  88. expenseService.genProcessDiagram(httpServletResponse, processId);
  89. }
  90. }

7、配置生成的流图的字体(防止/解决生成流程图片的乱码问题)

  1. package com.fcant.service_flowable.config;
  2. import org.flowable.spring.SpringProcessEngineConfiguration;
  3. import org.flowable.spring.boot.EngineConfigurationConfigurer;
  4. import org.springframework.context.annotation.Configuration;
  5. /**
  6. * FlowableConfig
  7. * <p>
  8. * encoding:UTF-8
  9. *
  10. * @author Fcant 下午 19:51 2020/8/2/0002
  11. */
  12. @Configuration
  13. public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
  14. @Override
  15. public void configure(SpringProcessEngineConfiguration engineConfiguration) {
  16. engineConfiguration.setActivityFontName("宋体");
  17. engineConfiguration.setLabelFontName("宋体");
  18. engineConfiguration.setAnnotationFontName("宋体");
  19. }
  20. }

8、配置Swagger

  1. package com.fcant.service_flowable.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
  5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  6. import springfox.documentation.builders.ApiInfoBuilder;
  7. import springfox.documentation.builders.PathSelectors;
  8. import springfox.documentation.builders.RequestHandlerSelectors;
  9. import springfox.documentation.service.ApiInfo;
  10. import springfox.documentation.service.Contact;
  11. import springfox.documentation.spi.DocumentationType;
  12. import springfox.documentation.spring.web.plugins.Docket;
  13. import springfox.documentation.swagger2.annotations.EnableSwagger2;
  14. /**
  15. * SwaggerConfig
  16. * <p>
  17. * encoding:UTF-8
  18. *
  19. * @author Fcant 下午 23:41 2020/8/1/0001
  20. */
  21. @Configuration
  22. @EnableSwagger2
  23. public class SwaggerConfig implements WebMvcConfigurer {
  24. @Override
  25. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  26. registry.addResourceHandler("swagger-ui.html")
  27. .addResourceLocations("classpath:/META-INF/resources/");
  28. registry.addResourceHandler("/webjars/**")
  29. .addResourceLocations("classpath:/META-INF/resources/webjars/");
  30. }
  31. /**
  32. * @author Fcant 13:44 2019/12/5
  33. */
  34. @Bean
  35. public Docket petApi() {
  36. return new Docket(DocumentationType.SWAGGER_2)
  37. .apiInfo(apiInfo())
  38. .select()
  39. .apis(RequestHandlerSelectors.basePackage("com.fcant.service_flowable.controller"))
  40. .paths(PathSelectors.any())
  41. .build();
  42. }
  43. /**
  44. * 该套 API 说明,包含作者、简介、版本、host、服务URL
  45. * @return
  46. */
  47. private ApiInfo apiInfo() {
  48. return new ApiInfoBuilder()
  49. .title("Flowable Service API")
  50. .contact(new Contact("fcant","null","fcscanf@outlook.com"))
  51. .version("0.1")
  52. .termsOfServiceUrl("www.yuque.com/fcant")
  53. .description("Flowable Service API")
  54. .build();
  55. }
  56. }

9、启动项目,访问Swagger页面进行接口测试

image.png
image.png

参考

CSDN:采用Springboot+Flowable快速实现工作流
https://blog.csdn.net/puhaiyang/article/details/79845248