activiti工作流入门

什么是工作流?

工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。通俗来讲,就是业务上一个完整的审批流程。例如员工的请假,出差,外出采购,合同审核等等,这些过程,都是一个工作流。

工作流引擎

image

常见的工作流引擎

主流的框架有:Activiti、jBPM、Camunda 、Flowable 、还有国产的盘古BPM、云程

activiti的使用

使用流程

  1. 引入依赖并初始化数据库
    既然activiti是一个框架,那么我们肯定是需要引入对应的jar包

  2. 通过工具绘画流程图
    使用 activiti 流程建模工具(activity-designer)定义业务流程(.bpmn 文件)
    .bpmn 文件就是业务流程定义文件,通过 xml 定义业务流程。

  3. 流程定义部署;
    向 activiti 部署业务流程定义(.bpmn 文件),使用 activiti 提供的 api 向 activiti 中部署.bpmn 文件,
    通俗来讲,就是让activiti认识要使用的流程

  4. 启动一个流程实例(ProcessInstance)
    启动一个流程实例表示开始一次业务流程的运行,比如员工请假流程部署完成,如果张三要请假就可以启动一个流程实例,如果李四要请假也启动一个流程实例,两个流程的执行互相不影响,就好比定义一个java类,实例化两个对象一样,部署的流程就好比java类,启动一个流程实例就好比new一个java对象

  5. 用户查询待办任务(Task)
    因为现在系统的业务流程已经交给 activiti 管理,通过 activiti 就可以查询当前流程执行到哪了,当前用户需要办理什么任务了,这些 activiti帮我们管理了。实际上我们学习activiti也只是学习它的API怎么使用,因为很多功能activiti都已经封装好了,我们会调用就行了

  6. 用户办理任务
    用户查询待办任务后,就可以办理某个任务,如果这个任务办理完成还需要其它用户办理,比如请假单创建后由部门经理审核,这个过程也是由 activiti 帮我们完成了,不需要我们在代码中硬编码指定下一个任务办理人了

  7. 流程结束
    当任务办理完成没有下一个任务节点了,这个流程实例就完成了。

引入依赖

        <!--引入activiti的springboot启动器 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.1.0.M6</version>
            <exclusions>
                <exclusion>
                    <artifactId>mybatis</artifactId>
                    <groupId>org.mybatis</groupId>
                </exclusion>
            </exclusions>
        </dependency>

添加配置

spring:    
	activiti:
      #    false:默认,数据库表不变,但是如果版本不对或者缺失表会抛出异常(生产使用)
      #    true:表不存在,自动创建(开发使用)
      #    create_drop: 启动时创建,关闭时删除表(测试使用)
      #    drop_create: 启动时删除表,在创建表 (不需要手动关闭引擎)
      		database-schema-update: true
      #监测历史表是否存在,activities7默认不开启历史表
      		db-history-used: true
      #none:不保存任何历史数据,流程中这是最高效的
      #activity:只保存流程实例和流程行为
      #audit:除了activity,还保存全部的流程任务以及其属性,audit为history默认值
      #full:除了audit、还保存其他全部流程相关的细节数据,包括一些流程参数
      		history-level: full
      #校验流程文件,默认校验resources下的process 文件夹的流程文件
      		check-process-definitions: true

数据库连接的url添加nullCatalogMeansCurrent=true

url: jdbc:mysql://localhost:3306/guigu-oa?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&nullCatalogMeansCurrent=true

通过工具绘画流程图

使用idea插件Activiti BPMN visualizer

流程定义部署

将资源文件放入rescource中
部署方式:单个部署、压缩包部署

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProcessTest {

    @Autowired
    private RepositoryService repositoryService;

    @Test
    public void deployProcess() {
        // 流程部署
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("process/qingjia.bpmn20.xml")
                .addClasspathResource("process/qingjia.png")
                .name("请假申请流程")
                .deploy();
        System.out.println(deploy.getId());
        System.out.println(deploy.getName());
    }
}

@Test
public void deployProcessByZip() {
    // 定义zip输入流
    InputStream inputStream = this
            .getClass()
            .getClassLoader()
            .getResourceAsStream(
                    "process/qingjia.zip");
    ZipInputStream zipInputStream = new ZipInputStream(inputStream);

    // 流程部署
    Deployment deployment = repositoryService.createDeployment()
            .addZipInputStream(zipInputStream)
            .name("请假申请流程")
            .deploy();
    System.out.println("流程部署id:" + deployment.getId());
    System.out.println("流程部署名称:" + deployment.getName());
}

启动流程实例

流程定义:将bpmn文件放到activiti的三张表中,好比是java中的一个类
流程实例:好比是java中的一个实例对象(一个流程定义可以对应多个流程实例),张三可以启动一个请假流程实例,李四也可以启动一个请假流程实例,他们互不影响

@Autowired
private RuntimeService runtimeService;

@Test
public void startUpProcess() {
    //创建流程实例,我们需要知道流程定义的key
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("qingjia");
    //输出实例的相关信息
    System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
    System.out.println("流程实例id:" + processInstance.getId());
    System.out.println("当前活动Id:" + processInstance.getActivityId());
}

查询任务

每个节点都配置了Assignee,流程启动后,任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户的待办任务。

@Autowired
private TaskService taskService;

/**
 * 查询当前个人待执行的任务
 */
@Test
public void findPendingTaskList() {
    //任务负责人
    String assignee = "zhangsan";
    List<Task> list = taskService.createTaskQuery()
            .taskAssignee(assignee)//只查询该任务负责人的任务
            .list();
    for (Task task : list) {
        System.out.println("流程实例id:" + task.getProcessInstanceId());
        System.out.println("任务id:" + task.getId());
        System.out.println("任务负责人:" + task.getAssignee());
        System.out.println("任务名称:" + task.getName());
    }
}

说明:

​ 流程实例id:一个流程只有一个,标识这个流程

​ 任务id:流程每进行到某个节点,就会给这个节点分配一个任务id

输出结果如下:

​ 流程实例id:d969f534-825e-11ed-95b4-7c57581a7819
​ 任务id:d96c3f28-825e-11ed-95b4-7c57581a7819
​ 任务负责人:zhangsan
​ 任务名称:张三审批

处理当前任务

任务负责人查询待办任务,选择任务进行处理,完成任务。
完成任务后,任务自动到下一个节点

    @Test
    public void completeTask(){
        Task task = taskService.createTaskQuery()
                .taskAssignee("zhangsan")
                .singleResult();//返回一条任务
        taskService.complete(task.getId());
    }

查询已处理的任务

@Autowired
private HistoryService historyService;

/**
 * 查询已处理历史任务
 */
@Test
public void findProcessedTaskList() {
    //张三已处理过的历史任务
    List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().taskAssignee("zhangsan").finished().list();
    for (HistoricTaskInstance historicTaskInstance : list) {
        System.out.println("流程实例id:" + historicTaskInstance.getProcessInstanceId());
        System.out.println("任务id:" + historicTaskInstance.getId());
        System.out.println("任务负责人:" + historicTaskInstance.getAssignee());
        System.out.println("任务名称:" + historicTaskInstance.getName());
    }
}

其他接口

/**
 * 查询流程定义
 */
@Test
public void findProcessDefinitionList(){
    List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery()
            .orderByProcessDefinitionVersion()
            .desc()
            .list();
    //输出流程定义信息
    for (ProcessDefinition processDefinition : definitionList) {
        System.out.println("流程定义 id="+processDefinition.getId());
        System.out.println("流程定义 name="+processDefinition.getName());
        System.out.println("流程定义 key="+processDefinition.getKey());
        System.out.println("流程定义 Version="+processDefinition.getVersion());
        System.out.println("流程部署ID ="+processDefinition.getDeploymentId());
    }
}

/**
 * 删除流程定义
 */
public void deleteDeployment() {
    //部署id
    String deploymentId = "82e3bc6b-81da-11ed-8e03-7c57581a7819";
    //删除流程定义,如果该流程定义已有流程实例启动则删除时出错
    repositoryService.deleteDeployment(deploymentId);
    //设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式
    //repositoryService.deleteDeployment(deploymentId, true);
}
posted @ 2023-12-13 22:26  ︶ㄣ演戲ㄣ  阅读(66)  评论(0)    收藏  举报