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: Flowable-ui 6.7.2下载
- 下载 Tomcat : tomcat 9 下载
把flowable-ui里面wars下的两个war包拷贝到tomcat的webapps文件夹中,然后启动tomcat
运行成功在浏览器输入 ,进入flowable-ui界面
初始用户名admin,初始密码test
在此图形化 界面设计 流程图,可以导出为.bpmn20.xml文件
快速开始
导入依赖
<!--Flowable流程引擎框架-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>.3.0</version>
</dependency>
安装插件
在IDEA安装 Flowable BPMN visualizer 插件,可以把.bpmn20.xml文件可视化的展示。
配置文件
spring:
datasource:
url: jdbc :mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useSSL=false& null CatalogMeansCurrent=true
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
flowable:
standalone:
server:
enabled: false # standalone 模式
async-executor-activate: false # 关闭定时任务JOB
idm:
enabled: false # 检测身份信息
database-schema-update: true # 没有数据库表的时候生成数据库表
flowable数据库必须存在(数据库名称任意),当flowable里面没有表的时候,项目运行会自动创建数据库。
配置类
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context. annotation .Configuration;
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
@Override
public void configure(SpringProcessEngineConfiguration engineConfiguration) {
engineConfiguration.setActivityFontName("宋体");
engineConfiguration.setLabelFontName("宋体");
engineConfiguration.setAnnotationFontName("宋体");
}
}
设计流程图
在flowable-ui进行流程设计
把流程图文件下载到本地,在resources目录下创建processes目录,在此目录下防止流程图文件
SpringBoot项目中processes目录下的流程图会自动部署。
人物
- 发起流程人:多啦 A 梦
- 组长:多啦 B 梦
- 老板:多啦 C 梦
- 经理:多啦 D 梦
controller
import org.flowable.engine. runtime Service;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util. HashMap ;
import java.util.List;
import java.util.Map;
@RestController
public class BXController {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
/**
* 创建流程实例
*/ @GetMapping("/createInstance/{username}/{money}")
public String createInstance(@PathVariable String username, @PathVariable Integer money) {
// 创建流程要携带的参数
Map <String, Object> variables = new HashMap<>();
variables.put("people", username);// 报销申请人
variables.put("reason", "出差");// 报销原因
variables.put("money", money);// 报销金额
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("报销申请", variables);
// 输出相关的流程实例信息
System.out.println("流程实例的ID:" + processInstance.getId());// 流程实例的Id -->
System.out.println("流程创建成功");
return username + "创建流程实例成功";
}
/**
* 组长同意
*/ @GetMapping("/agree/zz/{username}")
public String completeTaskZZ(@PathVariable String username) {
List<Task> l = taskService.createTaskQuery()
.processDefinitionKey("报销申请")
.taskAssignee(username)
.list();
Task task = l.get();
Map<String, Object> variable = new HashMap<>();
variable.put("zzAgree", true);
// 完成任务
taskService.complete(task.getId(), variable);
System.out.println(username + "同意请假");
return "组长同意";
}
/**
* 经理同意
*/ @GetMapping("/agree/jl/{username}")
public String completeTaskJL(@PathVariable String username) {
List<Task> l = taskService.createTaskQuery()
.processDefinitionKey("报销申请")
.taskAssignee(username)
.list();
Task task = l.get();
Map<String, Object> variable = new HashMap<>();
variable.put("jlAgree", true);
// 完成任务
taskService.complete(task.getId(), variable);
System.out.println(username + "同意请假");
return "经理同意";
}
/**
* 老板同意
*/ @GetMapping("/agree/lb/{username}")
public String completeTask(@PathVariable String username) {
List<Task> l = taskService.createTaskQuery()
.processDefinitionKey("报销申请")
.taskAssignee(username)
.list();
Task task = l.get();
Map<String, Object> variable = new HashMap<>();
variable.put("lbAgree", true);
// 完成任务
taskService.complete(task.getId(), variable);
System.out.println(username + "同意请假");
return "老板同意";
}
/**
* 组长拒绝
*/ @GetMapping("/reject/zz/{username}")
public String rejectTask(@PathVariable String username) {
List<Task> l = taskService.createTaskQuery()
.processDefinitionKey("报销申请")
.taskAssignee(username)
.list();
Task task = l.get();
Map<String, Object> variable = new HashMap<>();
variable.put("zzAgree", false);
// 完成任务
taskService.complete(task.getId(), variable);
System.out.println(username + "拒绝请假");
return "组长拒绝";
}
/**
* 经理拒绝
*/ @GetMapping("/reject/jl/{username}")
public String rejectTaskJL(@PathVariable String username) {
List<Task> l = taskService.createTaskQuery()
.processDefinitionKey("报销申请")
.taskAssignee(username)
.list();
Task task = l.get();
Map<String, Object> variable = new HashMap<>();
variable.put("jlAgree", false);
// 完成任务
taskService.complete(task.getId(), variable);
System.out.println(username + "拒绝请假");
return "经理拒绝";
}
/**
* 老板拒绝
*/ @GetMapping("/reject/lb/{username}")
public String rejectTaskLB(@PathVariable String username) {
List<Task> l = taskService.createTaskQuery()
.processDefinitionKey("报销申请")
.taskAssignee(username)
.list();
Task task = l.get();
Map<String, Object> variable = new HashMap<>();
variable.put("lbAgree", false);
// 完成任务
taskService.complete(task.getId(), variable);
System.out.println(username + "拒绝请假");
return "老板拒绝";
}
}
测试
测试样例一
创建流程实例: 多啦A梦/400 ,会返回流程实例ID
根据流程实例ID查询流程执行: {processId}
注意:必须设置配置类设置字体,不然流程图上的文字会展示乱码
组长同意: 多啦B梦
经理拒绝: 多啦D梦 ,流程执行结束
测试样例二
创建流程实例: 多啦A梦/700 ,会返回流程实例ID
组长同意: 多啦B梦
老板同意: 多啦C梦 ,流程结束