Activity workflow engine

Table of contents

1. Understand the workflow

1. What is workflow

2. Workflow engine

3. Common workflow engines

4. Overview of Activiti7

4.1 Introduction to Activiti

4.2. Modeling language BPMN

4.3, Activiti use process

Two, Activiti7

1. Use of Activiti

1.1, database support

1.2, Activiti environment

1.3, Activiti common Service service interface

1.4. Process Design Tool

2. Activiti process operation

2.1. Process definition

2.2. Process definition deployment

2.3. Start the process instance

2.4. Query task

2.5, processing the current task

2.6. Query processed tasks

2.7. Other interfaces (understand)

3. Process example

3.1, what is a process instance

3.2. Associate the actual business with the activiti table (BusinessKey)

3.3. Suspend and activate the process instance

4. Task assignment

4.1. Fixed distribution

4.2. Expression assignment

4.3. Listener assignment

5. Process variables

5.1, what is a process variable

5.2, the scope of process variables

5.3. How to use process variables

5.4, ​​set the global variable

5.5. Set Local variables

6. Task group

6.1, Candidate-users candidates

6.2. Group task handling process

6.3. Key code

7. Gateway

7.1. Exclusive Gateway

7.2. Parallel Gateway

7.3, including the gateway


1. Understand the workflow

1. What is workflow

Workflow (Workflow) is to automate the management of business processes through computers. It mainly solves "the process of automatically transferring documents, information or tasks among multiple participants according to some predefined rules , so as to achieve a certain expected business goal, or promote the realization of this goal." In layman's terms, it is a complete approval process in business. For example, employees' leave, business trips, out-of-home purchases, contract review, etc., these processes are all a workflow.

2. Workflow engine

For workflow processing, if we use the original method, we need to take various documents to each person in charge to sign, and need to be continuously approved by multiple departments. This method is time-consuming and laborious. And we can use the software system to assist us in handling these approval processes, so a workflow system appears, which can greatly improve work efficiency after using the workflow system.

In the process of learning workflow, we must have seen this model: fill out the leave form -> department manager approval -> general manager approval -> personnel filing.

(1) To realize the above-mentioned process, we can achieve this approval effect through the field identification, and add a field in the business table, such as filling out the leave form with 1, department manager with 2, general manager with 3, personnel The record is marked with 4. It seems that there is no problem, and the approval effect has been achieved. But once our process changes, we need to change our code at this time, which is obviously not advisable, so is there a professional way to achieve workflow management? And it can be achieved that after the business process changes, our program does not need to be changed. If this effect can be achieved, then the adaptability of our business system will be greatly improved. In this context, a workflow engine emerged .

Why use a workflow engine to achieve business process changes, without modifying the code, and the process can be automatically advanced?

(1) Let's first talk about why the process changes without modifying the code: our workflow engine has implemented a specification, which requires that our process management has nothing to do with the status field, and it is always the next step to read the business flow chart node. When the business is updated, we only need to update the business flow chart. This enables business process changes without modifying the code.

(2) Let’s talk about the automatic advancement of the process. This principle is even simpler. Take the leave model above as an example. The workflow engine will use a table to record the current node. After filling out the leave form, it must be the turn of the department manager to approve it, so once we complete the leave form, this record will be deleted from this form, and the information of the next node department manager will be inserted In this table, when we use the information of the department manager to query this table, we can find out the relevant approval information of the department manager, and so on, so that the automatic submission of the process is realized.

3. Common workflow engines

The mainstream frameworks are: Activiti , jBPM, Camunda, Flowable, and our domestic Pangu BPM, Yuncheng

4. Overview of Activiti7

4.1 Introduction to Activiti

activiti is a workflow engine that can extract complex business processes in business systems, define them using a special modeling language BPMN, and execute business processes according to pre-defined processes. The process of the system is managed by activiti, which reduces the workload of the business system for system upgrade and transformation due to process changes, thereby improving the robustness of the system and reducing the cost of system development and maintenance.

Official website: https://www.activiti.org

4.2. Modeling language BPMN

BPM (Business Process Management) is business process management, which is a standardized construction of end-to-end business processes to continuously improve organizational business efficiency

BPM software is an IT tool that promotes the organization and adjustment of business methods and solutions between people, between people and systems, and between systems according to changes in the business environment in the enterprise. Using BPM software to model, automate, manage, monitor and optimize the entire life cycle of internal and external business processes can reduce corporate costs and increase profits

BPMN (Business Process Model And Notation) is a business process model and notation. It is a set of standard business process modeling notations. Business processes can be created using the notations provided by BPMN. Activit uses BPMN for process modeling and process execution management

BPMN2.0 is an acronym for Business Process Modeling Notation 2.0, created and continuously developed by the Business Process Management Initiative, a non-profit association. BPMN2.0 is a set of symbol specifications that use some symbols to clarify the flow chart of business process design, which can improve the communication efficiency in business modeling. Currently BPMN2.0 is the latest version, it is used for layout and visual communication in BPM context

The basic symbols of BPMN2.0 mainly include:

  • Event Event

Start: Indicates the beginning of a process

Middle: between the start and end events that occur, affecting the flow of processing

End: Indicates the end of the process

edit

  • Activities Activities

Activity is a general term for work or task. An activity can be a task or a sub-process of the current process; secondly, you can also specify different types for the activity. Common activities are as follows:

edit

  • GatewayGateWay

There are several commonly used gateways that need to be understood to represent the branching and merging of processes:

    • Exclusive gateway: only one path will be chosen

    • Parallel gateways: each path will be chosen

    • Inclusive gateway: can execute multiple lines at the same time, also set conditions on the gateway

    • Event Gateway: It is specially set for intermediate capture events, allowing multiple output streams to point to multiple different intermediate capture events. When the process is executed to the event gateway, the process is in a waiting state and needs to wait for an event to be thrown to convert the waiting state into an active state

  • Flow to Flow

A flow is a connection between two process nodes. Common flow directions include the following:

Sequence flow: Represented by a solid line with a solid arrow, it is used to specify the order in which activities are executed

Information flow: represented by a dotted line with an arrow, used to describe the flow of messages sent and received between two independent business participants (business entities/business roles)

Association: Represented by a dotted line with a line arrow, used to associate related data, text, and other artifacts with flow objects. Inputs and outputs for showcasing activities

Process example:

4.3, Activiti use process

Step 1: Introduce dependencies and initialize the database

Since activiti is a framework, we definitely need to introduce the corresponding jar package coordinates, refer to the specific code.

Step 2: Draw a flow chart through tools

Use the activiti process modeling tool (activity-designer) to define business processes (.bpmn files)

The .bpmn file is the business process definition file, which defines the business process through xml.

The third step : process definition deployment;

Deploy the business process definition (.bpmn file) to activiti, use the api provided by activiti to deploy the .bpmn file to activiti,

In layman's terms, it is to let activiti know the process to be used

Step 4: Start a process instance (ProcessInstance)

Starting a process instance means starting a business process operation. For example, the deployment of the employee leave process is completed. If Zhang San wants to ask for leave, he can start a process instance. If Li Si wants to ask for leave, he can also start a process instance. The execution of the two processes does not affect each other. , just like defining a java class and instantiating two objects, the deployment process is like a java class, starting a process instance is like new a java object

Step 5: The user queries the to-do tasks (Task)

Because the business process of the system has been handed over to activiti for management, through activiti, you can query where the current process is being executed, and what tasks the current user needs to handle. Activiti helps us manage these. In fact, when we learn activiti, we just learn how to use its API, because many functions of activiti have been packaged, and we can call them.

Step 6: User handles tasks

After the user queries the pending tasks, he can handle a certain task. If the task is completed, other users need to handle it. For example, after the leave form is created, it will be reviewed by the department manager. This process is also completed by activiti for us, and we do not need to write in the code. Hard-coded to specify the next task handler

Step Seven: End of Process

When the task processing is completed and there is no next task node, the process instance is completed.

Two, Activiti7

1. Use of Activiti

1.1, database support

Activiti operation must have the support of the database, the supported databases are: mysql, oracle, postgres, mssql, db2, h2

1.2, Activiti environment

We directly explain the introduction to Activiti in the current project: guigu-oa-parent

1.2.1. Introducing dependencies

<!--引入activiti的springboot启动器 -->
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.1.0.M6</version>
    <exclusions>
<!--除去mybatis依赖:如果你的项目中无mybatis或者mybatisPlus依赖可不加-->
        <exclusion>
            <artifactId>mybatis</artifactId>
            <groupId>org.mybatis</groupId>
        </exclusion>
    </exclusions>
</dependency>

Description: After Activiti7 is integrated with SpringBoot, the SpringSecurity security framework is integrated by default. The Activiti framework will check whether the user exists, otherwise an exception will occur.

edit

1.2.2. Add configuration

The data source project has been added, just need the following configuration

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

1.2.3, start the project

Start the project to generate the project database table

1.2.4, database table introduction

Activiti's operation support must have the support of these 25 tables, mainly to record the user subjects participating in the process, user group information, process definition, process execution information, and process historical information during the operation of the business process etc.

1. Table naming rules and functions

Observing the created tables, we found that Activiti's tables all start with act_, followed by a two-letter identifier indicating the purpose of the table, which also corresponds to the API of the service provided by Activiti:

  • ACT_RE: RE means repository, the prefix table contains process definition and process static resources (pictures, rules, etc.)
  • ACT_RU: RU represents runtime. When these tables are running, they will contain data in progress such as process instances, tasks, variables, and asynchronous tasks. Activiti only saves these data during the execution of the process instance, and deletes these records at the end of the process. This way the table can always be kept small and fast
  • ACT_HI: HI means history, these tables contain some historical data, such as historical process instances, variables, tasks, etc.
  • ACT_GE: GE means general, general data

2. Introduction to Activiti data table

table classification

Table Name

explain

general data

[ACT_GE_BYTEARRAY]

Generic process definitions and process resources

[ACT_GE_PROPERTY]

system related properties

Process History

[ACT_HI_ACTINST]

Historical Process Examples

[ACT_HI_ATTACHMENT]

Historical Process Attachments

[ACT_HI_COMMENT]

historical descriptive information

[ACT_HI_DETAIL]

Detailed information on historical process runs

[ACT_HI_IDENTITYLINK]

User relationship during historical process running

[ACT_HI_PROCINST]

Historical Process Examples

[ACT_HI_TASKINST]

Examples of historical tasks

[ACT_HI_VARINST]

Variable information in the historical process running

Process definition table

[ACT_RE_DEPLOYMENT]

Deployment unit information

[ACT_RE_MODEL]

model information

[ACT_RE_PROCDEF]

Deployed Process Definition

run instance table

[ACT_RU_EVENT_SUBSCR]

runtime events

[ACT_RU_EXECUTION]

Runtime process execution instance

[ACT_RU_IDENTITYLINK]

Runtime user relationship information, storing information about task nodes and participants

[ACT_RU_JOB]

runtime job

[ACT_RU_TASK]

runtime task

[ACT_RU_VARIABLE]

runtime variable table

1.3, Activiti common Service service interface

Briefly introduce the implementation classes of each Service:

  • RepositoryService

Activiti's resource management class, which is responsible for deploying process definitions and managing process resources. When using Activiti, the process deployment needs to be completed first, and the business flow chart designed by the modeling tool will be deployed through the RepositoryService

  • RuntimeService

Activiti's process operation management class is used to start a new process instance and obtain relevant information about process execution. The process definition is used to determine the structure and behavior of each node in a process, and the process instance is an execution of the corresponding process definition, which can be understood as the relationship between classes and objects in Java

  • TaskService

Activiti's task management class is used to handle various tasks in business operations, such as querying tasks assigned to users or groups, creating new tasks, assigning tasks, determining and completing a task

  • HistoryService

Activiti's history management class can query historical information. When executing a process, the engine will save a lot of data, such as the start time of the process instance, the participants of the task, the time to complete the task, the execution path of each process instance, and so on. This service mainly obtains these data through the query function

  • ManagementService

Activiti's engine management class provides management and maintenance functions for the Activiti process engine. These functions are not used in workflow-driven applications and are mainly used for daily maintenance of the Activiti system

1.4. Process Design Tool

The IDEA version is less than or equal to 2019, and the Activiti plug-in actiBPM can be used. IDEA larger than this version can use the Activiti BPMN visualizer plug-in to draw process design.

Today our protagonist is: Activiti Modeler

Activiti Modeler is a front-end plug-in for online process design officially provided by Activiti. Developers can easily design processes online, save process models, deploy to process definitions, etc. Our subsequent projects also integrate Activiti Modeler to draw process definitions.

1.4.1. Download activiti-explorer

Official website download: Get started | Activiti

1.4.2. Decompress and obtain the deployment package

Unzip activiti-5.22.0.zip and get activiti-explorer.war in the activiti-5.22.0\wars directory

1.4.3, department activiti-explorer.war

Put activiti-explorer.war in the tomcat deployment directory and start tomcat

1.4.4. Visit activiti-explorer

http://localhost:8080/activiti-explorer

Default login account: kermit kermit

There are many functions above, we only need to pay attention to the process design, as shown in the figure below:

Click on the picture above: Process --> New Model --> Enter the model name (leave) --> Create

2. Activiti process operation

2.1. Process definition

We define a leave process

2.1.1. Create a new model

2.1.2. Start node

2.1.3. Task nodes

2.1.4. End node

2.1.5. Set node properties

Specify the label name: Zhang San Approval, node task leader: zhangsan

Specify the label name: Li Si Approval, node task leader: lisi

2.1.5. Set process definition key

2.1.6, save the process definition model

2.1.7. Download process definition file

The download file is: qingjia.bpmn20.xml

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
  <process id="qingjia" isExecutable="true">
    <startEvent id="sid-14A3E2A6-84E4-49E0-BF92-3DABD741430B"></startEvent>
    <userTask id="sid-38632C81-C407-4F0D-944D-FC30F90637A3" name="张三审批" activiti:assignee="zhangsan"></userTask>
    <sequenceFlow id="sid-081A176E-6756-4C4C-B36C-2649B12CFC5D" sourceRef="sid-14A3E2A6-84E4-49E0-BF92-3DABD741430B" targetRef="sid-38632C81-C407-4F0D-944D-FC30F90637A3"></sequenceFlow>
    <userTask id="sid-655780D5-8492-494F-9E30-2CFD6691E98D" name="李四审批" activiti:assignee="lisi"></userTask>
    <sequenceFlow id="sid-7DCE821D-4AE0-4F27-9811-80B575E7A758" sourceRef="sid-38632C81-C407-4F0D-944D-FC30F90637A3" targetRef="sid-655780D5-8492-494F-9E30-2CFD6691E98D"></sequenceFlow>
    <endEvent id="sid-7EE28419-BC61-49AC-8990-C63C4D2F7C0D"></endEvent>
    <sequenceFlow id="sid-2E583A5C-265A-4C05-B5E1-7F5DB98291F1" sourceRef="sid-655780D5-8492-494F-9E30-2CFD6691E98D" targetRef="sid-7EE28419-BC61-49AC-8990-C63C4D2F7C0D"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_qingjia">
    <bpmndi:BPMNPlane bpmnElement="qingjia" id="BPMNPlane_qingjia">
      <bpmndi:BPMNShape bpmnElement="sid-14A3E2A6-84E4-49E0-BF92-3DABD741430B" id="BPMNShape_sid-14A3E2A6-84E4-49E0-BF92-3DABD741430B">
        <omgdc:Bounds height="30.0" width="30.0" x="93.5" y="75.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-38632C81-C407-4F0D-944D-FC30F90637A3" id="BPMNShape_sid-38632C81-C407-4F0D-944D-FC30F90637A3">
        <omgdc:Bounds height="80.0" width="100.0" x="168.5" y="50.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-655780D5-8492-494F-9E30-2CFD6691E98D" id="BPMNShape_sid-655780D5-8492-494F-9E30-2CFD6691E98D">
        <omgdc:Bounds height="80.0" width="100.0" x="313.5" y="50.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-7EE28419-BC61-49AC-8990-C63C4D2F7C0D" id="BPMNShape_sid-7EE28419-BC61-49AC-8990-C63C4D2F7C0D">
        <omgdc:Bounds height="28.0" width="28.0" x="458.5" y="76.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-7DCE821D-4AE0-4F27-9811-80B575E7A758" id="BPMNEdge_sid-7DCE821D-4AE0-4F27-9811-80B575E7A758">
        <omgdi:waypoint x="268.5" y="90.0"></omgdi:waypoint>
        <omgdi:waypoint x="313.5" y="90.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-081A176E-6756-4C4C-B36C-2649B12CFC5D" id="BPMNEdge_sid-081A176E-6756-4C4C-B36C-2649B12CFC5D">
        <omgdi:waypoint x="123.5" y="90.0"></omgdi:waypoint>
        <omgdi:waypoint x="168.5" y="90.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-2E583A5C-265A-4C05-B5E1-7F5DB98291F1" id="BPMNEdge_sid-2E583A5C-265A-4C05-B5E1-7F5DB98291F1">
        <omgdi:waypoint x="413.5" y="90.0"></omgdi:waypoint>
        <omgdi:waypoint x="458.5" y="90.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

2.1.8. Download process definition picture

Right-click the picture above, save the picture as: qingjia.png

2.1.9. Put resource files into the project

Create a new process resource folder under the service-oa module resources

Put qingjia.bpmn20.xml and qingjia.png into the process directory

2.2. Process definition deployment

Deploying the process defined above in the designer to the activiti database is the process definition deployment. Add and deploy the bpmn and png files of the process definition to activiti one by one by calling the api of activiti, or pack the two files into a zip package for deployment.

2.2.1. Single file deployment method

package com.atguigu;

import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


@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());
    }
}

2.2.2. Compressed package deployment method

@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());
}

2.2.3. Operation database table

The three tables for operating activiti after the process definition is deployed are as follows:

The act_re_deployment process defines the deployment table, adding a record for each deployment

act_re_procdef process definition table, deploying each new process definition will add a record to this table

act_ge_bytearray process resource table

2.3. Start the process instance

Process definition: put the bpmn file into the three tables of activiti, like a class in java

Process instance: It is like an instance object in java (a process definition can correspond to multiple process instances), Zhang San can start a leave process instance, Li Si can also start a leave process instance, they do not affect each other

@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());
}

Operational Data Sheet

act_hi_actinst process instance execution history

Act_hi_identitylink process participating user history information

act_hi_procinst process instance historical information

act_hi_taskinst process task history information

act_ru_execution process execution information

Participating user information of act_ru_identitylink process

act_ru_task task information

2.4. Query task

Each node is configured with Assignee. After the process starts, the person in charge of the task can query the tasks that he needs to process currently, and the tasks that are queried are all to-do tasks of the user.

@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());
    }
}

illustrate:

Process instance id: There is only one process, which identifies the process

Task id: Every time the process reaches a certain node, a task id will be assigned to this node

The output is as follows:

Process instance id: d969f534-825e-11ed-95b4-7c57581a7819

Task id: d96c3f28-825e-11ed-95b4-7c57581a7819

Task leader: zhangsan

Task name: Approval by Zhang San

2.5, processing the current task

The task leader queries the to-do tasks, selects the tasks to process, and completes the tasks.

/**
 * 完成任务
 */
@Test
public void completTask(){
    Task task = taskService.createTaskQuery()
            .taskAssignee("zhangsan")  //要查询的负责人
            .singleResult();//返回一条

    //完成任务,参数:任务id
    taskService.complete(task.getId());
}

After the task is completed, the task automatically goes to the next node

2.6. Query processed tasks

@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());
    }
}

2.7. Other interfaces (understand)

/**
 * 查询流程定义
 */
@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);
}

3. Process example

3.1, what is a process instance

Process definition ProcessDefinition and process instance ProcessInstance are important concepts of Activiti, similar to the relationship between Java classes and Java instances

Starting a process instance means starting a business process operation. For example, the deployment of the employee leave process is completed. If Zhang San wants to ask for leave, he can start a process instance. If Li Si wants to ask for leave, he can also start a process instance. The execution of the two processes does not affect each other. , just like defining a java class and instantiating two objects, the deployment process is like a java class, starting a process instance is like new a java object

3.2. Associate the actual business with the activiti table (BusinessKey)

For example, if we fill out a leave form, there must be a unique identification of the leave form. We usually use this identification to associate activiti. This identification is called businesskey in activiti

BusinessKey: business identifier, usually the primary key of the business, the business identifier and the process identifier correspond one-to-one, the business identifier comes from the business system, and the storage of the business identifier is to associate and query the data of the business system according to the business identifier

For example: when the leave process starts a process instance, the id of the leave request can be stored in activiti as a business identifier. In the future, the id of the leave request can be obtained by querying the process instance information of activiti, so as to query the business system database to obtain the leave request information

/**
 * 启动流程实例,添加businessKey
 */
@Test
public void startUpProcessAddBusinessKey(){
    String businessKey = "1";
    // 启动流程实例,指定业务标识businessKey,也就是请假申请单id
    ProcessInstance processInstance = runtimeService.
            startProcessInstanceByKey("qingjia",businessKey);
    // 输出
    System.out.println("业务id:"+processInstance.getBusinessKey());
}

3.3. Suspend and activate the process instance

In some cases, it may be necessary to suspend the currently running process instead of directly deleting it due to process changes. After the process is suspended, it will not be executed;

3.3.1. All process instances are suspended

The operation process is defined as a suspended state, and all process instances below the process definition are suspended:

The process definition is in a suspended state. This process definition will not allow new process instances to be started. At the same time, all process instances under this process definition will be suspended and suspended.

@Test
public void suspendProcessInstance() {
    ProcessDefinition qingjia = repositoryService.createProcessDefinitionQuery().processDefinitionKey("qingjia").singleResult();
    // 获取到当前流程定义是否为暂停状态 suspended方法为true是暂停的,suspended方法为false是运行的
    boolean suspended = qingjia.isSuspended();
    if (suspended) {
        // 暂定,那就可以激活
        // 参数1:流程定义的id  参数2:是否激活    参数3:时间点
        repositoryService.activateProcessDefinitionById(qingjia.getId(), true, null);
        System.out.println("流程定义:" + qingjia.getId() + "激活");
    } else {
        repositoryService.suspendProcessDefinitionById(qingjia.getId(), true, null);
        System.out.println("流程定义:" + qingjia.getId() + "挂起");
    }
}

3.3.2. A single process instance hangs

Operate the process instance object, execute the suspend operation for a single process, if a process instance is suspended, the process will not continue to execute, and an exception will be reported when the current task of the process instance is completed;

@Test
public void SingleSuspendProcessInstance() {
    String processInstanceId = "8bdff984-ab53-11ed-9b17-f8e43b734677";
    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
    //获取到当前流程定义是否为暂停状态   suspended方法为true代表为暂停   false就是运行的
    boolean suspended = processInstance.isSuspended();
    if (suspended) {
        runtimeService.activateProcessInstanceById(processInstanceId);
        System.out.println("流程实例:" + processInstanceId + "激活");
    } else {
        runtimeService.suspendProcessInstanceById(processInstanceId);
        System.out.println("流程实例:" + processInstanceId + "挂起");
    }
}

4. Task assignment

There are three ways to assign tasks

  1. fixed allocation
  2. UEL expression assignment
  3. listener assignment

4.1. Fixed distribution

Specify a fixed task leader in the previous business process modeling, such as: Assignee: zhangsan/lisi

4.2. Expression assignment

activiti uses UEL expressions. UEL is part of the java EE6 specification. UEL is the unified expression language. activiti supports two UEL expressions: UEL-value and UEL-method.

4.2.1、UEL-value

New: an overtime process

As shown in the picture:

assignee1 This variable is a process variable of activiti

We start the process instance. The method of starting the instance is basically the same as the previous method. The only difference is that a parameter is added at startup

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

/**
 * 启动流程实例
 */
@Test
public void startUpProcess01() {
    Map<String, Object> variables = new HashMap<>();
    variables.put("assignee1","zhangsan");
    variables.put("assignee2","lisi");
    //创建流程实例,我们需要知道流程定义的key
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("qingjia01", variables);
    //输出实例的相关信息
    System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
    System.out.println("流程实例id:" + processInstance.getId());
}

4.2.2, UEL-method

As shown in the picture:

userBean is a bean in the spring container, which means calling the bean's getUsername(int id) method.

Manager approval: ${userBean.getUsername(1)}

Personnel approval: ${userBean.getUsername(2)}

package com.atguigu.process.bean;

import org.springframework.stereotype.Component;

@Component
public class UserBean {

    public String getUsername(int id) {
        if(id == 1) {
            return "zhangsan";
        }
        if(id == 2) {
            return "lisi";
        }
        return "admin";
    }
}

Deploy and start

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

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

When the process instance is started, the bean method will be called, the parameter is: 1, after the manager approves, then the bean method is called, the parameter is: 2

4.3. Listener assignment

Use the listener method to specify the person in charge, so you don't need to specify the assignee when designing the process.

The task listener is to execute custom java logic or expression when the corresponding task-related event occurs

Event options include:

Create:任务创建后触发
Assignment:任务分配后触发
Delete:任务完成后触发
All:所有事件发生都触发

Define the task listening class, and the class must implement the org.activiti.engine.delegate.TaskListener interface

package com.atguigu.process.bean;

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;

public class MyTaskListener implements TaskListener {

    @Override
    public void notify(DelegateTask delegateTask) {
        if(delegateTask.getName().equals("经理审批")){
            //这里指定任务负责人
            delegateTask.setAssignee("zhangsan");
        } else if(delegateTask.getName().equals("人事审批")){
            //这里指定任务负责人
            delegateTask.setAssignee("lisi");
        }
    }
}

Configure the listener

Both manager approval and personnel approval can be set to the same monitor

Deploy and test

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

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

When the process instance is started, the MyTaskListener listening method will be called

5. Process variables

5.1, what is a process variable

Process variables play a very important role in activiti. Process operation sometimes depends on process variables, business systems and activiti

Process variables are indispensable in combination, and process variables are variables that activiti sets according to management needs when managing workflow.

For example: when the leave application process flows, if the number of leave days is more than 2 days, it will be reviewed by the general manager, otherwise it will be directly reviewed by the department manager.

The number can be set as a process variable and used during process flow.

5.2, the scope of process variables

The role of a process variable can be a process instance, but it can also be a task (task) or an execution instance

5.2.1, global variables

The default scope of process variables is the process instance. When the scope of a process variable is the process instance, it can be called a global variable

The variable name in the global variable is not allowed to be repeated. If you set a variable with the same name, the value set later will overwrite the variable value set before.

5.2.2, local variable

Tasks and execution instances are only for one task and one execution instance range, and the scope is not as large as the process instance, which is called local variables.

Because the scope of Local variables does not affect each other in different tasks or different execution instances, the variable names can be the same without any influence. The local variable name can also be the same as the global variable name, it has no effect.

5.3. How to use process variables

Using process variables through UEL expressions

1. We have also used UEL expressions to set the task handler before, such as ${assignee1}, activiti obtains the value of the UEL expression, that is, the value of the process variable assignee1, and assigns the value as the person in charge of the task

2. We can also use UEL expressions on the connection between tasks to determine the direction of the process, such as ${day > 2 } and ${day <= 2}, day is a process variable name, and the execution of UEL expressions the result is boolean

5.4, ​​set the global variable

5.4.1. Set variables when starting the process

Set the process variable when starting the process, and the scope of the variable is the entire process instance.

Set the process variable through Map<key,value>, multiple variables can be set in the map, this key is the name of the process variable

This is the previous example code

@Test
public void startUpProcess() {
    Map<String, Object> variables = new HashMap<>();
    variables.put("assignee1", "zhangsan");
    variables.put("assignee2", "lisi");
    //创建流程实例,我们需要知道流程定义的key
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("qingjia", variables);
    //输出实例的相关信息
    System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
    System.out.println("流程实例id:" + processInstance.getId());
}

5.4.2. Set process variables when handling tasks

Its scope is the entire process instance . If the key of the set process variable already has the same name in the process instance, the variable set later will replace the variable set earlier.

Simulation example code:

@Test
public void completTask() {
    Task task = taskService.createTaskQuery()
            .taskAssignee("zhangsan")  //要查询的负责人
            .singleResult();//返回一条

    Map<String, Object> variables = new HashMap<>();
    variables.put("assignee2", "zhao");
    //完成任务,参数:任务id
    taskService.complete(task.getId(), variables);
}

5.4.3, through the current process instance settings

The global variable is set through the process instance id, and its scope is the entire process instance , which must not be completed.

Simulation example code:

@Test
public void processInstanceIdSetVariables() {
    Map<String, Object> variables = new HashMap<>();
    variables.put("assignee2", "wang");
    runtimeService.setVariables("1c347a90-82c6-11ed-96ca-7c57581a7819", variables);
}

5.5. Set Local variables

The scope of local process variables is only available under the current task node

When a task is processed, a local process variable is set. The currently running process instance can only be used before the end of the task. The variable cannot be used in the current process instance after the task ends.

Simulation example code:

@Test
public void completLocalTask() {
    Task task = taskService.createTaskQuery()
            .taskAssignee("zhangsan")  //要查询的负责人
            .singleResult();//返回一条

    // 设置local变量,作用域为该任务
    taskService.setVariableLocal(task.getId(),"assignee2","li");
    // 查看local变量
    System.out.println(taskService.getVariableLocal(task.getId(), "assignee2"));
    //完成任务,参数:任务id
    taskService.complete(task.getId());
}

6. Task group

6.1, Candidate-users candidates

1. Demand

In the process definition, the task leader is fixed in the assignee of the task node, and the participant is fixed in the .bpmn file when the process is defined. If you want to temporarily change the task leader, you need to modify the process definition. The system scalability is very poor. In response to this situation, we can set multiple candidates for the task, and select participants from the candidates to complete the task

2. Set task candidates

6.2. Group task handling process

Step 1: Query Group Tasks

Specify a candidate and query the candidate's current to-do tasks

Candidates cannot handle tasks

Step 2: Pick up (claim) tasks

All candidates for this group of quests can pick up

Turn the candidate's group task into a personal task, and the original candidate becomes the person in charge of the task

If you do not want to handle the task after picking it up

need to pick up

Step 3: Query personal tasks

The query method is the same as the personal task part, and the personal task that the user is responsible for is queried according to the assignee

Step Four: Handle Personal Tasks

6.3. Key code

6.3.1, deployment and start

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

    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("jiaban04");
    System.out.println(processInstance.getId());
}

6.3.2. Query group tasks

@Test
public void findGroupTaskList() {
    //查询组任务
    List<Task> list = taskService.createTaskQuery()
            .taskCandidateUser("zhangsan01")//根据候选人查询
            .list();
    for (Task task : list) {
        System.out.println("----------------------------");
        System.out.println("流程实例id:" + task.getProcessInstanceId());
        System.out.println("任务id:" + task.getId());
        System.out.println("任务负责人:" + task.getAssignee());
        System.out.println("任务名称:" + task.getName());
    }
}

6.3.2. Pick up group tasks

@Test
public void claimTask(){
    //拾取任务,即使该用户不是候选人也能拾取(建议拾取时校验是否有资格)
    //校验该用户有没有拾取任务的资格
    Task task = taskService.createTaskQuery()
            .taskCandidateUser("zhangsan01")//根据候选人查询
            .singleResult();
    if(task!=null){
        //拾取任务
        taskService.claim(taskId, "zhangsan01");
        System.out.println("任务拾取成功");
    }
}

Zhang San 01 has picked up the task, but Zhang San 02 cannot pick it up

6.3.3. Query personal to-do tasks

The query method is the same as personal task query

@Test
public void findGroupPendingTaskList() {
    //任务负责人
    String assignee = "zhangsan01";
    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());
    }
}

6.3.4. Handle personal tasks

with personal tasks

@Test
public void completGroupTask() {
    Task task = taskService.createTaskQuery()
            .taskAssignee("zhangsan01")  //要查询的负责人
            .singleResult();//返回一条
    taskService.complete(task.getId());
}

6.3.5. Return group tasks

If an individual does not want to handle the group task, he can return the group task, after which the user is no longer the person in charge of the task

@Test
public void assigneeToGroupTask() {
    String taskId = "d96c3f28-825e-11ed-95b4-7c57581a7819";
    // 任务负责人
    String userId = "zhangsan01";
    // 校验userId是否是taskId的负责人,如果是负责人才可以归还组任务
    Task task = taskService
            .createTaskQuery()
            .taskId(taskId)
            .taskAssignee(userId)
            .singleResult();
    if (task != null) {
        // 如果设置为null,归还组任务,该 任务没有负责人
        taskService.setAssignee(taskId, null);
    }
}

6.3.6. Task handover

Task handover, the task leader hands over the task to other candidates to handle the task

@Test
public void assigneeToCandidateUser() {
    // 当前待办任务
    String taskId = "d96c3f28-825e-11ed-95b4-7c57581a7819";
    // 校验zhangsan01是否是taskId的负责人,如果是负责人才可以归还组任务
    Task task = taskService
            .createTaskQuery()
            .taskId(taskId)
            .taskAssignee("zhangsan01")
            .singleResult();
    if (task != null) {
        // 将此任务交给其它候选人zhangsan02办理该 任务
        taskService.setAssignee(taskId, "zhangsan02");
    }
}

7. Gateway

Gateways are used to control the flow of processes and are usually used together with process variables.

7.1. Exclusive Gateway

  • Exclusive gateway: only one path will be chosen

When there is such a scenario in your process: leave application, within two days, the approval process of the department manager is over, and the general manager needs to approve it directly after two days, at this time, an exclusive gateway is needed

7.2. Parallel Gateway

  • Parallel (parallel) gateways: all paths will be selected at the same time

When such a scenario occurs: the leave application needs to be approved by both the department manager and the general manager. If there is no before and after the two, both people need to approve it before proceeding to the next node for personnel approval. At this time, a parallel gateway is required

The main difference from exclusive gateways is that parallel gateways do not resolve conditions. Even if a condition is defined in the sequence flow, it will be ignored.

7.3, including the gateway

Inclusive gateway: Multiple routes can be executed at the same time, and conditions can also be set on the gateway, which can be regarded as a combination of exclusive gateway and parallel gateway.

When such a scenario occurs: the leave application must be approved by the general manager of the department for more than or equal to 2 days, and the department manager for less than 2 days, and the leave application must be approved by the HR manager. At this time, the gateway needs to be included

Guess you like

Origin blog.csdn.net/qq_61544409/article/details/129719335