Activiti 核心 API 在 Spring Boot 2.x 中的简易使用教程

文章目录

      • 1 摘要
      • 2 准备工作
      • 3 核心代码
        • 3.1 创建流程引擎
        • 3.2 部署流程
        • 3.3 启动流程
        • 3.4 查询代理人当前的流程信息
        • 3.5 完成当前节点任务
        • 3.6 查询流程历史记录
        • 3.7 删除流程实例
      • 4 推荐参考资料
      • 5 Github 源码

1 摘要

Spring Boot 目前(2020年)已经成为Java后台的主流框架,各种技术都有关于 Spring Boot 的集成方案。本文将介绍 Activiti 工作流框架核心 API 在 Spring Boot 2.x 中的简易使用教程。

2 准备工作

(1) SpringBoot 2.x 快速集成 Activiti

(2) 绘制一个 Activiti BPMN 流程图 — 2020-07-22

3 核心代码

3.1 创建流程引擎

创建工作流的方式可以分为3种

第一种,通过代码配置:

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 创建流程引擎(通过代码的方式)
     */
    @Test
    public void createActivitiEngineByCode() {
        ProcessEngineConfiguration engineConfiguration = ProcessEngineConfiguration
                .createStandaloneProcessEngineConfiguration();
        engineConfiguration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        engineConfiguration.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/demo_activiti?useUnicode=true&characterEncoding" +
                "=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8&useSSL" +
                "=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true");
        engineConfiguration.setJdbcUsername("root");
        engineConfiguration.setJdbcPassword("root");

        /**
         * false: 不会自动创建表,没有表,则抛异常
         * true: 假如没有表,则自动创建
         * create-drop: 流程开始的时候创建表,流程结束之后删除表
         */
        engineConfiguration.setDatabaseSchemaUpdate("true");
        ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
        System.out.println("通过代码创建流程引擎成功!!!");
    }

第二种,通过指定的 xml 配置文件:

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 创建流程引擎(通过配置文件的方式)
     */
    @Test
    public void createActivitiEngineByCfg() {
        ProcessEngineConfiguration engineConfiguration = ProcessEngineConfiguration
                .createProcessEngineConfigurationFromResource("activiti.cfg.xml");
        ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
        System.out.println("使用 activiti.cfg.xml 创建流程引擎 !!!");
    }

配置文件:

./activiti-workflow/src/main/resources/activiti.cfg.xml
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver">property>
        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/demo_activiti?useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8&useSSL=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true">property>
        <property name="jdbcUsername" value="root">property>
        <property name="jdbcPassword" value="root">property>

        
        <property name="databaseSchemaUpdate" value="true">property>

    bean>

beans>

第三种,在 SpringBoot 的配置文件中配置 Activiti

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 创建流程引擎(读取 application.yml 中 activiti 配置)
     */
    @Test
    public void createProcessEngine() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        System.out.println("通过 ProcessEngines 获取流程引擎");
    }

配置文件application.yml:

./activiti-workflow/src/main/resources/application.yml
## spring config
spring:
  activiti:
    check-process-definitions: false
    database-schema-update: true
    process-definition-location-prefix: classpath:/
  datasource:
    url: "jdbc:mysql://127.0.0.1:3306/demo_activiti?useUnicode=true&characterEncoding=utf8\
      &useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8\
      &useSSL=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true\
      &nullCatalogMeansCurrent=true"
    username: root
    password: "root"
    hikari:
      driver-class-name: com.mysql.cj.jdbc.Driver
      

application.yml 中配置 Activiti 信息,数据源信息是可以重用的,无需配置两份。Activiti 已经完美集成到 Spring Boot 项目中。

3.2 部署流程

部署流程即将先前创建的流程图(bpmn)文件部署到系统中,流程文件会被保存到数据库中,流程图中的执行逻辑也会被保存下来,后边的流程执行将按照这个流程图来进行。同一张流程图可以部署多次,不过个人认为不建议这么做,一个流程图只部署一套。

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 部署工作流
     */
    @Test
    public void deploy() {
        // resource 目录下 bpmn 文件
        String bpmnResource = "processes/student_leave.bpmn";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        Deployment deployment = processEngine.getRepositoryService()
                .createDeployment()
                .addClasspathResource(bpmnResource)
                .name("studentLeave")
                .category("demoCategory")
                .deploy();
        System.out.println("部署 id: " + deployment.getId());
        System.out.println("部署名称: " + deployment.getName());
        System.out.println("部署策略: " + deployment.getCategory());

    }

3.3 启动流程

流程部署之后相当于创建了模板,启动流程,将会按照这个模板来执行。启动的流程相当于这个流程模板的实例,同一个部署的流程可以启动多个实例。不同的用户发起请求,就启动一个新的流程实例。

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 启动工作流
     */
    @Test
    public void startProcess() {
        // 进程 key:bpmn 文件中工作流 id
        String processKey = "student_leave";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 获取流程实例
        ProcessInstance instance = runtimeService.startProcessInstanceByKey(processKey);
        System.out.println("流程实例 id: " + instance.getId());
        System.out.println("流程定义 id: " + instance.getProcessDefinitionId());
    }

3.4 查询代理人当前的流程信息

可以查询到属于该代理人执行的任务节点,可以理解为某个用户待处理的任务。只有当流程执行到当前代理人的节点的时候,才能够查询到。

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 查询办理人当前流程信息
     */
    @Test
    public void queryTask() {
        // 办理人
        String assignee = "张三";
        // 进程 key:bpmn 文件中工作流 id
        String processKey = "student_leave";
        // 获取任务服务
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        // 创建一个查询任务对象
        TaskQuery taskQuery = taskService.createTaskQuery();
        // 办理人列表
        List<Task> taskList = taskQuery.taskAssignee(assignee).processDefinitionKey(processKey).list();
        // 遍历列表
        taskList.stream().forEach(task -> {
            System.out.println("任务的办理人: " + task.getAssignee());
            System.out.println("任务的 id: " + task.getId());
            System.out.println("任务的名称: " + task.getName());
            System.out.println("任务的所有者: " + task.getOwner());
            System.out.println("任务的策略: " + task.getCategory());
            System.out.println("任务的创建时间: " + task.getCreateTime());
            System.out.println("任务的执行 id: " + task.getExecutionId());
            System.out.println("任务的 kay: " + task.getTaskDefinitionKey());
            System.out.println("任务的流程 id: " + task.getProcessDefinitionId());
            System.out.println("------------------------------");
        });
    }

3.5 完成当前节点任务

轮到某个代理人处理任务的时候,该代理人可以完成该节点任务,流程即执行到下一个节点。完成节点任务必须的参数是任务节点的 id,不需要代理人的信息,因此需要在执行完成节点任务前,对代理人身份等信息进行校验。完成节点任务时,Activiti 支持批注信息

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 完成当前节点流程任务
     */
    @Test
    public void completeTask(){
        String taskId = "2505";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 完成任务
        processEngine.getTaskService().complete(taskId);
        System.out.println("当前任务执行完毕");

    }

3.6 查询流程历史记录

查询流程的历史记录,包含的信息包括每个节点开始的时间、代理人、审批信息等。当需要查询流程进度的时候可以用到。

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 查询历史记录
     */
    @Test
    public void queryHistory3() {
        // 流程 id
        String processId = "student_leave_3:1:7504";
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        List<HistoricTaskInstance> historyList = engine.getHistoryService()
                .createHistoricTaskInstanceQuery()
                .processDefinitionId(processId)
                .list();
        historyList.stream().forEach(history -> {
            System.out.println("任务的办理人: " + history.getAssignee());
            System.out.println("任务的 id: " + history.getId());
            System.out.println("流程实例 id: " + history.getProcessInstanceId());
            System.out.println("任务的名称: " + history.getName());
            System.out.println("任务的所有者: " + history.getOwner());
            System.out.println("任务的策略: " + history.getCategory());
            System.out.println("任务的创建时间: " + history.getCreateTime());
            System.out.println("任务的执行 id: " + history.getExecutionId());
            System.out.println("任务的 kay: " + history.getTaskDefinitionKey());
            System.out.println("任务的流程 id: " + history.getProcessDefinitionId());
            System.out.println("------------------------------");

        });
    }

3.7 删除流程实例

当一个审批流程需要取消的时候,可以将流程的实例进行删除,包括流程的历史记录也可以删除。

./activiti-workflow/src/test/java/com/ljq/demo/springboot/activiti/ActivitiWorkflowApplicationTests.java
    /**
     * 删除流程实例(包括历史记录)
     */
    @Test
    public void deleteProcessInstance3() {
        // 流程实例 id
        String processInstanceId = "10001";
        // 删除原因
        String deleteReason = "需要删除";
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        ProcessInstance processInstance = engine.getRuntimeService().createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        if (Objects.isNull(processInstance)) {
            engine.getHistoryService().deleteHistoricProcessInstance(processInstanceId);
        } else {
            engine.getRuntimeService().deleteProcessInstance(processInstanceId, deleteReason);
            engine.getHistoryService().deleteHistoricProcessInstance(processInstanceId);
        }

    }

以上即为 Activiti 的部分核心 API 使用,简单的流程操作已经足够了

4 推荐参考资料

【官方文档】Activiti User Guide

SpringBoot activiti 系列教程

Activiti工作流实战开发

Activiti 删除部署与流程实例

5 Github 源码

Gtihub 源码地址 : https://github.com/Flying9001/springBootDemo

个人公众号:404Code,分享半个互联网人的技术与思考,感兴趣的可以关注.
404Code

你可能感兴趣的:(Java)