springboot如何集成flowable,如何部署flowable在线编辑器画bpm图以及bpm图的画法,我在上一篇博客中写了,这里直接上代码

  这是我画的请假流程bpm图。

springboot集成flowable 实现请假流程 springboot集成flowable设计器_spring boot

  然会到代码部分。

  首先,先写一个config类,避免生成的bpm图中文乱码。

package com.example.config;

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 springProcessEngineConfiguration) {
        springProcessEngineConfiguration.setActivityFontName("宋体");
        springProcessEngineConfiguration.setLabelFontName("宋体");
        springProcessEngineConfiguration.setAnnotationFontName("宋体");
    }
}

  由于我在画bpm图的时候,给“经理审批”节点和“老板审批”节点设置了监听器。所以接下来写监听器类

  • 经理审批节点监听器。指定任务受理人为“领导”。
package com.example.listen;

import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;

public class ManagerTaskHandler implements TaskListener {
    
    @Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.setAssignee("领导");
        System.out.println("执行监听器————————————————————————————————————");
    }
}
  • 老板审批节点监听器。指定任务受理人为“老板”。
package com.example.listen;

import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;

public class BossTaskHandler implements TaskListener {

    @Override
    public void notify(DelegateTask delegateTask) {
        delegateTask.setAssignee("老板");
    }
}

  接下来到controller。

  • 发起请假流程。这里要说明一下,只有在上一个节点完成任务后,流程才会执行到下一个节点。所以这里在发起流程后,就手动完成了任务,让流程进行到下一个节点。
/**
     * 发起请假
     *
     * @param userId    用户Id
     * @param days     请假天数
     * @param descption 描述
     */ 
@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("days", days);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave-flow", map);
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        taskService.complete(task.getId());

        return "提交成功.流程Id为:" + processInstance.getId() + "任务id: " + task.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(tasks.toString());

        return tasks.toString();
    }


    /**
     * 批准
     *
     * @param taskId 任务ID
     */
    @RequestMapping(value = "apply")
    @ResponseBody
    public String apply(String taskId) {
        List<Task> t = taskService.createTaskQuery().list();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        //Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        if (task == null) {
            throw new RuntimeException("流程不存在");
        }
        //通过审核
        HashMap<String, Object> map = new HashMap<>();
        map.put("result", "同意");
        taskService.complete(taskId, map);
        return "processed ok!";
    }

    /**
     * 拒绝
     */
    @ResponseBody
    @RequestMapping(value = "reject")
    public String reject(String taskId) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("result", "驳回");
        taskService.complete(taskId, map);
        return "reject";
    }

    /**
     * 生成流程图
     *
     * @param processId 任务ID
     */
    @RequestMapping(value = "processDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
        List<ProcessInstance> t = runtimeService.createProcessInstanceQuery().list();
        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);
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, Collections.emptyList(), engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), null, 1.0, false);
        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();
            }
        }
    }

  测试。

  • 发起流程。可以看到后台打印了监听器中的内容,说明执行了监听器。

springboot集成flowable 实现请假流程 springboot集成flowable设计器_hadoop_02

  • 获取审批列表。
  • 通过经理审批。taskId可以从act_ru_task表中查看。
  • 查看流程图。
  • 老板驳回请求。
  • 再次查看流程图。可以看到驳回请求后,又回到申请人节点。 

springboot集成flowable 实现请假流程 springboot集成flowable设计器_spring boot_03

  • 如果老板也通过的话,整个流程就结束了。

       整个流程到这里就演示完了。当时在学的时候,流程卡在第一个节点不往下执行,最后发现只有上一个节点任务完成,才会到下一个节点,发起人节点要手动完成任务。其实在实际开发中,当发起人提交表单时,任务也就完成了,流程会接着往下执行。

  最后补充一下个人认为比较重要的几个表:

act_ru_execution:运行流程实例表。发起的运行中流程可以在此表中看到。
  act_ru_task:运行时任务表。可以查看运行的任务id和任务执行到哪个节点。
  act_re_procdef:已经发布定义的流程可以在此表中看到。
  act_id_user:用户信息表。