来源:juejin.cn/post/7387380647269253146
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;
《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
截止目前,累计输出 54w+ 字,讲解图 2330+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有2000+小伙伴加入
![]()
找了好多文章,每个文章多多少少都有坑点,终于是搞出来了,本文只搞整合,如需详细定义可自行去搜索,网上很多。
程序相关
环境
jdk1.8
maven3
SpringBoot 2.7.5
flowable 6.6.0
MySQL8
目录
![72d0e29d374d6129e09b505b3728c506.jpeg](https://img-blog.csdnimg.cn/img_convert/72d0e29d374d6129e09b505b3728c506.jpeg)
依赖
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<flowable.version>6.6.0</flowable.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 工作流flowable jar包 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>${flowable.version}</version>
</dependency>
<!-- 下面俩皆是flowable-ui所需jar包,不用ui画流程图的可不加 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-ui-idm</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-ui-modeler</artifactId>
<version>${flowable.version}</version>
</dependency>
<!-- 忘了这家伙干啥的了,好像是解决中途的某个报错的,诸位可去掉验证验证 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-layout</artifactId>
<version>${flowable.version}</version>
</dependency>
<!-- mysql数据库连接jar包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<!-- mybatis ORM jar包 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置
application.properties (可自行改为yml)
#端口
server.port=8081
#ui相关信息
flowable.idm.app.admin.user-id=admin
flowable.idm.app.admin.password=admin
flowable.idm.app.admin.first-name=xxx
flowable.idm.app.admin.last-name=xxx
flowable.database-schema-update=true# 没有数据库表的时候生成数据库表(true) 建表后可关闭(false),下次启动不会再次建表
# 关闭定时任务JOB
flowable.async-executor-activate=false
#数据库
spring.datasource.url=jdbc:mysql://xxxx:3306/flowable-test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true #此处的nullCatalogMeansCurrent=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
#日志
logging.level.org.flowable=DEBUG
注意
&nullCatalogMeansCurrent=true
这个一定要加在url后,不然flowable自动创建表失败在数据库中创建flowable数据库,启动项目时,flowable服务会自动创建对应的表
启动项目后 网站的登录用户 密码
user-id: admin password: admin
表
![a150f671903f22be4ba925d91ddee613.jpeg](https://img-blog.csdnimg.cn/img_convert/a150f671903f22be4ba925d91ddee613.jpeg)
后面还有很多,自动创建的,我也没数过
类
防止流程图乱码FlowableConfig
package org.example.config;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;
/**
* flowable配置----为放置生成的流程图中中文乱码
*/
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
@Override
public void configure(SpringProcessEngineConfiguration engineConfiguration) {
engineConfiguration.setActivityFontName("宋体");
engineConfiguration.setLabelFontName("宋体");
engineConfiguration.setAnnotationFontName("宋体");
}
}
返回结果Result
package org.example.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private boolean flag;
private String message;
private Object data;
public Result(boolean flag , String message){
this.flag = flag;
this.message = message;
}
}
TaskVO封装审批列表查询结果
package org.example.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ 审批列表查询结果
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TaskVO {
private String id;
private String day;
private String name;
}
controller请假流程接口
package org.example.controller;
import lombok.extern.slf4j.Slf4j;
import org.example.vo.Result;
import org.example.vo.TaskVO;
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.*;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/leave")
@Slf4j
public class LeaveController {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ProcessEngine processEngine;
@PostMapping( "add/{day}/{studentUser}")
public Result sub(@PathVariable("day") Integer day , @PathVariable("studentUser") String studentUser) {
// 学生提交请假申请
Map<String, Object> map = new HashMap<>();
map.put("day", day);
map.put("studentName", studentUser);
// stuLeave为学生请假流程xml文件中的id,即后面bpmn20.xml文件的process id="stuLeave"
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("stuLeave", map);
log.info("流程实例ID:" + processInstance.getId());
//完成申请任务
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.complete(task.getId());
//此处id为流程id
return new Result(true,"提交成功.流程Id为:" + processInstance.getId()) ;
}
@GetMapping("teacherList")
public Result teacherList() {
//此处.taskCandidateGroup("a")的值“a”即是画流程图时辅导员审批节点"分配用户-候选组"中填写的值
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("a").list();
List<TaskVO> taskVOList = tasks.stream().map(task -> {
Map<String, Object> variables = taskService.getVariables(task.getId());
return new TaskVO(task.getId(), variables.get("day").toString(), variables.get("studentName").toString());
}).collect(Collectors.toList());
log.info("任务列表:" + tasks);
if (tasks == null || tasks.size() == 0) {
return new Result(false,"没有任务");
}
return new Result(true,"获取成功",taskVOList);
}
/**
* 辅导员批准
*
* @param taskId 任务ID,非流程id
*/
@GetMapping("teacherApply/{taskId}")
public Result teacherApply(@PathVariable("taskId") String taskId) {
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("a").list();
Task task = taskService.createTaskQuery().taskCandidateGroup("a").taskId(taskId).singleResult();
if (task == null) {
return new Result(false, "没有任务");
}
//通过审核
HashMap<String, Object> map = new HashMap<>();
map.put("outcome", "通过");
// for (Task task : tasks) {
// taskService.complete(task.getId(), map);
// }
taskService.complete(task.getId(), map);
return new Result(true,"审批成功");
}
/**
* 辅导员拒绝
* @param taskId 任务ID,非流程id
*/
@GetMapping( "teacherReject/{taskId}")
public Result teacherReject(@PathVariable("taskId") String taskId) {
Task task1 = taskService.createTaskQuery().taskCandidateGroup("a").taskId(taskId).singleResult();
//Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task1 == null) {
return new Result(false, "没有任务");
}
//通过审核
HashMap<String, Object> map = new HashMap<>();
map.put("outcome", "驳回");
taskService.complete(task1.getId(), map);
return new Result(true,"审批失败");
}
/**
* 院长获取审批管理列表
*/
@GetMapping("deanList")
public Result deanList() {
//此处.taskCandidateGroup("b")的值“b”即是画流程图时辅导员审批节点"分配用户-候选组"中填写的值
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("b").list();
List<TaskVO> taskVOList = tasks.stream().map(task -> {
Map<String, Object> variables = taskService.getVariables(task.getId());
return new TaskVO(task.getId(), variables.get("day").toString(), variables.get("studentName").toString());
}).collect(Collectors.toList());
if (tasks == null || tasks.size() == 0) {
return new Result(false,"没有任务");
}
return new Result(true,"获取成功",taskVOList);
}
/**
* 院长批准
* @param taskId 任务ID,非流程id
* @return
*/
@GetMapping("deanApply/{taskId}")
public Result apply(@PathVariable("taskId") String taskId) {
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("b").list();
//Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (tasks == null) {
return new Result(false, "没有任务");
}
//通过审核
HashMap<String, Object> map = new HashMap<>();
map.put("outcome", "通过");
for (Task task : tasks) {
taskService.complete(task.getId(), map);
}
return new Result(true,"审批成功");
}
/**
* 院长拒绝
* @param taskId 任务ID,非流程id
* @return
*/
@GetMapping("deanReject/{taskId}")
public Result deanReject(@PathVariable("taskId") String taskId) {
// List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("b").list();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
return new Result(false, "没有任务");
}
//通过审核
HashMap<String, Object> map = new HashMap<>();
map.put("outcome", "驳回");
// for (Task task : tasks) {
// taskService.complete(task.getId(), map);
// }
taskService.complete(task.getId(), map);
return new Result(true,"审批成功");
}
/**
* 再次申请
* @param piId 流程id
* @param day
* @return
*/
@GetMapping("subAgain/{piId}/{day}")
public Result subAgain(@PathVariable("piId") String piId, @PathVariable("day") Integer day){
Task task = taskService.createTaskQuery().processInstanceId(piId).singleResult();
if(Objects.isNull(task)){
return new Result(false, "没有任务");
}
Map<String, Object> map = new HashMap<>();
map.put("day", day);
taskService.complete(task.getId(), map);
return new Result(true,"申请成功");
}
/**
* 生成流程图
*
* @param taskId 流程ID
*/
@GetMapping( "processDiagram/{taskId}")
public void genProcessDiagram(HttpServletResponse httpServletResponse,@PathVariable("taskId") String taskId) throws Exception {
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(taskId).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的Id
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 ,true);
OutputStream out = null;
byte[] buf = new byte[1024];
int legth = 0;
try {
//此处设置resp的header诸多文章都没写,但是我不写出不来流程图,诸位可去掉试试
httpServletResponse.setHeader("Content-Type",
"image/png;charset=utf-8");
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();
}
}
}
}
此时可以启动项目了,访问http://localhost:8081
用配置文件配置的账号密码登录
![5f996bb194e9ad08d512b400789d61d7.jpeg](https://img-blog.csdnimg.cn/img_convert/5f996bb194e9ad08d512b400789d61d7.jpeg)
创建流程
![8f85e87d9454c96aff2f7545d63f2f0a.jpeg](https://img-blog.csdnimg.cn/img_convert/8f85e87d9454c96aff2f7545d63f2f0a.jpeg)
![9a8b71682db033fa123018aba8175e36.jpeg](https://img-blog.csdnimg.cn/img_convert/9a8b71682db033fa123018aba8175e36.jpeg)
简单画图操作
![25d8dcd6eb10f3cafc9420cda8045691.jpeg](https://img-blog.csdnimg.cn/img_convert/25d8dcd6eb10f3cafc9420cda8045691.jpeg)
画请假流程
![e0c48d355c512de85868f76bd4bb597c.jpeg](https://img-blog.csdnimg.cn/img_convert/e0c48d355c512de85868f76bd4bb597c.jpeg)
![9ce2b330a8225db24ea63eae02601321.jpeg](https://img-blog.csdnimg.cn/img_convert/9ce2b330a8225db24ea63eae02601321.jpeg)
![503cf7e2133ea3a1051a2b1c71dcbdfc.jpeg](https://img-blog.csdnimg.cn/img_convert/503cf7e2133ea3a1051a2b1c71dcbdfc.jpeg)
![acfb76103d59b27fe83507aa34391a1d.jpeg](https://img-blog.csdnimg.cn/img_convert/acfb76103d59b27fe83507aa34391a1d.jpeg)
![66be98607a7f03d0e7cf07669d547939.jpeg](https://img-blog.csdnimg.cn/img_convert/66be98607a7f03d0e7cf07669d547939.jpeg)
![3f6eff78aa60e973bffca4e89913e851.jpeg](https://img-blog.csdnimg.cn/img_convert/3f6eff78aa60e973bffca4e89913e851.jpeg)
![e9534f1107665a4fa4d23d0e34ffadb4.jpeg](https://img-blog.csdnimg.cn/img_convert/e9534f1107665a4fa4d23d0e34ffadb4.jpeg)
![1f213a0ace20928755f4617c18b0dca3.jpeg](https://img-blog.csdnimg.cn/img_convert/1f213a0ace20928755f4617c18b0dca3.jpeg)
![048445492413d123e38ec5148d4265d9.jpeg](https://img-blog.csdnimg.cn/img_convert/048445492413d123e38ec5148d4265d9.jpeg)
注意:每个审批元素属性中有个独占任务项,我参考的博客是改了的,但是我改不了,不过也没发现有啥问题,大家有兴趣可以去研究研究
![f09b744b76eda3be83500838e2be8a4c.jpeg](https://img-blog.csdnimg.cn/img_convert/f09b744b76eda3be83500838e2be8a4c.jpeg)
在resources下创建processes文件夹,复制下载的"学生请假流程.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: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="stuLeave" name="学生请假流程" isExecutable="true">
<documentation>学校学生请假流程</documentation>
<startEvent id="startEvent1" name="开始" flowable:formFieldValidation="true"></startEvent>
<userTask id="apply" name="请假申请" flowable:assignee="${studentName}" flowable:formFieldValidation="true">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<userTask id="teacherPass" name="辅导员审批" flowable:candidateGroups="a" flowable:formFieldValidation="true"></userTask>
<exclusiveGateway id="judgeTask" name="判断是否大于2天"></exclusiveGateway>
<userTask id="principalPass" name="院长审批" flowable:candidateGroups="b" flowable:formFieldValidation="true"></userTask>
<endEvent id="over" name="结束"></endEvent>
<sequenceFlow id="judgeLess" name="小于2天" sourceRef="judgeTask" targetRef="over">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${day<=2}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="judgeMore" name="大于2天" sourceRef="judgeTask" targetRef="principalPass">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${day>2}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flowBeg" name="流程开始" sourceRef="startEvent1" targetRef="apply"></sequenceFlow>
<sequenceFlow id="sid-F3C3133B-68E1-4D1B-B06B-761EDD44E9F6" name="申请流程" sourceRef="apply" targetRef="teacherPass"></sequenceFlow>
<sequenceFlow id="TeacherNotPassFlow" name="驳回" sourceRef="teacherPass" targetRef="apply">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='驳回'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="teacherPassFlow" name="通过" sourceRef="teacherPass" targetRef="judgeTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=="通过"}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="presidentNotPassFlow" name="驳回" sourceRef="principalPass" targetRef="apply">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='驳回'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="presidentPassFlow" name="通过" sourceRef="principalPass" targetRef="over">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=='通过'}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_stuLeave">
<bpmndi:BPMNPlane bpmnElement="stuLeave" id="BPMNPlane_stuLeave">
<bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
<omgdc:Bounds height="30.0" width="30.0" x="100.0" y="163.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="apply" id="BPMNShape_apply">
<omgdc:Bounds height="80.0" width="100.0" x="209.9999968707562" y="137.99999794363978"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="teacherPass" id="BPMNShape_teacherPass">
<omgdc:Bounds height="80.0" width="100.0" x="389.99999418854725" y="137.99999794363978"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="judgeTask" id="BPMNShape_judgeTask">
<omgdc:Bounds height="40.0" width="40.0" x="569.9999915063382" y="157.99999764561656"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="principalPass" id="BPMNShape_principalPass">
<omgdc:Bounds height="80.0" width="100.0" x="539.9999834597114" y="284.9999915063383"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="over" id="BPMNShape_over">
<omgdc:Bounds height="28.0" width="28.0" x="794.9999881535771" y="163.9999975562096"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="presidentNotPassFlow" id="BPMNEdge_presidentNotPassFlow">
<omgdi:waypoint x="539.9999834597114" y="324.9999915063383"></omgdi:waypoint>
<omgdi:waypoint x="259.9999968707562" y="324.9999915063383"></omgdi:waypoint>
<omgdi:waypoint x="259.9999968707562" y="217.9499979436398"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="judgeLess" id="BPMNEdge_judgeLess">
<omgdi:waypoint x="609.4890905518624" y="178.45641965548475"></omgdi:waypoint>
<omgdi:waypoint x="795.0000204150059" y="178.03191983331223"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-F3C3133B-68E1-4D1B-B06B-761EDD44E9F6" id="BPMNEdge_sid-F3C3133B-68E1-4D1B-B06B-761EDD44E9F6">
<omgdi:waypoint x="309.94999687075494" y="177.99999794363978"></omgdi:waypoint>
<omgdi:waypoint x="389.99999418854725" y="177.99999794363978"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="judgeMore" id="BPMNEdge_judgeMore">
<omgdi:waypoint x="590.4349219597013" y="197.50836625144538"></omgdi:waypoint>
<omgdi:waypoint x="590.1363337825771" y="284.9999915063383"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flowBeg" id="BPMNEdge_flowBeg">
<omgdi:waypoint x="129.94999913083947" y="177.99999978727305"></omgdi:waypoint>
<omgdi:waypoint x="209.99999373428892" y="177.99999865202045"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="presidentPassFlow" id="BPMNEdge_presidentPassFlow">
<omgdi:waypoint x="639.9499834597113" y="324.9999915063383"></omgdi:waypoint>
<omgdi:waypoint x="808.9999881535771" y="324.9999915063383"></omgdi:waypoint>
<omgdi:waypoint x="808.9999881535771" y="191.94992565845044"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="TeacherNotPassFlow" id="BPMNEdge_TeacherNotPassFlow">
<omgdi:waypoint x="439.99999418854725" y="137.99999794363978"></omgdi:waypoint>
<omgdi:waypoint x="439.99999418854725" y="68.00000129640101"></omgdi:waypoint>
<omgdi:waypoint x="259.9999968707562" y="68.00000129640101"></omgdi:waypoint>
<omgdi:waypoint x="259.9999968707562" y="137.99999794363978"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="teacherPassFlow" id="BPMNEdge_teacherPassFlow">
<omgdi:waypoint x="489.949994188544" y="178.16594469153907"></omgdi:waypoint>
<omgdi:waypoint x="570.4333248783485" y="178.43333101762673"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
演示
提交申请
![5fb1a6bde1a2c7e436859cb5195620d2.jpeg](https://img-blog.csdnimg.cn/img_convert/5fb1a6bde1a2c7e436859cb5195620d2.jpeg)
辅导员审批列表
![af6b866ca726089aee3877a993ed652b.jpeg](https://img-blog.csdnimg.cn/img_convert/af6b866ca726089aee3877a993ed652b.jpeg)
流程图
![4db272a7c1f1d04c7e5131d55dc46d72.jpeg](https://img-blog.csdnimg.cn/img_convert/4db272a7c1f1d04c7e5131d55dc46d72.jpeg)
辅导员批准
![c07a528f2c379311d86f48fd57957fdf.jpeg](https://img-blog.csdnimg.cn/img_convert/c07a528f2c379311d86f48fd57957fdf.jpeg)
流程图
![0cf207905402b61e63594e86bce70789.jpeg](https://img-blog.csdnimg.cn/img_convert/0cf207905402b61e63594e86bce70789.jpeg)
院长获取审批列表
![699b3a2e33891146630fa6a58c88502e.jpeg](https://img-blog.csdnimg.cn/img_convert/699b3a2e33891146630fa6a58c88502e.jpeg)
院长拒绝
![798a9a64a8b44a2b5f8ae0f24170a5b1.jpeg](https://img-blog.csdnimg.cn/img_convert/798a9a64a8b44a2b5f8ae0f24170a5b1.jpeg)
流程图
![3b820fbdf6ef5216111524ef2d2d4338.jpeg](https://img-blog.csdnimg.cn/img_convert/3b820fbdf6ef5216111524ef2d2d4338.jpeg)
再次申请
![1ce9122d674c344057d6ce8059a5860c.jpeg](https://img-blog.csdnimg.cn/img_convert/1ce9122d674c344057d6ce8059a5860c.jpeg)
流程图
![51fa25909b06b4105de581578ae8a40e.jpeg](https://img-blog.csdnimg.cn/img_convert/51fa25909b06b4105de581578ae8a40e.jpeg)
辅导员审批列表
![3d9334e90c09669783c37e5060f6d06a.jpeg](https://img-blog.csdnimg.cn/img_convert/3d9334e90c09669783c37e5060f6d06a.jpeg)
其它流程大家可自行验证
大家一定要注意各个接口的入参id,有的是流程id,有的是任务id,且任务id也会随着节点变动而变动,我是从审批列表中获取的,关于id变动这块,大家有兴趣可深入研究下,我反正是一脸懵,大家可以看看ACT_RU_TASK
这张表观察观察每个审批节点的id变化情况
表结构
ACT_RE : 'RE’表示 repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
ACT_RU: 'RU’表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Flowable只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
ACT_HI: 'HI’表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
ACT_GE: GE 表示 general。 通用数据, 用于不同场景下
ACT_ID: ’ID’表示identity(组织机构)。这些表包含标识的信息,如用户,用户组,等等。
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;
《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
截止目前,累计输出 54w+ 字,讲解图 2330+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有2000+小伙伴加入
![]()
1. 我的私密学习小圈子~
2. 终极 Nginx 配置指南(全网最详细)
3. 线程池不再乱配线程数了
4. SpringBoot 物理线程、虚拟线程、Webflux 性能全面对比!
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。
点“在看”支持小哈呀,谢谢啦