Activiti是一个开源的工作流引擎,它实现了BPMN 2.0规范,可以发布设计好的流程定义,并通过api进行流程调度。

Activiti 作为一个遵从 Apache 许可的工作流和业务流程管理开源平台,其核心是基于 Java 的超快速、超稳定的 BPMN2.0 流程引擎,强调流程服务的可嵌入性和可扩展性,同时更加强调面向业务人员。

Activiti 流程引擎重点关注在系统开发的易用性和轻量性上。每一项 BPM 业务功能 Activiti 流程引擎都以服务的形式提供给开发人员。通过使用这些服务,开发人员能够构建出功能丰富、轻便且高效的 BPM 应用程序。

核心组件介绍

1. 关键对象

  1. Deployment:流程部署对象,部署一个流程时创建。
  2. ProcessDefinitions:流程定义,部署成功后自动创建。
  3. ProcessInstances:流程实例,启动流程时创建。
  4. Task:任务,在Activiti中的Task仅指有角色参与的任务,即定义中的UserTask。
  5. Execution:执行计划,流程实例和流程执行中的所有节点都是Execution,如UserTask、ServiceTask等。

2. 服务接口

  1. ProcessEngine:流程引擎的抽象,通过它我们可以获得我们需要的一切服务。
  2. RepositoryService:Activiti中每一个不同版本的业务流程的定义都需要使用一些定义文件,部署文件和支持数据(例如BPMN2.0 XML文件,表单定义文件,流程定义图像文件等),这些文件都存储在Activiti内建的Repository中。RepositoryService提供了对 repository的存取服务。
  3. RuntimeService:在Activiti中,每当一个流程定义被启动一次之后,都会生成一个相应的流程对象实例。RuntimeService提供了启动流程、查询流程实例、设置获取流程实例变量等功能。此外它还提供了对流程部署,流程定义和流程实例的存取服务。
  4. TaskService: 在Activiti中业务流程定义中的每一个执行节点被称为一个Task,对流程中的数据存取,状态变更等操作均需要在Task中完成。TaskService提供了对用户Task 和Form相关的操作。它提供了运行时任务查询、领取、完成、删除以及变量设置等功能。
  5. IdentityService: Activiti中内置了用户以及组管理的功能,必须使用这些用户和组的信息才能获取到相应的Task。IdentityService提供了对Activiti 系统中的用户和组的管理功能。
  6. ManagementService: ManagementService提供了对Activiti流程引擎的管理和维护功能,这些功能不在工作流驱动的应用程序中使用,主要用于Activiti系统的日常维护。
  7. HistoryService: HistoryService用于获取正在运行或已经完成的流程实例的信息,与RuntimeService中获取的流程信息不同,历史信息包含已经持久化存储的永久信息,并已经被针对查询优化。

现在至少要知道有这些对象和接口。并结合Activiti Api这一章节来看,你就会对部署流程、启动流程、执行任务等操作有一个基本的概念。之后编写一个简单的单元测试,主要为了测试activiti.cfg.xml配置的是否正确,流程是否可以被部署即可。

至于与Spring的集成,一定要熟悉基于Spring配置Activiti,以及事务的处理。

官方demo使用(activiti-explorer)

activiti工作流历史版本下载,更改版本号后在浏览器地址栏回车即可

https://github.com/Activiti/Activiti/releases/download/activiti-5.16.3/activiti-5.16.3.zip

下载后解压得到:

初始化数据库(本文采用的mysql数据库)

\wars\activiti-explorer.war解压到tomcat的webapps下,并修改\activiti-explorer\WEB-INF\classes中的db.properties:

#db=h2
#jdbc.driver=org.h2.Driver
#jdbc.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000
#jdbc.username=sa
#jdbc.password= db=mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1/activititest?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456

访问首页,打开浏览器输入http://localhost:8080/activiti-explore,使用用户kermit,密码kermit登录

使用idea进行activiti工作流开发

1.安装IDEA中编辑Activiti流程的插件actiBPM,安装完成后重启IDEA

2.新建一个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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.xuan</groupId>
<artifactId>testactiviti</artifactId>
<version>1.0-SNAPSHOT</version> <name>testactiviti</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!--<scope>test</scope>-->
</dependency>
<!--- Activiti依赖导入 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>5.22.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>jackson-core-asl</artifactId>
<groupId>org.codehaus.jackson</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang3</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang3</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
</exclusions>
</dependency>
<!--MySQL 驱动包,如果是其他库的话需要换驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
</dependencies>
</project>

创建资源文件夹resource,并把目录设置为Test Resources Root

目录结构为

在resource目录中新建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 id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl"
value="jdbc:mysql://localhost:3306/testactiviti?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT%2B8"></property>
<property name="jdbcUsername" value="root"></property>
<property name="jdbcPassword" value="123456"></property>
<property name="databaseSchemaUpdate" value="true"></property>
</bean>
</beans>

在resources下面新建一个WorkTest.bpmn文件:

新建之后页面会变成如下图所示这样,中间是画布,右边是一些元素,左边是每个元素的一些详细信息,直接拖拽右边的元素就可以画流程了。

画完流程图之后可以更改整个流程的name和元素的name,assignee,

但是画图之后,没有连接图标怎么办呢
把鼠标放在开头的那个图标上,此时光标的形状改变了。 拖到另一个上面,连接成功了。
怎么连接成功的呢? 把鼠标放到图标的正中心,然后会看到光标变成了“扇子类型”的样子(黑白相间)。只要看到变成这个样子,就可以拖动到另一个图标中,进行连接了

我这里画的一个很简单的流程图,只用到了startEvent、endEvent和userTask。我的流程是做的订单的审批。如图:

画完图后,但是并没有生成png图片,这个时候重命名刚才创建的文件,把后缀改成xml,然后右键

这个时候发现显示的时候有乱码:

解决方法:

找到idea安装目录bin目录下如下图所示两个文件,用编辑器打开,在文件末尾添加 -Dfile.encoding=UTF-8 ,然后重启idea,再打开流程图就会发现中文已经可以正常显示了。

解决问题后,把xml文件重新改成bpmn格式,和png图片一起压缩成zip包进行部署。

1.创建需要的表格

Activiti提供使用代码或者配置文件的方式来配置数据库的信息,新建MyActiviti.java来生成数据库信息:

public class MyActiviti {
@Test
public void creatTable() {
ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").buildProcessEngine();
System.out.println("processEngine:"+ processEngine);
} @Test
public void creatTable2() {
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
//连接数据库配置
processEngineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8");
processEngineConfiguration.setJdbcUsername("root");
processEngineConfiguration.setJdbcPassword("123456"); /**
public static final String DB_SCHEMA_UPDATE_FALSE = "false";//不能自动创建表,需要表存在
public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";//先删除表再创建表
public static final String DB_SCHEMA_UPDATE_TRUE = "true";//如果表不存在,自动创建表
*/
processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP);
//工作流的核心对象,ProcessEngine对象
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
System.out.println("processEngine:"+ processEngine);
}
}

运行这个类的creatTable或creatTable2之后,自动帮我们把对应的数据库表创建起来,有些说23-25张表都是有可能的,我这里是生成了25张表。

所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。

  • ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
  • ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
  • ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
  • ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
  • ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。

每个表和字段的具体含义可以参考:https://blog.csdn.net/hj7jay/article/details/51302829

2.部署流程

建表成功之后就可以开始部署流程了,部署之后就可以在act_re_procdef表中看到对相应的流程信息.

    @Test
public void deploy() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
DeploymentBuilder builder = repositoryService.createDeployment();//创建一个部署的构建器
builder.addClasspathResource("WorkTest.bpmn");//从类路径中添加资源,一次只能添加一个资源
builder.name("订单审批");
builder.category("办公类别");
Deployment deploy = builder.deploy(); System.out.println("部署的id" + deploy.getId());
System.out.println("部署的名称" + deploy.getName());
}
    //查询流程
@Test
public void queryProcdef() {
RepositoryService repositoryService = processEngine.getRepositoryService();
//创建查询对象
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
//添加查询条件
//query.processDefinitionKey("myProcess_2");//通过key获取
// .processDefinitionName("My process")//通过name获取
query.orderByProcessDefinitionId().asc();//根据ID排序
//执行查询获取流程定义明细
List<ProcessDefinition> pds = query.list();
for (ProcessDefinition pd : pds) {
System.out.println("ID:" + pd.getId() + ",NAME:" + pd.getName() + ",KEY:" + pd.getKey() + ",VERSION:" + pd.getVersion() + ",RESOURCE_NAME:" + pd.getResourceName() + ",DGRM_RESOURCE_NAME:" + pd.getDiagramResourceName());
}
}

3.执行工作流

    @Test
public void startProcess() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//指定执行我们刚才部署的工作流程,就是bomn文件定义的流程ID或者名称
String processDefiKey = "myProcess_1";
//取运行时服务
RuntimeService runtimeService = processEngine.getRuntimeService();
//取得流程实例
ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefiKey);//通过流程定义的key 来执行流程
System.out.println("流程实例id:" + pi.getId());//流程实例id
System.out.println("流程定义id:" + pi.getProcessDefinitionId());//输出流程定义的id
}

启动流程之后就会有相应的任务产生,存在act_ru_task表中,可以查看任务节点

4.查询信息

    @Test
public void queryTask() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
//processInstanceId,就是act_ru_task的PROC_INST_ID_
String processInstanceId = "12501";
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list(); //首次运行的时候这个没有输出,因为第一次运行的时候扫描act_ru_task的表里面是空的,但第一次运行完成之后里面会添加一条记录,之后每次运行里面都会添加一条记录
for (Task task : tasks) {
System.out.println("taskId:" + task.getId() +
",taskName:" + task.getName() +
",assignee:" + task.getAssignee() +
",createTime:" + task.getCreateTime());
}
}

也可以根据其它各种条件进行查询

    //查询流程定义明细
@Test
public void queryProcdef() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
//创建查询对象
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
//添加查询条件
query.processDefinitionKey("myProcess_1");//通过key获取
// .processDefinitionName("My process")//通过name获取
// .orderByProcessDefinitionId()//根据ID排序
//执行查询获取流程定义明细
List<ProcessDefinition> pds = query.list();
for (ProcessDefinition pd : pds) {
System.out.println("ID:" + pd.getId() + ",NAME:" + pd.getName() + ",KEY:" + pd.getKey() + ",VERSION:" + pd.getVersion() + ",RESOURCE_NAME:" + pd.getResourceName() + ",DGRM_RESOURCE_NAME:" + pd.getDiagramResourceName());
}
}

5.处理任务

    //完成任务
@Test
public void compileTask(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
String taskId="12504";//任务id,act_ru_task的ID_
processEngine.getTaskService().complete(taskId);
System.out.println("当前任务执行完毕");
}

其它还有删除流程等各种操作,可以参考https://segmentfault.com/a/1190000013839729

Activiti使用的更多相关文章

  1. 流程开发Activiti 与SpringMVC整合实例

    流程(Activiti) 流程是完成一系列有序动作的概述.每一个节点动作的结果将对后面的具体操作步骤产生影响.信息化系统中流程的功能完全等同于纸上办公的层级审批,尤其在oa系统中各类电子流提现较为明显 ...

  2. activiti工作流的web流程设计器整合视频教程 SSM和独立部署

    本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...

  3. activiti工作流的web流程设计器整合视频教程 SSM 和 独立部署

    本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...

  4. 文档分享-Activiti 5.16 用户手册

    今天在翻看工作流相关的网页的时候,在开源中国上http://www.oschina.net/question/915507_149175发现activiti的中文文档:http://www.mossl ...

  5. 1. Activiti 运行时表信息总结

    Activiti的后台是有数据库的支持,所有的表都以ACT_开头. 第二部分是表示表的用途的两个字母标识. 用途也和服务的API对应. ACT_RE_*: 'RE'表示repository. 这个前缀 ...

  6. Activiti学习(二)数据表结构

    Activiti工作流引擎数据库表结构 数据库表的命名 Acitiviti数据库中表的命名都是以ACT_开头的.第二部分是一个两个字符用例表的标识.此用例大体与服务API是匹配的. l        ...

  7. Activiti学习(一) 环境搭建

    原料:Activiti5.4  MyEclipse 10 1.先将activiti文件夹放置myeclipse的安装目录dropins文件夹下2.将activiti文件夹里activiti.link中 ...

  8. Activiti工作流学习(三)Activiti工作流与spring集成

    一.前言 前面Activiti工作流的学习,说明了Activiti的基本应用,在我们开发中可以根据实际的业务参考Activiti的API去更好的理解以及巩固.我们实际的开发中我们基本上都使用sprin ...

  9. activiti当前任务高亮(解决乱码问题)

    package com.xinwei; import java.io.File; import java.io.InputStream; import java.util.ArrayList; imp ...

  10. activiti 中文文档

    http://www.mossle.com http://www.mossle.com/docs/activiti/index.html

随机推荐

  1. 华为HCNA乱学Round 8:生成树

  2. springMVC异常处理总结

    a.ExceptionHandlerExceptionResolver 1.@ExceptionHandler --- 统一处理一个controller中(@ExceptionHandler所在con ...

  3. ng-zorro等组件默认样式的修改

    https://www.jianshu.com/p/8b887c2aac06 在项目中修改ng-zorro组件默认样式的一些方法: 类名等 前加::ng-deep: 类名等 前加:root: 类名等 ...

  4. 修改state(react)中的某一个对象中的单个参数

    react项目中我们经常会涉及到修改state中参数的问题,如果参数为常用的基本类型变量,我们可以直接通过this.setState({...})方法来进行修改,但是如果变量为一个对象我们要如何修改呢 ...

  5. [c++] SYSTEM_INFO

    SYSTEM_INFO,Win32 API函数GetSystemInfo所使用的结构体. 说明 SYSTEM_INFO结构体包含了当前计算机的信息.这个信息包括计算机的体系结构.中央处理器的类型.系统 ...

  6. PTA(Advanced Level)1046.Shortest Distance

    The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed t ...

  7. 使用Themleaf 模板引擎手动生成html文件

    1.为什么要写这一篇呢? 在做一个邮件发送功能的时候,需要发送html邮件,javaMail 发送html 的时候需要有已经生成的html正文,所以需要提前将要发送的内容生成,所以就需要模板引擎来动态 ...

  8. java生成0~9个9个不相等的整数

    HashSet<Integer> hs=new HashSet<Integer>(); Integer i=0; while (i<9){ int s=(int) Mat ...

  9. std::tr1::function和bind组件

    C++中std::tr1::function和bind 组件的使用 在C++的TR1中(Technology Report)中包含一个function模板类和bind模板函数,使用它们可以实现类似函数 ...

  10. 分层最短路(牛客第四场)-- free

    题意: 给你边权,起点和终点,有k次机会把某条路变为0,问你最短路是多长. 思路: 分层最短路模板题.题目有点坑(卡掉了SPFA,只能用dijkstra跑的算法). #include<iostr ...