[Camunda]流程引擎从入门到入行 - 运行时服务runtimeService

Camunda流程引擎系列

四、运行时服务类 - RuntimeService



前言

该服务类包含了许多与实例相关的服务,流程定义好的规则开始运转时,就是我们本次分享的主要内容。


一、RuntimeServiceImpl

我们对运行时服务的调用,基本都可以基于该类进行操作,官方提供了非常多的方法,有兴趣的小伙伴可以搜索 RuntimeServiceImpl 看看源码,在org.camunda.bpm.engine.impl包下。

派生类

  • 可根据不同API启动实例,并返回ProcessInstance对象;
  • 可异步删除所有实例,并返回Batch对象;
  • 可获取变量信息,并返回VariableMap对象;
  • 可获取变量信息,并返回Map<String, Object>对象;
  • 可获取单个变量信息,并返回TypedValue;
  • 可查询执行实例,并返回ExecutionQuery对象;
  • 可自定义SQL查询并执行实例,并返回NativeExecutionQuery对象;
  • 可查询流程实例信息,并返回ProcessInstanceQuery对象;
  • 可自定义SQL查询流程实例信息,并返回NativeProcessInstanceQuery对象;
  • 可查询Incident相关信息,并返回Incident对象;

启动实例方式

  • processDefinitionKey
  • processDefinitionKey + 租户ID
  • messageName + 租户ID
  • messageName
  • processDefinitionId

二、流程定义

1.定义

流程定义:通过资源文件,获取已事先定义好的流程规则信息。
执行实例:发起流程定义,可以认为流程定义就像定义了一个类,而执行实例就是生成了一个对象。
流程实例:一个流程的最长分支,就好比项目管理里面的关键路径。

public interface ProcessInstance extends Execution

启动流程时会首先创建流程实例,如果存在子流程、多实例、并行网关,则会再次创建执行实例。流程运转的过程中永远执行的时自己对应的执行实例。当所有执行实例按照规则执行完毕之后,则流程实例随之结束。

Camunda用ProcessInstance对象去描述流程执行的每一个节点,流程按照流程定义的规则执行一次的过程,就可以表示执行对象Execution。

一个流程中,执行对象可以是多个,执行实例在某个活动节点时,需要我们通过特定API去完成,然后执行实例继续往下走。

一个实例运行的简单过程:

  1. 启动实例;
  2. 创建实例;
  3. 更新实例;
  4. 完成实例。

稍微复杂一点的如存在并行网关的话,流程实例就是这样的:
在这里插入图片描述

2. 启动流程

RuntimeService有很多启动流程的API,我们演示其中一种,因为不同的API主要差别在于传参的不同,传参不同主要是业务逻辑的不同,但是其本质大同小异。

获取runtimeService

private RuntimeService runtimeService = PnxProcessEngine.INSTANCE.getProcessEngine().getRuntimeService();

根据key启动实例

这个KEY可以在数据库表 ACT_RE_PROCDEF 的KEY_字段查看到,当然也可以在流程文件中查到,或者通过查询接口查到。

    public ProcessInstance startProcess(String key) {
        return runtimeService.startProcessInstanceByKey(key);
    }

实例启动后,程序会返回ProcessInstance 的对象。
下面是我们的测试代码,可以看看返回的对象包含什么样的数据

    @Test
    void startProcess() {
        String key = "Process_0iplu3k";
        ProcessInstance processInstance = pnxRuntimeService.startProcess(key);
        processInstance.getId();
        System.out.println("id is : " + processInstance.getId());
        System.out.println("getBusinessKey is : " + processInstance.getBusinessKey());
        System.out.println("getRootProcessInstanceId is : " + processInstance.getRootProcessInstanceId());
        System.out.println("getProcessInstanceId is : " + processInstance.getProcessInstanceId());
    }

当流程实例启动时,以下两张表会有新的数据插入:

ACT_RU_EXECUTION
ACT_RU_TASK

同时会有几张历史表也会插入数据(ACT_HI_XXXX都是历史表):

ACT_HI_ACTINST
ACT_HI_TASKINST
ACT_HI_PROCINST
ACT_HI_IDENTITYLINK


完成Task

一个实例启动过后,对应的任务需要完成才会走入下一个节点,这时候我们会有大量对Task的操作,从产品的角度来看,一个任务启动会根据规则分配到人,然后该用户获取自己的任务列表,进行操作后完成该任务。

那么我们看看这几个操作会涉及哪几个API,以及用测试代码做一下测试看看,然后对完成一个任务时会操作哪些数据做一些讲解。

/**
 * @author zhaopeng01
 * @version 1.0
 * @title: PnxTaskServiceImpl
 * @projectName phoenix-camunda
 * @description: TODO
 * @date 2020/11/1421:41
 */
@Service
public class PnxTaskServiceImpl {
    private TaskService taskService = PnxProcessEngine.INSTANCE.getProcessEngine().getTaskService();

    public List<Task> getTasks(int first, int max) {
        return taskService.createTaskQuery().listPage(first, max);
    }

    public void assignTask(String taskId, String assignee) {
        taskService.setAssignee(taskId, assignee);
    }

    public List<Task> getTasksByAssignee(String assignee, int first, int max) {
        return taskService.createTaskQuery().taskAssignee(assignee).listPage(first, max);
    }

    public void completeTask(String taskId) {
        taskService.complete(taskId);
    }

    public Task getTaskById(String taskId) {
        return taskService.createTaskQuery().taskId(taskId).singleResult();
    }
}

测试代码:
/**
 * @author zerozhao
 * @version 1.0
 * @title: PnxTaskServiceImplTest
 * @projectName phoenix-camunda
 * @description: TODO
 * @date 2020/11/1421:50
 */
@SpringBootTest
class PnxTaskServiceImplTest {
    @Autowired
    PnxTaskServiceImpl taskService;

    private String taskId = "1604";
    private String assignee = "zero";

    @Test
    @Order(0)
    void getTasks() {
        System.out.println(taskService);
        List<Task> tasks = taskService.getTasks(0, 5);
        tasks.stream().forEach(task -> {
            taskId = task.getId();
        });
    }

    @Test
    @Order(1)
    void assignTask() {
        taskService.assignTask(taskId, assignee);
    }

    @Test
    @Order(2)
    void getTasksByAssignee() {
        List<Task> tasks = taskService.getTasksByAssignee(assignee, 0, 5);
        tasks.stream().forEach(task -> {
            assertEquals("assignee is equal.", task.getAssignee(), assignee);
        });
    }

    @Test
    @Order(3)
    void completeTask() {
        taskService.completeTask(taskId);
        Task task = taskService.getTaskById(taskId);
        assertNull("没有对应task", task);
    }
}

在这组单元测试代码中,我们会先查询任务列表,然后对该任务赋予一个执行人,接下来会完成该任务,用原任务号去查询,该任务已经没有了。
那么原任务去哪里了呢?进入历史表了,而任务表会插入一个新的任务,是我们流程定义的下一个节点。
任务的完成会涉及到多张表的数据操作,那么我们来看看分别是那几张表,这将有利于我们理解其背后的逻辑,从而更好地完成我们的业务诉求。

插入:

  • ACT_HI_TASKINST
  • ACT_HI_IDENTITYLINK(不一定有,要看用户模式)
  • ACT_HI_ACTINST
  • ACT_RU_TASK

删除:

  • ACT_RU_TASK

更新:

  • ACT_RU_EXECUTION
  • ACT_HI_ACTINST
  • ACT_HI_TASKINST

历史数据

在流程引擎中,更多的数据会记录进历史表中,我们要查询一些任务的状态或者列表,都会使用到这些历史表,而有的数据会在系统运行中,同步插入历史表与当前任务表。
我们来看看几张主要的历史表以及与之对应的当前数据表。

  • ACT_RU_EXECUTION:正在执行的信息
  • ACT_HI_PROCINST:已经执行完的历史流程实例信息
  • ACT_HI_ACTINST:所有完成的历史活动
  • ACT_RU_TASK:正在执行的任务数据
  • ACT_HI_TASKINST:已经执行完的历史任务数据

设定发起人与使用initiator

之前的流程中,我们设置了流程的当前节点执行人,但是在实际的场景中我们的流程是不是还会有一个发起人?以及每个任务节点的指派人?指派人的设定会有一点不同,并且可以将指派人作为变量传入后续的任务中。

    @Autowired
    PnxIdentityService pnxIdentityService;
    @Autowired
    PnxRuntimeServiceImpl pnxRuntimeService;

    /**
     * 指定启动用户的开启流程
     * @param authUser
     * @param processKey
     */
    public void startProcess(String authUser, String processKey) {
        pnxIdentityService.setAuthUser(authUser);
        pnxRuntimeService.startProcess(processKey);
    }

通过IdentityService来设置流程发起人。

**NOTE:**我们开启流程最好用key,不要使用id,id是系统标识,会伴随部署更新对应的值,导致系统可能走到我们预期以外的流程上去。

删除流程实例

一个流程,如果走到一半,或者别的原因,我们希望中止了,那么就可以使用流程删除,流程删除的操作也很简单,调用RuntimeService的API即可,传入流程实例的ID与删除原因。

    public void delProcess (String processId, String reason) {
        runtimeService.deleteProcessInstance(processId, reason);
    }

这个过程中会涉及到如下数据库表操作:
删除:

  • ACT_RU_TASK
  • ACT_RU_EXECUTION

更新:

  • ACT_HI_ACTINST
  • ACT_HI_PROCINST
  • ACT_HI_TASKINST

流程的挂起与激活

有时候我们不希望一个流程被删除,但是也不希望再被操作,等待以后重新恢复。
当一个流程实例挂起时,该实例下的子流程也都会挂起,所以需要慎重确认。

  • 流程定义的挂起
    /**
     * 挂起流程定义,挂起后基于该定义的流程将不能再执行,除非先激活
     *
     * @param id
     */
    public void suspendProcessDef(String id) {
        runtimeService.suspendProcessInstanceByProcessDefinitionId(id);
    }
  • 流程实例的挂起
    /**
     * 挂起流程定义,挂起后基于该定义的流程将不能再执行,除非先激活
     *
     * 两种挂起方式
     *
     * @param id
     */
    public void suspendProcessDef(String id) {
        //runtimeService.suspendProcessInstanceByProcessDefinitionId(id);
        ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
        processInstanceQuery.processInstanceId(id);
        runtimeService.updateProcessInstanceSuspensionState().byProcessInstanceQuery(processInstanceQuery).suspendAsync();
    }
  • 激活流程定义
    /**
     * 两种激活流程定义的方法
     * @param id
     */
    public void activeProcessDef(String id) {
        //repositoryService.activateProcessDefinitionById(id);
        repositoryService
                .updateProcessDefinitionSuspensionState()
                .byProcessDefinitionId(id)
                .includeProcessInstances(true)
                .activate();
    }

总结

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在原有Activiti的教程资源上对零散的源码进行了集中整理,并增加了pdm、IDE集成Activiti插件等文件,附上部分菜单,整理不易,给分支持,后期继续分享其他资源 01 - 问候Activiti他大爷 1.Activiti简介 2.Activiti的HelloWorld实现 1.Activiti的25张表; 2.引入Activiti配置文件activiti.cfg.xml; 3.在Eclipse 上安装Activiti插件; 4.初识Activiti流程设计工具; 5.了解Activiti bpmn图表对应的 XML 文件 6.Activiti HelloWorld实现(代码层次) 7.Activiti HelloWorld实现(表数据发生的变化) 02 - Activiti流程定义 1.流程定义添加(部署) 1.Classpath加载方式; 2.Zip加载方式; 2.流程定义查询 1.查询流程定义; 2.查询某个流程定义的流程设计图片; 3.查询最新版本的流程定义集合; 3.流程定义删除 1.删除key相同的所有流程定义 4.流程定义的‘修改’ 03 - Activiti流程实例 1.构建学生请假审批流程 2.执行对象概念 3.判断流程实例状态 4.历史流程实例查询 5.历史活动查询 04 - Activiti流程变量 1.流程变量的概念 2.使用TaskService设置和获取流程变量 3.局部流程变量 4.使用RuntimeService设置和获取流程变量 5.启动流程的时候设置流程变量 6.完成任务的时候设置流程变量 05 - Activiti流程控制网关 1.连线 2.排它网关 3.并行网关 06 - Activiti任务分配 1.个人任务分配 2.多用户任务分配 3.内置用户组设计表以及IdentityService 4.组任务分配
当使用CamundaJava API生成BPMN流程并进行部署和运行时,可以按照以下步骤操作: 1. 添加Camunda依赖:在你的项目中添加Camunda的相关依赖。可以在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.camunda.bpm</groupId> <artifactId>camunda-engine</artifactId> <version>7.15.0</version> </dependency> ``` 2. 创建流程定义:使用CamundaJava API来创建BPMN流程定义。以下是一个简单的示例: ```java import org.camunda.bpm.engine.ProcessEngine; import org.camunda.bpm.engine.ProcessEngineConfiguration; import org.camunda.bpm.engine.RepositoryService; import org.camunda.bpm.engine.repository.Deployment; import org.camunda.bpm.engine.repository.ProcessDefinition; public class CamundaProcessDeploymentExample { public static void main(String[] args) { // 创建Camunda流程引擎 ProcessEngineConfiguration config = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration(); ProcessEngine processEngine = config.buildProcessEngine(); // 获取RepositoryService RepositoryService repositoryService = processEngine.getRepositoryService(); // 创建BPMN模型 BpmnModelInstance model = Bpmn.createExecutableProcess("myProcess") .startEvent() .userTask() .name("User Task") .endEvent() .done(); // 部署流程定义 Deployment deployment = repositoryService.createDeployment() .addModelInstance("myProcess.bpmn", model) .deploy(); // 获取流程定义 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .deploymentId(deployment.getId()) .singleResult(); // 输出流程定义ID System.out.println("流程定义ID: " + processDefinition.getId()); } } ``` 3. 运行流程:使用CamundaJava API来启动和执行流程实例。以下是一个简单的示例: ```java import org.camunda.bpm.engine.ProcessEngine; import org.camunda.bpm.engine.ProcessEngineConfiguration; import org.camunda.bpm.engine.RuntimeService; import org.camunda.bpm.engine.runtime.ProcessInstance; public class CamundaProcessExecutionExample { public static void main(String[] args) { // 创建Camunda流程引擎 ProcessEngineConfiguration config = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration(); ProcessEngine processEngine = config.buildProcessEngine(); // 获取RuntimeService RuntimeService runtimeService = processEngine.getRuntimeService(); // 启动流程实例 ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess"); // 输出流程实例ID System.out.println("流程实例ID: " + processInstance.getId()); } } ``` 通过以上步骤,你可以使用CamundaJava API生成BPMN流程、部署流程定义并运行流程实例。你可以根据具体需求来设计和定制你的流程定义。希望对你有帮助!如有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值