美文网首页工作流引擎
Spring Boot 集成 Activiti 工作流引擎 极简

Spring Boot 集成 Activiti 工作流引擎 极简

作者: 光剑书架上的书 | 来源:发表于2021-06-13 15:37 被阅读0次

    Activiti 简介

    Java 通用型工作流引擎:Activiti。

    源代码:https://github.com/Activiti/Activiti

    Activiti is the leading lightweight, java-centric open-source BPMN engine supporting real-world process automation needs.

    Activiti 项目是一项新的基于Apache许可的开源BPM平台,从基础开始构建,旨在提供支持新的BPMN 2.0标准。

    Activiti 是一种轻量级,可嵌入的BPM引擎,而且还设计适用于可扩展的云架构。 Activiti将提供宽松的 Apache 许可2.0,同时促进Activiti BPM引擎和BPMN 2.0的匹配。

    Activiti 的核心服务组件

    1.RepositoryService:提供一系列管理流程部署和流程定义的API。
    2.RuntimeService:在流程运行时对流程实例进行管理与控制。
    3.TaskService:对流程任务进行管理,例如任务提醒、任务完成和创建任务等。
    4.IdentityService:提供对流程角色数据进行管理的API,这些角色数据包括用户组、用户及它们之间的关系。
    5.ManagementService:提供对流程引擎进行管理和维护的服务。
    6.HistoryService:对流程的历史数据进行操作,包括查询、删除这些历史数据。
    7.FormService:表单服务。

    Activiti应用场景:

    多人协作的(或者需要动态变动)的业务流程场景。

    业务流程模型 BPMN xml 配置文件

    一个xml文件,activiti去解析这个文件,了解我们到底想干什么事。

    test01.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="test01" name="test01" isExecutable="true">
            <startEvent id="sid-d0c54d06-2073-4018-8381-e5e43f1b5578" name="Start"/>
    
            <serviceTask id="sid-0396a986-7e6b-4634-883b-1ee7db9aeb45"
                         activiti:exclusive="true"
                         name="Step1"
                         activiti:class="com.example.actividemo.ServiceTask1">
                <extensionElements>
                    <activiti:field name="text1">
                        <activiti:string><![CDATA[test1]]></activiti:string>
                    </activiti:field>
                </extensionElements>
            </serviceTask>
    
            <sequenceFlow id="sid-05a29cc5-7a04-4282-be89-4d83f943774b" sourceRef="sid-d0c54d06-2073-4018-8381-e5e43f1b5578"
                          targetRef="sid-0396a986-7e6b-4634-883b-1ee7db9aeb45"/>
    
            <serviceTask id="sid-c43c4370-4407-4746-893f-dcee3e4e9936"
                         activiti:exclusive="true"
                         name="Step2"
                         activiti:class="com.example.actividemo.ServiceTask2">
                <extensionElements>
                    <activiti:field name="text2">
                        <activiti:string><![CDATA[test2]]></activiti:string>
                    </activiti:field>
                </extensionElements>
            </serviceTask>
    
            <endEvent id="sid-665b6b28-9b81-4ab7-ba77-6eb50da3c810" name="End"/>
            <sequenceFlow id="sid-26493bea-97f7-44d4-b7ec-255266dcb8ab" sourceRef="sid-0396a986-7e6b-4634-883b-1ee7db9aeb45"
                          targetRef="sid-c43c4370-4407-4746-893f-dcee3e4e9936"/>
            <sequenceFlow id="sid-9f0f635b-4e97-4e95-b1fd-c9996bf659af" sourceRef="sid-c43c4370-4407-4746-893f-dcee3e4e9936"
                          targetRef="sid-665b6b28-9b81-4ab7-ba77-6eb50da3c810"/>
        </process>
    </definitions>
    
    

    其中,activiti:class="com.example.actividemo.ServiceTask1"activiti:class="com.example.actividemo.ServiceTask2"

    对应到代码里:

    package com.example.actividemo;
    
    
    import org.activiti.engine.delegate.DelegateExecution;
    import org.activiti.engine.delegate.Expression;
    import org.activiti.engine.delegate.JavaDelegate;
    
    public class ServiceTask1 implements JavaDelegate {
        //流程变量
        private Expression text1;
    
        //重写委托的提交方法
        @Override
        public void execute(DelegateExecution execution) {
            System.out.println("serviceTask1 已经执行已经执行!");
            String value1 = (String) text1.getValue(execution);
            System.out.println(value1);
            execution.setVariable("var1", new StringBuffer(value1).reverse().toString());
        }
    }
    
    package com.example.actividemo;
    
    
    import org.activiti.engine.delegate.DelegateExecution;
    import org.activiti.engine.delegate.Expression;
    import org.activiti.engine.delegate.JavaDelegate;
    
    public class ServiceTask2 implements JavaDelegate {
        //流程变量
        private Expression text2;
    
        //重写委托的提交方法
        @Override
        public void execute(DelegateExecution execution) {
            System.out.println("serviceTask2 已经执行已经执行!");
            String value1 = (String) text2.getValue(execution);
            System.out.println(value1);
            execution.setVariable("var1", new StringBuffer(value1).reverse().toString());
        }
    }
    

    Spring Boot 集成 Activiti 项目实战

    创建 Spring Boot 工程,目录结构如下:

    .
    ├── HELP.md
    ├── activi-demo.iml
    ├── mvnw
    ├── mvnw.cmd
    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   └── com
        │   │       └── example
        │   │           └── actividemo
        │   │               ├── ActivitiController.java
        │   │               ├── ActivityConsumerService.java
        │   │               ├── ActivityConsumerServiceImpl.java
        │   │               ├── Application.java
        │   │               ├── ServiceTask1.java
        │   │               └── ServiceTask2.java
        │   └── resources
        │       ├── application.properties
        │       ├── static
        │       ├── templates
        │       └── test01.bpmn20.xml
        └── test
            └── java
                └── com
                    └── example
                        └── actividemo
                            └── ApplicationTests.java
    
    14 directories, 14 files
    
    

    源代码如下:

    ActivitiController

    package com.example.actividemo;
    
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/activiti")
    public class ActivitiController {
    
        @Autowired
        private ActivityConsumerService activityConsumerService;
    
        /**
         * 注册流程
         *
         * @return
         */
        @RequestMapping("/createDeployment")
        public Boolean createDeployment() {
            return activityConsumerService.createDeployment();
        }
    
        /**
         * 启动流程
         *
         * @return
         */
        @RequestMapping("/startActivityDemo")
        public Boolean startActivityDemo() {
            return activityConsumerService.startActivityDemo("test01");
        }
    
        /**
         * 获取待办
         *
         * @return
         */
        @RequestMapping("/getTaskList")
        public List getTaskList() {
            return activityConsumerService.getTaskList();
        }
    
        /**
         * 提交
         *
         * @param taskId
         * @return
         */
        @RequestMapping("/complete")
        public boolean complete(String taskId) {
            return activityConsumerService.complete(taskId);
        }
    
        /**
         * 根据流程id直接结束流程
         *
         * @return
         * @paramru
         */
        @RequestMapping("/deleteProcessInstance")
        public boolean deleteProcessInstance(String runId) {
            return activityConsumerService.deleteProcessInstance(runId);
        }
    
    
    }
    

    ActivityConsumerService

    package com.example.actividemo;
    
    
    import java.util.List;
    
    public interface ActivityConsumerService {
        boolean createDeployment();
    
        boolean startActivityDemo(String key);
    
        List getTaskList();
    
        boolean complete(String taskId);
    
        boolean deleteProcessInstance(String runId);
    }
    
    

    ActivityConsumerServiceImpl

    package com.example.actividemo;
    
    
    import org.activiti.engine.HistoryService;
    import org.activiti.engine.RepositoryService;
    import org.activiti.engine.RuntimeService;
    import org.activiti.engine.TaskService;
    import org.activiti.engine.repository.DeploymentBuilder;
    import org.activiti.engine.runtime.ProcessInstance;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service("activityService")
    public class ActivityConsumerServiceImpl implements ActivityConsumerService {
    
        @Autowired
        private RuntimeService runtimeService;
        @Autowired
        private TaskService taskService;
        @Autowired
        private HistoryService historyService;
        @Autowired
        private RepositoryService repositoryService;
    
        /**
         * 注册一个流程
         *
         * @return
         */
        @Override
        public boolean createDeployment() {
            DeploymentBuilder builder = repositoryService.createDeployment();
            builder.addClasspathResource("test01.bpmn20.xml");
            builder.deploy();
            return true;
        }
    
        /**
         * 查询待办
         *
         * @return
         */
        public List getTaskList() {
            return historyService.createHistoricActivityInstanceQuery().list();
        }
    
    
        /**
         * 根据流程key开启一个流程
         *
         * @param key
         * @return
         */
        @Override
        public boolean startActivityDemo(String key) {
            ProcessInstance test01 = runtimeService.startProcessInstanceByKey(key);
            String id = test01.getId();
            System.out.println("流程id=" + id);
            return true;
        }
    
        /**
         * 根据任务id提交任务
         *
         * @param taskId
         * @return
         */
        @Override
        public boolean complete(String taskId) {
            taskService.complete(taskId);
            return true;
        }
    
        /**
         * 根据流程id直接结束流程
         *
         * @param runId
         * @return
         */
        @Override
        public boolean deleteProcessInstance(String runId) {
            runtimeService.deleteProcessInstance(runId, "结束");
            return true;
        }
    
    
    }
    

    Application

    package com.example.actividemo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    
    @SpringBootApplication(exclude = {
            org.activiti.spring.boot.SecurityAutoConfiguration.class
    })
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
    }
    
    

    ServiceTask1 、ServiceTask2

    package com.example.actividemo;
    
    
    import org.activiti.engine.delegate.DelegateExecution;
    import org.activiti.engine.delegate.Expression;
    import org.activiti.engine.delegate.JavaDelegate;
    
    public class ServiceTask1 implements JavaDelegate {
        //流程变量
        private Expression text1;
    
        //重写委托的提交方法
        @Override
        public void execute(DelegateExecution execution) {
            System.out.println("serviceTask1 已经执行已经执行!");
            String value1 = (String) text1.getValue(execution);
            System.out.println(value1);
            execution.setVariable("var1", new StringBuffer(value1).reverse().toString());
        }
    }
    
    package com.example.actividemo;
    
    
    import org.activiti.engine.delegate.DelegateExecution;
    import org.activiti.engine.delegate.Expression;
    import org.activiti.engine.delegate.JavaDelegate;
    
    public class ServiceTask2 implements JavaDelegate {
        //流程变量
        private Expression text2;
    
        //重写委托的提交方法
        @Override
        public void execute(DelegateExecution execution) {
            System.out.println("serviceTask2 已经执行已经执行!");
            String value1 = (String) text2.getValue(execution);
            System.out.println(value1);
            execution.setVariable("var1", new StringBuffer(value1).reverse().toString());
        }
    }
    

    项目配置文件 application.properties

    server.port=8080
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/activi_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=88888888
    spring.activiti.check-process-definitions=false
    spring.activiti.process-definition-location-prefix=classpath:*
    spring.activiti.process-definition-location-suffixes=.bpmn20.xml
    

    Maven 项目配置文件 pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.5.1</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>activi-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>activi-demo</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>1.8</java.version>
            <activiti.version>6.0.0</activiti.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.activiti</groupId>
                <artifactId>activiti-engine</artifactId>
                <version>${activiti.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.activiti</groupId>
                <artifactId>activiti-spring</artifactId>
                <version>${activiti.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.activiti</groupId>
                <artifactId>activiti-spring-boot-starter-basic</artifactId>
                <version>${activiti.version}</version>
            </dependency>
    
            <!-- Activiti 流程图 -->
            <dependency>
                <groupId>org.activiti</groupId>
                <artifactId>activiti-common-rest</artifactId>
                <version>${activiti.version}</version>
            </dependency>
            <!-- Activiti 在线设计 -->
            <dependency>
                <groupId>org.activiti</groupId>
                <artifactId>activiti-modeler</artifactId>
                <version>5.22.0</version>
                <exclusions>
                    <exclusion>
                        <artifactId>spring-beans</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-context</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-core</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-tx</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-web</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-security-config</artifactId>
                        <groupId>org.springframework.security</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-security-core</artifactId>
                        <groupId>org.springframework.security</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-security-crypto</artifactId>
                        <groupId>org.springframework.security</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-security-web</artifactId>
                        <groupId>org.springframework.security</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>spring-webmvc</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>activation</artifactId>
                        <groupId>javax.activation</groupId>
                    </exclusion>
                    <exclusion>
                        <artifactId>commons-io</artifactId>
                        <groupId>commons-io</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
    
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    

    运行测试

    先部署任务:http://127.0.0.1:8080/activiti/createDeployment

    然后启动工作流实例:http://127.0.0.1:8080/activiti/startActivityDemo

    运行输出:

    serviceTask1 已经执行已经执行!
    test1
    serviceTask2 已经执行已经执行!
    test2
    流程id=7501
    

    查看历史流程:http://127.0.0.1:8080/activiti/getTaskList

    [
      {
        "id": "10003",
        "processInstanceId": "10001",
        "processDefinitionId": "test01:3:5044",
        "startTime": "2021-06-13T07:20:19.009+00:00",
        "endTime": "2021-06-13T07:20:19.010+00:00",
        "durationInMillis": 1,
        "deleteReason": null,
        "activityId": "sid-d0c54d06-2073-4018-8381-e5e43f1b5578",
        "activityName": "Start",
        "activityType": "startEvent",
        "executionId": "10002",
        "assignee": null,
        "taskId": null,
        "calledProcessInstanceId": null,
        "tenantId": "",
        "persistentState": {
          "executionId": "10002",
          "durationInMillis": 1,
          "endTime": "2021-06-13T07:20:19.010+00:00",
          "assignee": null,
          "deleteReason": null
        },
        "time": "2021-06-13T07:20:19.009+00:00",
        "inserted": false,
        "deleted": false,
        "updated": false
      },
      ...
    ,
      {
        "id": "7514",
        "processInstanceId": "7508",
        "processDefinitionId": "test01:3:5044",
        "startTime": "2021-06-13T06:47:16.733+00:00",
        "endTime": "2021-06-13T06:47:16.733+00:00",
        "durationInMillis": 0,
        "deleteReason": null,
        "activityId": "sid-665b6b28-9b81-4ab7-ba77-6eb50da3c810",
        "activityName": "End",
        "activityType": "endEvent",
        "executionId": "7509",
        "assignee": null,
        "taskId": null,
        "calledProcessInstanceId": null,
        "tenantId": "",
        "persistentState": {
          "executionId": "7509",
          "durationInMillis": 0,
          "endTime": "2021-06-13T06:47:16.733+00:00",
          "assignee": null,
          "deleteReason": null
        },
        "time": "2021-06-13T06:47:16.733+00:00",
        "inserted": false,
        "deleted": false,
        "updated": false
      }
    ]
    

    工作流的数据库表数据:

    数据库共28张表。一些比较重要的表有:

    1. act_ru_execution 执行对象表
    2. act_ru_task 用户任务表
    3. act_hi_actinst 活动节点历史表
    4. act_hi_procinst 流程实例历史表
    5. act_hi_taskinst 历史任务表

    参考资料

    https://www.cnblogs.com/qq376324789/p/12023530.html
    https://www.jianshu.com/p/972613558ba1

    相关文章

      网友评论

        本文标题:Spring Boot 集成 Activiti 工作流引擎 极简

        本文链接:https://www.haomeiwen.com/subject/vwqweltx.html