工作流引擎

Activiti&Flowable

工作流引擎

ProcessEngine对象,这是Activiti工作的核心。负责生成流程运行时的各种实例及数据、监控和管理流程的运行。

BPMN

业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)

实现

  1. 配置数据库
  2. 画(配置)流程图

SpringBoot-Flowable

  1. 添加依赖

    <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>
    
  2. 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
    
  3. 定义流程文件

    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标签内。包括各个节点以及每条流程线。

  4. 测试

    首先创建一个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;
    /***************此处为业务代码******************/
    }
    
    1. 启动流程

      @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();
          } 
      
    2. 查询流程列表和代办列表

      @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();
          }
      
    3. 审批

      @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!";
          } 
      
    4. 生成流程图

      /**
           * 生成流程图
           *
           * @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();
                  }
              }
          }
      
posted @   是熙穆吖~  阅读(135)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示