俯瞰开源工作流引擎Activiti「建议收藏」

俯瞰开源工作流引擎Activiti「建议收藏」Activiti是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,采用了宽松的ApacheLicence2.0开源协议,因此Activiti一经推出,就得到了开源社区的大力支持,在开源社区的支持下,Activiti吸引了很多的工作流专家参与到该项目中,并且也促使了Activiti在工作流领域的创新。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

写作背景

  在办公纸质时代甚至现在,许多流程审核采用手工递纸张表单的方式,一级一级审批签字,工作效率非常低下,而且对于数据统计以及生成报表的功能,需要经过大量的手工操作才能实现。随着计算机的普及以及互联网时代的到来,这些工作的参与者只需要在计算机的系统中填入工作内容,系统就会按照定义好的流程自动执行,各级审批者可以得到工作的信息并做出相应的审批和管理操作。数据统计以及报表的生成也由系统代为完成,这样大大提高了工作效率,在这种背景下,各种的工作流应用以及中间件应运而生。
  两年前,初入公司在营销平台就开始为营销活动申请专门定制了工作流审核平台–甜橙金融营销自助平台。今年在接管新平台后有些老业务需要迁移,在迁移过程中发现很多业务都有这种一级审核、二级审核甚至多级审核机制。随着自助平台定制化需求越来越多,流程与业务耦合性增强;以及老业务平台审核方案产生多套临时业务申请表,维护临时表越来越困难。为了实现这种业务与流程的分离,启发了脑海中的思考,是不是可以将流程从业务中单独剥离出来做统一的流程管理。

目录



一、工作流介绍

  在了解 Activiti 之前我们先了解一下什么是工作流,什么是工作流建模,以及工作流要解决的问题:
  工作流,是对工作流程及其各操作步骤之间业务规则的抽象、概括、描述。工作流建模,即将工作流程中的工作如何前后组织在一起的逻辑和规则在计算机中以恰当的模型进行表示并对其实施计算。
这里写图片描述
  工作流要解决的主要问题是:为实现某个业务目标,在多个参与者之间,利用计算机,按某种预定规则自动传递文档、信息或者任务。


BPMN2.0

  计算机在近时代的发展,工作流被广泛应用于电信、软件、制造、金融和办公自动化领域,随着工作流技术的兴起,为了给全部业务的参与者提供易于理解的标准标记法,由业务流程管理倡议组织(BPMI),开发出了“业务流程建模标记法” (Business Process Modeling Notation, BPMN), BPMN规范的发布是为了让业务流程的全部参与人员对流程可以进行可视化管理,提供一套让所有参与人员都易于理解的语言和标记,为业务流程的设计人员(非技术人员)和流程的实现人员(技术人员)建立起一座桥梁.。BPMI组织于2005年并入OMG组织,当前BPMN规范由OMG组织进行维护:
  2004年发布 BPMN 1.0规范。
  2008年1月发布 BPMN 1.1规范。
  2011年1月发布 BPMN 2.0规范,并且全称改为 Business Process Model And Notation(业务流程模型和符号)。


元素

  使用BPMN 2.0的目的是建立简单并且易懂的业务流程模型,但是同时又需要处理高度复的业务流程,因此要解决这两个矛盾的要求,需要在规范中定义标准的图形和符号。BPMN定义了5个基础的元素类别:

  • 流对象(Flow Objects),在一个业务流程中,流对象是用于定义行为的图形元素,主要有事件(Events)、活动(Activities)和网关(Gateways)三种流对象。
  • 数据(Data):主要有数据对象(Data Objects)、数据输入(Data Inputs) 、数据输出(Data Inputs)和数据存储(Data Stores) 4种元素。
  • 连接对象(Connecting Objects):用于连接流对象,主要有4种连接流对象的方式,包括顺序流(Sequence Flows)、消息流(Message Flows)、关联(Associations)和数据关联(Data Associations) 。
  • 泳道(Swimlanes):泳道提供了两种途径用于组织基础的模型元素,分别是池(Pools)和道(Lanes) 。
  • 制品(Artifacts):制品主要用于为流程提供附加信息,当前制品包括组(Group)和注释(Text Annotation) 。

  以上的元素分类以及下面表格中所列的元素,均是BPMN规范中元素的组成部分,每个对象均有自己对应的图形。下面的表格给出了各个元素的图形及其描述。

元素 图形 描述
事件(Events) 这里写图片描述 发生在流程执行过程中的事情
活动(Activities) 这里写图片描述 在流程执行过程中执行的工作
网关(Gateways) 这里写图片描述 控制流程的分支和聚合
顺序流(Sequence Flows) 这里写图片描述 表示流对象的前后执行顺序
消息流(Message Flows) 这里写图片描述 表示公开流程或协作模型里参与者之间的消息、交互
关联(Association) 这里写图片描述 为流程中的元素关联信息或数据
池(Pool) 这里写图片描述 我们使用池来表示流程的参与者
道(Lane) 这里写图片描述 我们使用道对池内的活动进行分组
数据对象(Data Object) 这里写图片描述 数据对象是一个显示活动是如何需要或产生数据的
消息(Message) 这里写图片描述 消息主要用于描述流程参与者之间的沟通内容
组(Group) 这里写图片描述 对元素进行分类
注释(Text Annotation) 这里写图片描述 给元素附加信息,便于阅读

  以上是 BPMN 规范中定义的基本元素,在这些元素的基础上,会产生很多子元素,例如网关(Gateways),还可以细分为排他网关、并行网关等,详细分类见下图。
这里写图片描述


BPMN 2.0 xml 结构

  一份遵循BPMN 2.0 规范的流程描述文件,除了可以用流程元素的图形定义,还可以用 XML 语法规范定义,这样流程描述文件就可在不同的流程引擎中使用,只要该流程引擎遵守 BPMN 2.0规范,例如可以用 标签来表示用户任务。
  除了 BPMN2.0规范的元素及其属性外,工作流引擎的供应商还可以在不改变已有属性的前提下,在这些规范的基础上添加额外的属性,但是添加的属性不能与已有的属性产生冲突,而且还需要简单易懂。 Activiti 扩展了额外的属性,为了不产生冲突,属性名称统一用 “activiti:” 开头,后面再拼接属性名。例如,属性 activiti:class=”com.bestpay.DemoService”。


二、Activiti 介绍

  Activiti是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,采用了宽松的Apache Licence 2.0开源协议,因此Activiti一经推出,就得到了开源社区的大力支持,在开源社区的支持下, Activiti吸引了很多的工作流专家参与到该项目中,并且也促使了Activiti在工作流领域的创新。
  Activiti的创始人Tom Baeyens是jBPM的创始人,由于在jBPM的未来架构上产生意见分歧, Tom Baeyens在2010年离开了JBoss并加入Alfresco公司,Tom Baevens的离开使得jBPM5完全放弃了jBPM4的架构,基于Drools Flow重新开发。而在2010年的5月,Tom Baeyens发布了第一个Activiti版本(5.0alphal),由此看来,Activiti更像是jBPM4的延续,也许为了让其看起来更像jBPM4的延续,Activiti团队直接将Activiti的第一个版本定义为5.0。
Activiti


服务组件

  在 Activiti 中,流程引擎的实例对象是 ProcessEngine, 当创建了了流程引擎实例后,在ProcessEngine中会初始化一系列服务组件,这些组件提供了大部分操作流程引擎数据的业务方法,它们就好像J2EE中的Service层,可以使用ProcessEngine中的getXXXService方法得到这些组件的实例。一个ProcessEngine主要有以下实例,如下图。
这里写图片描述

  • RepositoryService: 提供一系列管理流程定义和流程部署的API。
  • RuntimeService: 在流程运行时对流程实例进行管理与控制。
  • TaskService: 对流程任务进行管理,例如任务提醒、任务完成和创建任务等。
  • IdentityService:提供对流程角色数据进行管理的API,这些角色数据包括用户组、用户及它们之间的关系。
  • MangementService:提供对流程引擎进行管理和维护的服务。
  • HistoryService:对流程的历史数据进行操作,包括查询、删除这些历史数据。
  • DynamicBpmnService:使用该服务,可以不需要重新部署流程模型,就可以实现对流程模型的部分修改。


环境准备

Eclipse 插件安装

  Eclipse 插件安装方法这里不做说明,这里提供安装的 URL:http://activiti.org/designer/update/。安装完成之后,需要重启 Eclipse ,在新建文件的对话框中,如果看到下图,则表示安装成功。
这里写图片描述

IDEA 插件安装

  在偏好设置中的 Plugins 选项中(mac:Perferences->plugins,windows:setting->plugins)搜索 actiBPM 插件,点击 Install 重启 IDEA 即可,安装成功后如下图。
这里写图片描述


Activiti 下载

  Activiti 的官网是http://www.activiti.org/, 在我们的 activiti 之旅中将使用 activit 6.0版本,下面是该版本的下载地址:https://github.com/Activiti/Activiti/releases/download/activiti-6.0.0/activiti-6.0.0.zip
下载解压后得到 activiti-6.0.0目录,该目录下有三个子目录:database、libs、wars。下面对各个目录进行简单的额描述:
->database: 用于存放 activiti 数据表的初始化脚本(create 子目录)、删除脚本(drop 子目录)和升级脚本(update 子目录)。从目录里面的脚本文件名可得知,Activiti 支持主流的数据库 oracle,mysql,ms,postgres,DB2等。
->libs:用来存放该版本的 jar 包和源码。
->wars: 存放 activiti 官方提供的示例 war 包,包含三个 activiti-app.war,activiti-admin.war,activit-rest.war。以上三个war包都是基于activiti开发的示例应用,并且都是使用内存数据库(h2)所以不需要配置数据库环境,直接复制到tomcat的 webapps 目录中就可以使用,当然如果你想使用本地的数据库可以用压缩工具打开war包修改WEB-INF/classes/META-INF/activiti-app/下的activiti-app.properties 文件即可。
activiti-app.war 是一套完整的工作流应用;activiti-rest.war 是一套提供restful接口的应用,其实activiti已经提供了restful接口,这个war包只是稍微配置了一下并部署了几个示例流程;activiti-admin.war 顾名思义是可以管理activiti流程相关的应用,这个大家可以打开就可以很快上手。


编写第一个 Activiti 程序

  1. 建立工程环境,打开IDEA,新建项目如下图所示:
    这里写图片描述
  2. 导入 jar 包依赖,除了引入 activiti 相关 jar 之外,还需引入对应的数据驱动 jar 包,maven 依赖如以下代码片段:
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-engine</artifactId>
    <version>6.0.0</version>
</dependency>
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring</artifactId>
    <version>6.0.0</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.196</version>
</dependency>

3.创建配置文件,如果没有指定的 Activiti 的配置文件,那么默认情况下将会到 classpath 下读取 activiti.cfg.xml 文件作为 Activiti 的配置文件,该文件主要用于配置数据库连接等属性。配置文件activiti.cfg.xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
   <!-- 流程引擎配置的bean -->
   <!--<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti" /> <property name="jdbcDriver" value="com.mysql.jdbc.Driver" /> <property name="jdbcUsername" value="root" /> <property name="jdbcPassword" value="123456" /> <property name="databaseSchemaUpdate" value="true" /> </bean>-->
   <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
      <property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
      <property name="jdbcDriver" value="org.h2.Driver" />
      <property name="jdbcUsername" value="sa" />
      <property name="jdbcPassword" value="" />
      <property name="databaseSchemaUpdate" value="true" />
   </bean>
</beans>

  activiti.cfg.xml是一份标准的 xml 文档,在该 xml 文档中只配置了一个名称为processEngineConfiguration的 bean 元素,bean 的前面四个属性是一个数据库名称为 activiti 的数据库连接,后面databaseSchemaUpdate的值为 true 表示在项目启动过程中会自动创建数据库表(数据库activiti需要手工创建),上述配置文件还提供的 mysql 的配置方式(已注释)。

4.创建流程文件,流程文件是遵循 BPMN2.0规范的 xml 文件,我们创建一个简单的请假流程,下图是流程图。
这里写图片描述
流程图对应的文件 leave.xml 如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/testm1533999566823" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1533999566823" name="" targetNamespace="http://www.activiti.org/testm1533999566823" typeLanguage="http://www.w3.org/2001/XMLSchema">
  <process id="myProcess_1" isClosed="false" isExecutable="true" name="leave" processType="None">
    <startEvent id="_2" name="StartEvent"/>
    <userTask activiti:exclusive="true" id="_3" name="请假申请"/>
    <userTask activiti:exclusive="true" id="_4" name="请假审核"/>
    <endEvent id="_5" name="EndEvent"/>
    <sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/>
    <sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/>
    <sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/>
  </process>
  <bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
    <bpmndi:BPMNPlane bpmnElement="myProcess_1">
      <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
        <dc:Bounds height="32.0" width="32.0" x="40.0" y="65.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
        <dc:Bounds height="55.0" width="85.0" x="110.0" y="55.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
        <dc:Bounds height="55.0" width="85.0" x="235.0" y="55.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
        <dc:Bounds height="32.0" width="32.0" x="355.0" y="65.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3">
        <di:waypoint x="72.0" y="81.0"/>
        <di:waypoint x="110.0" y="82.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4">
        <di:waypoint x="195.0" y="82.5"/>
        <di:waypoint x="235.0" y="82.5"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5">
        <di:waypoint x="320.0" y="82.5"/>
        <di:waypoint x="355.0" y="81.0"/>
        <bpmndi:BPMNLabel>
          <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

  上述代码清单为一个流程文件,该文件中的 process 元素用于描述流程信息, 而bpmndi:BPMNDiagram元素则用于描述流程节点的位置信息。在 process 元素中定义了开始事件 srartEvent 、两个 usertask和结束事件 endEvent 以及连接这些元素的顺序流(sequenceFlow)。

5.加载流程文件与启动流程,在准备好流程需要的 jar 包,数据库表(这里配置的是自动创建表,但是数据库还是需要手动创建)流程配置文件和流程文件之后,终于可以 coding 了,Talk is cheap, Show you the code。

package me.lbing.workflow.demo01;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;

/** * 第一个流程运行类 * @author jeremy king * */
public class Leave { 
   
   public static void main(String[] args) {
      // 创建流程引擎,获取默认的流程引擎
      ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
      // 得到流程存储服务
      RepositoryService repositoryService = engine.getRepositoryService();
      // 得到运行时服务
      RuntimeService runtimeService = engine.getRuntimeService();
      // 获取流程任务
      TaskService taskService = engine.getTaskService();
      // 部署流程文件
      repositoryService.createDeployment()
            .addClasspathResource("bpmn/leave.bpmn").deploy();
      // 开启流程
      runtimeService.startProcessInstanceByKey("myProcess_1");
      // 查询第一个节点的任务并且输出
      Task task = taskService.createTaskQuery().singleResult();
      System.out.println("第一个任务完成前,当前任务名称:" + task.getName());
      // 完成第一个任务,相当于流程图中的请假申请
      taskService.complete(task.getId());
      // 查询第二个节点的任务并且输出
      task = taskService.createTaskQuery().singleResult();
      System.out.println("第二个任务完成前,当前任务名称:" + task.getName());
      // 完成第二个任务,相当于流程图中的请假审核(流程结束)
      taskService.complete(task.getId());
      task = taskService.createTaskQuery().singleResult();
      System.out.println("流程结束后,查找任务:" + task);
   }
}

运行结果:
第一个任务完成前,当前任务名称:请假申请
第二个任务完成前,当前任务名称:请假审核
流程结束后,查找任务:null

样例Github源码地址(包含配置文件,流程文件,以及代码)

参考网址:
https://blog.csdn.net/zezezuiaiya/article/details/78121663
https://blog.csdn.net/yongboyhood/article/details/70833021
http://www.mossle.com/docs/activiti/index.html

参考书籍:
<<疯狂工作流讲义 杨恩雄>>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/157485.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • PyCharm官网无法访问的解决办法[通俗易懂]

    PyCharm官网无法访问的解决办法[通俗易懂]问题描述  最近在研究pythonweb框架,用的是以前学python的时候用的Pycharm社区版(无力吐槽)。不太好用,就想去下个企业版用用,结果出现这种情况。。。  emmm,检查了网络没问题,换了个浏览器也是无法访问,最后辗转多个论坛发现似乎是因为hosts文件的问题。模糊的记得我好像激活成功教程过这个软件修改了一下hosts文件,改回来就可以访问Pycharm官网了。解决办法  Wi…

  • 矩阵转置基本性质

    矩阵转置基本性质一个矩阵的转置与本身相乘得到对称矩阵

  • Java集合容器面试题(2020最新版)「建议收藏」

    Java集合容器面试题(2020最新版)「建议收藏」文章目录集合容器概述什么是集合集合的特点集合和数组的区别使用集合框架的好处常用的集合类有哪些?List,Set,Map三者的区别?List、Set、Map是否继承自Collection接口?List、Map、Set三个接口存取元素时,各有什么特点?集合框架底层数据结构哪些集合类是线程安全的?Java集合的快速失败机制“fail-fast”?怎么确保一个集合不能被修改?Collection…

  • EmguCV 常用函数功能说明「建议收藏」

    AbsDiff,计算两个数组之间的绝对差。dst(I)c=abs(src1(I)c-src2(I)c)。所有数组必须具有相同的数据类型和相同的大小(或ROI大小)。累加,将整个图像或其所选区域添加到累加器和。累积产品,将2张图像或其选定区域的产品添加到累加器中。AccumulateSquare,将输入src或其选定的区域,增加到功率2,添加到累加器sqsum。累积权重,计算输

  • tomcat宕机自动重启和每日定时启动tomcat

    tomcat宕机自动重启和每日定时启动tomcat在项目后期维护中会遇到这样的情况,tomcat在内存溢出的时候就出现死机的情况和遇到长时间不响应,需要人工手动关闭和重启服务,针对这样的突发情况,希望程序能自动处理问题而不需要人工关于,所以才有了目前的需求。一、设置tomcat定时启动1,首先将tomcat注册为服务,先打开tomcat的bin目录下service.bat文件,修改下面的值,这是sevvice的注册名称和显

  • 使用IDEA搭建一个简单的SpringBoot项目——详细过程

    使用IDEA搭建一个简单的SpringBoot项目——详细过程一、创建项目1.File->new->project;2.选择“SpringInitializr”,点击next;(jdk1.8默认即可)3.完善项目信息,组名可不做修改,项目名可做修改;最终建的项目名为:test,src->main->java下包名会是:com->example->test;点击next;4.Web下勾选Spri…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号