开源工作流 Activiti

一、工作流介绍
  在了解 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 中,流程引擎的实例对象是 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 程序
建立工程环境,打开IDEA,新建项目如下图所示: 

导入 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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  上述代码清单为一个流程文件,该文件中的 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

参看样例:https://github.com/jgroups/workflow-activiti

参考网址: 
https://blog.csdn.net/zezezuiaiya/article/details/78121663 
https://blog.csdn.net/yongboyhood/article/details/70833021 
http://www.mossle.com/docs/activiti/index.html
--------------------- 
作者:jgroup 
来源:CSDN 
原文:https://blog.csdn.net/jgroup/article/details/82116523 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值