工作流引擎
Activiti&Flowable
工作流引擎
ProcessEngine对象,这是Activiti工作的核心。负责生成流程运行时的各种实例及数据、监控和管理流程的运行。
BPMN
业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)
实现
- 配置数据库
- 画(配置)流程图
SpringBoot-Flowable
-
添加依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--flowable工作流依赖--> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring-boot-starter</artifactId> <version>6.3.0</version> </dependency> <!--mysql依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version> </dependency> </dependencies>
-
Flowable配置
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/flowable-spring-boot?characterEncoding=UTF-8 username: root password: root flowable: #关闭定时任务JOB async-executor-activate: false
-
定义流程文件
The Flowable engine expects processes to be defined in the BPMN 2.0 format, which is an XML standard that is widely accepted in the industry. Typically, such a process definition is modeled with a visual modeling tool, such as the Flowable Designer (Eclipse) or the Flowable Modeler (web application).
flowable建议采用业界标准BPMN2.0的XML来描述需要定义的工作流。 可以使用流程建模工具生成xxx.bpmn20.xml文件。
核心逻辑在于process标签内。包括各个节点以及每条流程线。
-
测试
首先创建一个Controller:自动注入Flowable框架的几个Bean
@Controller @RequestMapping(value = "expense") public class ExpenseController { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Autowired private RepositoryService repositoryService; @Autowired private ProcessEngine processEngine; /***************此处为业务代码******************/ }
-
启动流程
@RequestMapping(value = "add") @ResponseBody public String addExpense(String userId, Integer money, String descption) { //启动流程 HashMap<String, Object> map = new HashMap<>(); map.put("taskUser", userId); map.put("money", money); ProcessInstance processInstance = runtimeService .startProcessInstanceByKey("Expense", map); return "提交成功.流程Id为:" + processInstance.getId(); }
-
查询流程列表和代办列表
@RequestMapping(value = "/list") @ResponseBody public Object list(String userId) { List<Task> tasks = taskService.createTaskQuery() .taskAssignee(userId) .orderByTaskCreateTime() .desc() .list(); for (Task task : tasks) { System.out.println(task.toString()); } return tasks.toArray().toString(); }
-
审批
@RequestMapping(value = "apply") @ResponseBody public String apply(String taskId) { Task task = taskService .createTaskQuery() .taskId(taskId) .singleResult(); if (task == null) { throw new RuntimeException("流程不存在"); } //通过审核 HashMap<String, Object> map = new HashMap<>(); map.put("outcome", "通过"); taskService.complete(taskId, map); return "processed ok!"; }
-
生成流程图
/** * 生成流程图 * * @param processId 任务ID */ @RequestMapping(value = "processDiagram") public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception { ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).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); OutputStream out = null; byte[] buf = new byte[1024]; int legth = 0; try { 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(); } } }
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现