springboot如何集成flowable,如何部署flowable在线编辑器画bpm图以及bpm图的画法,我在上一篇博客中写了,这里直接上代码
这是我画的请假流程bpm图。
然会到代码部分。
首先,先写一个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();
}
}
}
测试。
- 发起流程。可以看到后台打印了监听器中的内容,说明执行了监听器。
- 获取审批列表。
- 通过经理审批。taskId可以从act_ru_task表中查看。
- 查看流程图。
- 老板驳回请求。
- 再次查看流程图。可以看到驳回请求后,又回到申请人节点。
- 如果老板也通过的话,整个流程就结束了。
整个流程到这里就演示完了。当时在学的时候,流程卡在第一个节点不往下执行,最后发现只有上一个节点任务完成,才会到下一个节点,发起人节点要手动完成任务。其实在实际开发中,当发起人提交表单时,任务也就完成了,流程会接着往下执行。
最后补充一下个人认为比较重要的几个表:
act_ru_execution:运行流程实例表。发起的运行中流程可以在此表中看到。
act_ru_task:运行时任务表。可以查看运行的任务id和任务执行到哪个节点。
act_re_procdef:已经发布定义的流程可以在此表中看到。
act_id_user:用户信息表。