likes
comments
collection
share

SpringBoot整合Flowable【04】- 通过代码控制流程流转

作者站长头像
站长
· 阅读数 3

一、前情回顾

在03篇中,我用Flowable-UI绘制了一个简单的绩效流程并在官方的demo中跑完了整个流程,加深了各位读者对于一个流程中包含的一些基础概念加深了认识,并且在这个过程里也渗透了一些可以应用的知识点。但我们也能想到,在实际业务中我们是要靠后端的接口去控制流程的流转,而不能靠Flowable-UI去控制。因此,本篇文章就是带领读者使用Flowable的Java Api去控制流程流转,从而熟悉对相关API的使用。

二、导入流程

本次我们演示使用的模型就是上篇中在Flowable-UI中建立的绩效模型,因此我们需要把模型文件导出。在模型管理界面,我们绘制的模型在详情页都有导出选项。 SpringBoot整合Flowable【04】-  通过代码控制流程流转

将导出的模型文件放到项目里,位置没有硬性要求,但建议放在resource目录下。 SpringBoot整合Flowable【04】-  通过代码控制流程流转

三、代码控制

虽然Flowable也可以在非Spring环境下使用,但我相信应该没人会拒绝SpringBoot,毕竟精力扑到业务和开发上,比折腾配置可有趣多了。

1.相关配置

我们需要在02篇配置的基础上添加Flowable相关的配置。

flowable:
  async-executor-activate: true # 关闭定时任务job
  database-schema-update: true # flowable自动更新表结构

2.部署流程

完成了相关的配置后,我们来定义一个流程控制器并注入一个RepositoryService对象,它提供了管理和控住部署和流程定义相关操作的API。

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/process/v1")
public class ProcessControllerV1 {

    private final RepositoryService repositoryService;
    
}

接着声明一个部署流程的接口方法,当然,这里也可以编写一个测试类进行测试,只是我个人更喜欢直接用接口测:

/**
 * 部署流程模型.
 *
 * @return 流程key
 */
@PostMapping("/deploy")
public ResponseEntity<Object> createProcessDef() {
    //1,创建部署对象
    Deployment deployment = repositoryService.createDeployment()
            //2.添加流程定义文件
            .addClasspathResource("process/performance.bpmn20.xml")
            //3.设置流程名称
            .name("绩效流程")
            //4.部署
            .deploy();
    //5.返回部署的流程id
    return new ResponseEntity<>(new BaseResponse<>(deployment.getId()), HttpStatus.OK);
}

完成编码通过调试工具调这个接口,当方法正常执行后,会返回流程部署的id。 SpringBoot整合Flowable【04】-  通过代码控制流程流转 此时我们可以在三张表中看到此次部署的相关信息,首先是act_ge_bytearray表,它记录了流程定义的资源信息,包含了xml和流程图的图片信息; SpringBoot整合Flowable【04】-  通过代码控制流程流转 其次是act_re_deployment表,它记载了这次的部署行为; SpringBoot整合Flowable【04】-  通过代码控制流程流转 最后是act_re_procdef表,他记录了此次部署对应的流程定义信息; SpringBoot整合Flowable【04】-  通过代码控制流程流转

3.启动流程

流程部署成功后,就可以启动流程了,我们需要注入一个新的服务类-RuntimeService来启动流程。

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/process/v1")
public class ProcessControllerV1 {

    private final RepositoryService repositoryService;

    private final RuntimeService runtimeService;

在这里需要说明下启动流程有两个方法,分别是通过id和key。它们的区别就是id是由引擎维护的,而key是由我们自己维护的(Ps:这里迷惑的同学回到03篇看下,我们在创建流程和节点的时候都有输入Key)。因此,在实际业务开发中我建议还是通过id启动流程。

runtimeService.startProcessInstanceById(processId);

runtimeService.startProcessInstanceByKey(processKey);

于是我们通过流程id来启动这个绩效流程,这个方法会返回一个流程实例对象。需要注意的是,在下面的示例中,我是直接声明的,聪明的同学一定已经想到了,在实际业务开发中,这个是在部署流程之后,由前端调这个接口并传入流程id来启动流程。

/**
 * 启动流程.
 *
 * @return 流程key
 */
@PostMapping("/start")
public ResponseEntity<Object> startProcessDef() {
    //1.声明流程id
    String processId = "performance-001:1:a9d432fd-ec57-11ee-980b-c85ea9014af0";
    //2.启动流程
    ProcessInstance processInstance = runtimeService.startProcessInstanceById(processId);
    //3.返回流程实例对象id
    return new ResponseEntity<>(new BaseResponse<>(processInstance.getId()), HttpStatus.OK);
}

通过调试工具调这个接口,当方法正常执行后,会返回流程实例的id。 SpringBoot整合Flowable【04】-  通过代码控制流程流转 启动流程也需要我们关注三张表,此时我们可以在act_ru_task表中看到当前流程走到了自评节点以及节点的承办人,即当前待办的记录信息。 SpringBoot整合Flowable【04】-  通过代码控制流程流转 而在act_ru_execution表中则记录了每个启动了的流程分支。 SpringBoot整合Flowable【04】-  通过代码控制流程流转 另外,可以在act_hi_actinst表中查询到这个流程的运行记录,需要注意的是:只要你启动一个流程,记录都会维护在这张表中SpringBoot整合Flowable【04】-  通过代码控制流程流转 这里可以看到我们在部署流程启动流程这两个方法里涉及到了两个概念-1.流程定义2.流程实例,它们二者的关系可以类比为Java中的类与对象,即定义一个流程后,我们可以根据这个流程定义启动N个流程实例

4.流程审批

流程启动成功后,为了流程的跑通,我们就需要对各个节点进行审批。因此,我们需要注入新的服务类- TaskService,它负责处理所有的节点任务。

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/process/v1")
public class ProcessControllerV1 {

    private final RepositoryService repositoryService;

    private final RuntimeService runtimeService;

    private final TaskService taskService;

还记得前面提过的每个节点都有个承办人,完成节点的审批就需要各个节点的承办人来做。因此我们先写个方法来查找某个承接人待处理的待办:

/**
 * 查询指定用户的待办任务.
 *
 * @param user 待办用户
 * @return 待办任务id
 */
private String findUserAgentTask(String user) {
    //1.查找指定用户的一个待办任务
    Task agentTask = taskService.createTaskQuery()
            .taskAssignee(user)
            .singleResult();
    //2.返回待办任务的id
    return agentTask.getId();
}

因为我这里演示只启动了一个流程,所以也只有一个待办,因此查询单个任务就可以了。读者们在实际开发者需要结合实际业务,如果业务场景会出现一个用户有多个待办,一定要查询任务集合,否则会报错。

//待办任务集合
List<Task> list = taskService.createTaskQuery()
        .taskAssignee(user)
        .list();
//待办任务集合(带分页)
List<Task> tasks = taskService.createTaskQuery()
        .taskAssignee(user)
        .listPage(1, 10);      
      

查询到某个用户的待办后,返回待办任务的id,直接调用API完成节点审批即可。这里再复习一下:因为我们不使用引擎自带的用户关系,所以这里的审批操作其实引擎不会校验的,所以需要我们根据实际业务自行编写鉴权代码。 我这里演示也没什么要鉴权的,直接完成审批:

/**
 * 完成节点任务.
 *
 * @return 流程key
 */
@PostMapping("/complete/{agentUser}")
public ResponseEntity<Object> completeTask(@PathVariable String agentUser) {
    //1.查询指定用户的待办任务
    String agentTaskId = findUserAgentTask(agentUser);
    //2.完成指定任务的审批
    taskService.complete(agentTaskId);
    //3.返回响应
    return new ResponseEntity<>(new BaseResponse<>(null), HttpStatus.OK);
}

通过调试工具调这个接口并在调用时传入承接人数据,运行后提示执行成功。 SpringBoot整合Flowable【04】-  通过代码控制流程流转 各位读者不要被这个传承接人数据限制了,我只是为了演示API的使用,既然强调了引擎不会校验我们自定义的用户关系,在我们自己不加入逻辑判断的情况下,直接给完成方法穿待办任务id也是可以通过的:

/**
 * 完成节点任务.
 *
 * @return 流程key
 */
@PostMapping("/complete/{agentUser}")
public ResponseEntity<Object> completeTask(@PathVariable String agentUser) {
    //1.查询指定用户的待办任务
    //String agentTaskId = findUserAgentTask(agentUser);
    //2.完成指定任务的审批
    taskService.complete("d30f9ffd-eeb2-11ee-9654-c85ea9014af0");
    //3.返回响应
    return new ResponseEntity<>(new BaseResponse<>(null), HttpStatus.OK);
}

这时候我们回到act_ru_task表,就可以看到节点走到了上级评节点: SpringBoot整合Flowable【04】-  通过代码控制流程流转 再次调用接口,就可以看到节点走到了隔级评节点: SpringBoot整合Flowable【04】-  通过代码控制流程流转 最后调用一次,会发现act_ru_task表中已经没有数据了,因为我们这个流程已经完成了,后续我们想查这个流程节点的信息就只能去历史相关表里了。 SpringBoot整合Flowable【04】-  通过代码控制流程流转

四、小结

本篇主要是让各位读者了解了如何通过代码控制流程流转,介绍了几个主要的服务类和相关API地使用,至此,各位读者应该已经对Flowable可以进行初步的应用了,在以后的篇章中,会开始一些进阶的内容,比如节点引用表单、驳回功能、网关的使用等等。