1.创建springboot项目
1.1 引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lidoudou</groupId>
<artifactId>FlowableTest</artifactId>
<version>1.0</version>
<properties>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.7.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<!--springboot程序测试依赖,如果是自动创建项目默认添加-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
1.2 配置yml
spring:
datasource:
username: root
password: root
url: jdbc:mysql:///flowable?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&autoReconnect=true
driver-class-name: com.mysql.cj.jdbc.Driver
server:
port: 8080
1.3 启动项目
附件:项目目录
启动成功后会自动帮我们创建flowable所需要的表格
2.画流程图
2.1 安装IDEA 插件 Flowable BPMN visualizer
2.2 开始画一个简单的流程图
<?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:xsd="http://www.w3.org/2001/XMLSchema" 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="ask_for_leave" name="ask_for_leave" isExecutable="true">
<userTask id="leaveTask" name="请假" flowable:assignee="#{leaveTask}"/>
<userTask id="zuzhangTask" name="组长审核" flowable:assignee="#{zuzhangTask}"/>
<userTask id="managerTask" name="经理审核" flowable:assignee="#{managerTask}"/>
<exclusiveGateway id="managerJudgeTask"/>
<exclusiveGateway id="zuzhangJudeTask"/>
<endEvent id="endLeave" name="结束"/>
<startEvent id="startLeave" name="开始"/>
<sequenceFlow id="flowStart" sourceRef="startLeave" targetRef="leaveTask"/>
<sequenceFlow id="modeFlow" sourceRef="leaveTask" targetRef="zuzhangTask"/>
<sequenceFlow id="zuzhang_go" sourceRef="zuzhangJudeTask" targetRef="managerTask" name="通过">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${checkResult=='通过'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="zuzhang_reject" sourceRef="zuzhangJudeTask" targetRef="sendMail" name="拒绝">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${checkResult=='拒绝'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="jugdeFlow" sourceRef="managerTask" targetRef="managerJudgeTask"/>
<sequenceFlow id="flowEnd" name="通过" sourceRef="managerJudgeTask" targetRef="endLeave">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${checkResult=='通过'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="rejectFlow" name="拒绝" sourceRef="managerJudgeTask" targetRef="sendMail">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${checkResult=='拒绝'}]]></conditionExpression>
</sequenceFlow>
<serviceTask id="sendMail" flowable:exclusive="true" name="发送失败提示" isForCompensation="true" flowable:class="com.lidoudou.Controller.AskForLeaveFail"/>
<sequenceFlow id="endFlow" sourceRef="sendMail" targetRef="askForLeaveFail"/>
<endEvent id="askForLeaveFail" name="请假失败"/>
<sequenceFlow id="zuzhangTask_zuzhangJudeTask" sourceRef="zuzhangTask" targetRef="zuzhangJudeTask"/>
</process>
</definitions>
2.3 编写controller 开始测试
package com.lidoudou.Controller;
import lombok.extern.log4j.Log4j2;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
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.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @program: FlowableTest
* @description:
* @author: ldd
* @create: 2024-05-10 15:42
**/
@RestController
@Log4j2
public class FlowController {
@Autowired
RuntimeService runtimeService;
@Autowired
TaskService taskService;
@Autowired
RepositoryService repositoryService;
@Autowired
ProcessEngine processEngine;
@GetMapping("/pic")
public void showPic(HttpServletResponse resp, String processId) throws Exception {
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
if (pi == null) {
return;
}
List<Execution> executions = runtimeService
.createExecutionQuery()
.processInstanceId(processId)
.list();
List<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, false);
OutputStream out = null;
byte[] buf = new byte[1024];
int legth = 0;
try {
out = resp.getOutputStream();
while ((legth = in.read(buf)) != -1) {
out.write(buf, 0, legth);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
String staffId = "1000";
/**
* 开启一个流程
*/
@GetMapping("/begin")
public void askForLeave() {
HashMap<String, Object> map = new HashMap<>();
map.put("leaveTask", staffId);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ask_for_leave", map);
runtimeService.setVariable(processInstance.getId(), "name", "javaboy");
runtimeService.setVariable(processInstance.getId(), "reason", "休息一下");
runtimeService.setVariable(processInstance.getId(), "days", 10);
System.out.println(processInstance.getId());
}
String zuzhangId = "90";
/**
* 提交给组长审批
*/
@GetMapping("/submitToZuzhang")
public void submitToZuzhang() {
//员工查找到自己的任务,然后提交给组长审批
List<Task> list = taskService.createTaskQuery().taskAssignee(staffId).orderByTaskId().desc().list();
for (Task task : list) {
log.info("任务 ID:{};任务处理人:{};任务是否挂起:{}", task.getId(), task.getAssignee(), task.isSuspended());
Map<String, Object> map = new HashMap<>();
//提交给组长的时候,需要指定组长的 id
map.put("zuzhangTask", zuzhangId);
taskService.complete(task.getId(), map);
}
}
String managerId = "80";
/**
* 组长审批-批准
*/
@GetMapping("/zuZhangApprove")
void zuZhangApprove() {
List<Task> list = taskService.createTaskQuery().taskAssignee(zuzhangId).orderByTaskId().desc().list();
for (Task task : list) {
log.info("组长 {} 在审批 {} 任务", task.getAssignee(), task.getId());
Map<String, Object> map = new HashMap<>();
//组长审批的时候,如果是同意,需要指定经理的 id
map.put("managerTask", managerId);
map.put("checkResult", "通过");
taskService.complete(task.getId(), map);
}
}
/**
* 组长审批-拒绝
*/
@GetMapping("/zuZhangReject")
public void zuZhangReject() {
List<Task> list = taskService.createTaskQuery().taskAssignee(zuzhangId).orderByTaskId().desc().list();
for (Task task : list) {
log.info("组长 {} 在审批 {} 任务", task.getAssignee(), task.getId());
Map<String, Object> map = new HashMap<>();
//组长审批的时候,如果是拒绝,就不需要指定经理的 id
map.put("checkResult", "拒绝");
taskService.complete(task.getId(), map);
}
}
/**
* 经理审批自己的任务-批准
*/
@GetMapping("/managerApprove")
public void managerApprove() {
List<Task> list = taskService.createTaskQuery().taskAssignee(managerId).orderByTaskId().desc().list();
for (Task task : list) {
log.info("经理 {} 在审批 {} 任务", task.getAssignee(), task.getId());
Map<String, Object> map = new HashMap<>();
map.put("checkResult", "通过");
taskService.complete(task.getId(), map);
}
}
/**
* 经理审批自己的任务-拒绝
*/
@GetMapping("/managerReject")
public void managerReject() {
List<Task> list = taskService.createTaskQuery().taskAssignee(managerId).orderByTaskId().desc().list();
for (Task task : list) {
log.info("经理 {} 在审批 {} 任务", task.getAssignee(), task.getId());
Map<String, Object> map = new HashMap<>();
map.put("checkResult", "拒绝");
taskService.complete(task.getId(), map);
}
}
}
2.3 当组长或者经理拒绝时,触发我们定义的这个类
@Component
public class AskForLeaveFail implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
System.out.println("请假失败。。。");
}
}
可以自己手动实践实践,需要案例可以私聊