Activiti 6.0 概述与 Hello World 快速入门(Spring Boot 打包)

目录

Activiti 概述 与 下载

Hello World

安装流程设计器插件

绘制工作流程图

IDEA 编码实现工作流

Activiti 核心 API 预览


Activiti 概述 与 下载

1、工作流(Workflow):是对工作流程及其各个操作步骤之间业务规则的抽象、概况和描述。

2、工作流模型:将工作流程中的工作如何前后组织在一起的逻辑和规则,在计算机中以恰当的模型表达并对其实施计算。

3、工作流要解决的问题是实现某个业务目标、利用计算机在多个参与者之间按某种预定规则自动传递文档、信息或者任务。

4、主流的工作流框架:Activiti、OSWorkflow、JBoss 的 JBPM、Apache 的 ofBiz 等。生活中有很多的流程管理,比如请假流程、报销流程、审批流程等等。

5、Activiti 历史:JBPM 4 的时候团队内部发生分歧,其中部分开发人员脱离了大部队(JBoss),出来独立写出了 Activiti5;JBoss 则继续 JBPM 的开发,后续又有了 JBPM 5 ...。

6、所以 Activiti 5 基本等同于 JBPM4,2016 年 11 月开源了 Activiti 5.22.0,2017 年 5 月开源了 Activiti 6.0.0,2018 年开始开源 Activiti 7.X。Activiti 7 分为了 Activiti Core 与 Activiti Cloud 两个方向,更倾向于云环境、微服务。

7、Activiti 易于与 Spring、Spring boot、Spring cloud 集成,BPM 全称 Business Process Management - 业务流程管理

8、Activiti 支持主流的数据库(官方文档):

Activiti database type Example JDBC URL Notes

h2

jdbc:h2:tcp://localhost/activiti

Default configured database

mysql

jdbc:mysql://localhost:3306/activiti?autoReconnect=true

Tested using mysql-connector-java database driver

oracle

jdbc:oracle:thin:@localhost:1521:xe

 

postgres

jdbc:postgresql://localhost:5432/activiti

 

db2

jdbc:db2://localhost:50000/activiti

 

mssql

jdbc:sqlserver://localhost:1433;databaseName=activiti (jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver) OR jdbc:jtds:sqlserver://localhost:1433/activiti (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)

Tested using Microsoft JDBC Driver 4.0 (sqljdbc4.jar) and JTDS Driver

Activiti 官网:https://www.activiti.org

Activiti Github 开源地址:https://github.com/Activiti/Activiti

Activiti v7.X 官方开发手册:https://activiti.gitbook.io/activiti-7-developers-guide/

Activiti v6.X 官方开发手册:https://www.activiti.org/userguide/

Activiti v5.X 官方开始手册:https://www.activiti.org/5.x/userguide/

本文暂时使用 Activiti 6.X 版本,如果需要使用 Activiti 做微服务开发的,则应该使用 Activiti 7.X 版本。

Hello World

1、千里之行,始于足下。学习一个新框架得先有一个 Hello World 压压惊,否则会很迷茫。

2、本文环境:Java JDK 1.8 + IDEA 2018 +Maven 3.1.6 + Activiti 6.0.0 + H2 Database + Spring Boot 2.1.4 进行开发。

1)使用 Maven 管理,不再去 Activiti 官网下载 jar 包,然后导入到项目中

2)暂时使用 H2 内存数据库,让 Activiti 的表和数据先直接在内存数据库中使用。

3、特别提醒

1)Acticiti 工作流开发,第一步是需要绘制工作流程图(本文开头的那种图),第二步就是编码。

2)下载 Acticiti 6.0.0 开发包或者源码可以看到,里面提供了针对各种数据库的 sql 文件,然后实际中并不需要手动去执行这些 sql 脚本,因为在后台代码中构建流程引擎(ProcessEngine)的时候,它可以自动执行 sql 建表脚本创建好 28 张表

3)Activiti 6.0.0  有 28 张表,使用 Activiti API 操作工作流的时候,Activiti 会自动操作自己的数据库表。所以对于 activiti 的 28 张数据库表,前期并不需要关心,对我们来说是透明的,入门之后可以再去深入了解。

安装流程设计器插件

官网介绍地址:https://www.activiti.org/userguide/#eclipseDesignerInstallation

1、eclipse、sts、idea 都有绘制 activiti 流程图的插件,但官方文档介绍的是 eclipse(sts本质也是eclipse),所以这里也采用 在 sts 上安装流程图插件。(注:在 sts 插件上绘制好流程图后,本人更喜欢 IDEA 编码,所以后续只需要将 sts 中创建好的 .bpmn 文件拷贝过去即可)

1、这里选择在线安装插件 activiti 插件,打开 help -> Install New Software 安装新的软件(插件),在 Install 面板中,点击 Add 按钮添加插件名称与地址:

Name: Activiti BPMN designer (名称可以随意取)
Location: http://activiti.org/designer/update/

2、点击 "Next" 下一步,然后会联网进行下载,之后在 "Install Detail" 面板直接 "Next",然后进入 "Review license" 查看许可证面板,点击第一项 "I accept ..." 同意,最后点击 "Finish" 完成安装。

3、安装过程中可能会弹框提示,选择安装所有即可,然后会提示重启,重启之后可以点击菜单 "Window -> Show View -> Other..." 看到 activiti 插件:

4、设置保存 bpmn 流程图时,同时保存一张同名的 .png 图片:

绘制工作流程图

1、安装好插件之后就可以开始绘制工作流程图了,随便在某个目录上右键,然后 "New -> Other...-> Activiti -> Activiti Diagram" 创建 Activiti 流程图:

2、基本工作流程图绘制并不难,从右侧的选项中拖到到中间即可,开始的黑色圆圈为开始事件,User Task 表示用户任务,带黑色叉的矩形为排它网关(用于条件判断),末尾的粗黑线圆圈为结束事件,箭头线表示顺序流。

3、排它网关用于条件判断,比如同意则继续往后走、不同意则重新返回,在网关上选择箭头按住拖到目标按钮上即可。

4、在空白处点击,为整个流程设置 id 与 name,在每个按钮上点击,为他们设置 id 与 name 值,这些值将来都是 .bpmn 文件中的属性值,代码中会操作它们,它们也会被自动处理到数据库中。

5、为3个用户任务设置 form 表单参数,即此任务执行需要的参数,因为操作比较长,无法全部做成动图,所以只演示添加1个属性。type 表示参数类型,required 表示参数是否必须要填。

6、用户任务设置的参数表示工作流中用户提供的参数,而这些参数需要在排它网关中进行判断,比如主管审批结果输入为 y 时才能继续往后走,否则输入 n 时,则应该重新回到 "填写审批信息"。当排它网关未作任何限制时,则主管和人事无论输入什么,都会继续往后走,显然这不满足我们的需求,则此时应该设置排它网关的条件,它类似 EL 表达式的写法 ${条件判断} ,|| 表示或,&& 表示与,条件判断的值是上一个用户任务中的 form 表单参数。

7、至此工作流程图绘制完毕,第一次可能比较难理解,但是多画几次,然后结合后面的代码,则容易理解。

注意:这个流程图(.bpmn文件)本质就是一个 .xml 文件,可以用记事本、或者浏览器等打开就可以看出来,后面会提供完整的文件,所以即使没画出来,也没关系,并不影响后面的代码运行。

IDEA 编码实现工作流

1、因为本人习惯使用 IDEA,所以在 IDEA 中新建一个 Maven 项目,Java SE 应用,直接在 main 方法中进行简单使用。

2、将 sts 中插件绘制好的流程文件 .bpmn 拷贝到 IDEA 项目的类路径下,当然直接使用 sts 、eclipse 开发也是一样的。

3、pom.xml 文件内容如下。

spring-boot-starter-parent 与 spring-boot-maven-plugin 是方便 maven 项目打包的,可选

slf4j-api 与 slf4j-log4j12 用于做日志框架,可选

activiti-spring-boot-starter-basic:activiti 与 spring boot 集成的启动器,里面包含了 activiti-engine 引擎,以及 activiti 与 spring 的集成,以及 jdbc 。必选,

h2 是内存数据库,必须使用一个数据库,当然可以换成其它数据库。

guava 方便做集合、字符串等操作,可选

junit 方便做单元测试,可选

<?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 http://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.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>wmx.com</groupId>
    <artifactId>activiti-first</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <!--https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>

        <!--官网地址:https://www.activiti.org/userguide/#_getting_started_2-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter-basic</artifactId>
            <version>6.0.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.183</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>27.0-jre</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

4、只建了一个 MainApp.java 文件操作工作流,编码分为 4 步:1)创建流程引擎 -> 2)部署流程定义文件 -> 3)启动运行流程、4)处理流程任务。内容如下:

package com.activiti.study;

import com.google.common.collect.Maps;
import org.activiti.engine.*;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.impl.form.DateFormType;
import org.activiti.engine.impl.form.StringFormType;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class MainApp {
    private static Logger LOGGER = LoggerFactory.getLogger(MainApp.class);

    public static void main(String[] args) throws ParseException {
        LOGGER.info(" App start...");

        //1、创建流程引擎
        ProcessEngine processEngine = getProcessEngine();
        //2、部署流程定义文件
        ProcessDefinition processDefinition = getProcessDefinition(processEngine);
        //3、启动运行流程
        ProcessInstance processInstance = getProcessInstance(processEngine, processDefinition.getId());
        //4、处理流程任务
        handlingTasks(processEngine, processInstance);
        LOGGER.info(" App quit...");
    }

    /**
     * 处理流程任务
     *
     * @param processEngine
     * @param processInstance
     * @throws ParseException
     */
    private static void handlingTasks(ProcessEngine processEngine, ProcessInstance processInstance) throws ParseException {
        Scanner scanner = new Scanner(System.in);//从控制台手动输入数据
        while (processInstance != null && !processInstance.isEnded()) {
            TaskService taskService = processEngine.getTaskService();//获取任务服务
            List<Task> taskList = taskService.createTaskQuery().list();
            for (Task task : taskList) {
                LOGGER.info("当前待处理任务id [{}],任务名称 [{}]", task.getId(), task.getName());
                Map<String, Object> dataMap = getStringObjectMap(processEngine, scanner, task);
                taskService.complete(task.getId(), dataMap);//提交任务/完成任务
                //重新获取流程实例
                processInstance = processEngine.getRuntimeService()
                        .createProcessInstanceQuery()
                        .processInstanceId(processInstance.getId())
                        .singleResult();
            }
        }
        scanner.close();
    }

    /**
     * 设置当前任务的表单参数。从控制台输入
     *
     * @param processEngine
     * @param scanner
     * @param task
     * @return
     * @throws ParseException
     */
    private static Map<String, Object> getStringObjectMap(ProcessEngine processEngine, Scanner scanner, Task task) throws ParseException {
        FormService formService = processEngine.getFormService();//表单服务
        TaskFormData taskFormData = formService.getTaskFormData(task.getId());//根据任务id获取任务表单数据对象
        List<FormProperty> formPropertyList = taskFormData.getFormProperties();//获取表单属性
        Map<String, Object> dataMap = Maps.newHashMap();
        for (FormProperty formProperty : formPropertyList) {
            String line = null;
            if (StringFormType.class.isInstance(formProperty.getType())) {
                LOGGER.info("请输入 {}", formProperty.getName());
                line = scanner.nextLine();
                dataMap.put(formProperty.getId(), line);
            } else if (DateFormType.class.isInstance(formProperty.getType())) {
                LOGGER.info("请输入 {}", formProperty.getName());
                line = scanner.nextLine();
                dataMap.put(formProperty.getId(), DateUtils.parseDate(line, "yyyy-MM-dd HH:mm:ss"));
            } else {
                LOGGER.warn("暂时不支持此类型 [{}]", formProperty.getType());
            }
            LOGGER.info("您成功输入 [{}]", line);
        }
        return dataMap;
    }

    /**
     * 启动运行流程
     *
     * @param processEngine
     * @param processDefinitionId
     */
    private static ProcessInstance getProcessInstance(ProcessEngine processEngine, String processDefinitionId) {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId);
        String processDefinitionKey_ = processInstance.getProcessDefinitionKey();
        LOGGER.info("启动流程,流程key [{}] ", processDefinitionKey_);//输出:启动流程,流程key [approvalFor2Level]
        return processInstance;
    }

    /**
     * 部署流程定义文件
     *
     * @param processEngine
     * @return
     */
    private static ProcessDefinition getProcessDefinition(ProcessEngine processEngine) {
        RepositoryService repositoryService = processEngine.getRepositoryService();//获取存储服务
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();//创建部署构建器
        //通过类路径下的 .bpmn 文件进行构建。.bpmn 文件的本质其实就是一个定义好的 .xml 文件
        deploymentBuilder.addClasspathResource("approvalFor2Level.bpmn");
        //部署流程定义文件。此时 Activiti 会自动将 .bpmn 中的数据添加到数据库中,以备后续数据库操作
        Deployment deployment = deploymentBuilder.deploy();
        String deploymentId = deployment.getId();
        String deploymentKey = deployment.getKey();
        String deploymentName = deployment.getName();
        Date deploymentTime = deployment.getDeploymentTime();

        //输出:部署id [1],部署key [null],部署名称 [null],部署时间 [Wed Jul 24 09:40:00 CST 2019]
        LOGGER.info("部署id [{}],部署key [{}],部署名称 [{}],部署时间 [{}]", deploymentId, deploymentKey, deploymentName, deploymentTime);

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
        String processDefinitionName = processDefinition.getName();
        String processDefinitionId = processDefinition.getId();
        String processDefinitionKey = processDefinition.getKey();
        //输出:流程定义文件名 [二级审批流程],流程id [approvalFor2Level:1:4],流程key [approvalFor2Level]
        LOGGER.info("流程定义文件名 [{}],流程id [{}],流程key [{}]", processDefinitionName, processDefinitionId, processDefinitionKey);
        return processDefinition;
    }

    /**
     * 创建流程引擎
     *
     * @return
     */
    private static ProcessEngine getProcessEngine() {
        //StandaloneInMemProcessEngineConfiguration:标准的基于内存数据库的流程引擎配置.
        ProcessEngineConfiguration pecfg = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
        //buildProcessEngine:通过流程引擎配置构建流程引擎,此时会自动创建 activiti 的 28 张表
        ProcessEngine processEngine = pecfg.buildProcessEngine();
        String name = processEngine.getName();
        String version = ProcessEngine.VERSION;
        LOGGER.info("流程引擎名称 [{}],版本 [{}]", name, version);//输出:流程引擎名称 [default],版本 [6.0.0.4]
        return processEngine;
    }
}

5、整个项目源码:https://github.com/wangmaoxiong/activitiFirst,核心就是 pom.xml 文件、MainApp.java、approvalFor2Level.bpmn 流程文件、log4j.properties 日志文件。

1)上面的 hello World 要想成功运行,之前绘制好的 .bpmn 文件是必不可少的,因为内容较长,所以不再这里粘贴,从这里获取:https://github.com/wangmaoxiong/activitiFirst/tree/master/src/main/resources

2)其中可以修改 log4j.properties 的日志输出级别为 DEBUG log4j.rootLogger=DEBUG ,console,logFile,就会发现应用启动到结束,它在不停的操作数据库,做 sql 操作。

6、因为使用的是 StandaloneInMemProcessEngineConfiguration 流程引擎配置,它的源码如下,显然它默认使用的是 h2 内存数据库,create-drop 表示应用启动时自动建表,应用关闭时自动删除,数据不会持久化到磁盘。

public class StandaloneInMemProcessEngineConfiguration extends StandaloneProcessEngineConfiguration {
    public StandaloneInMemProcessEngineConfiguration() {
        this.databaseSchemaUpdate = "create-drop";
        this.jdbcUrl = "jdbc:h2:mem:activiti";
    }
}

7、启动应用,测试如下:

上面只是测试了正常情况下,全部通过的情景,也可以放弃提交,主管或者人事输入 n 拒绝通过等否则情况都是没问题的

Activiti 核心 API 预览

1、ProcessEngine:流程引擎,这是最重要的 API,通过它可以获取其它的 API。

2、RepositoryService:存储服务,负责对流程定义和部署的管理,比如流程图片以及 xml 文件。

3、RuntimeService:流程运行服务,用于对流程运行过程的控制,如启动流程实例、暂停、挂起、继续等

4、TaskService:流程任务服务,用于对人工任务的管理(如增删改查),设置操作权限。

5、HistoryService:历史记录相关服务接口。

6、FormService:表单服务。

7、IdentityService:身份服务,提供对流程角色数据进行管理的 API,这些角色数据包括用户组、用户及它们之间的关系。

8、ManagementService:提供对流程引擎进行管理和维护的服务。

发布了458 篇原创文章 · 获赞 884 · 访问量 92万+

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/97135508
今日推荐