深入了解Activiti工作流流程定义

2016-03-27| 发布: | 浏览: 2363 |保存PDF

部署流程定义

部署流程定义的流程:
1. 先获取流程引擎对象:在创建时会自动加载 classpath 下的 activiti.cfg.xml
2. 首先获得默认的流程引擎,通过流程引擎获取了一个 RepositoryService 对象(仓库对象)
3. 由仓库的服务对象产生一个部署对象配置对象,用来封装部署操作的相关配置。
4. 这是一个链式编程,在部署配置对象中设置显示名,上传流程定义规则文件
5. 向数据库表中存放流程定义的规则信息。

部署流程定义加载资源文件有两种方式

1、从 classpath 路径加载文件
deploymentBuilder.addClasspathResource("diagrams/hello.bpmn");
deploymentBuilder.addClasspathResource("diagrams/hello.png");
2、使用 zip 的输入流用作部署流程定义
InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrams/hello.zip");
ZipInputStream zipInputStream = new ZipInputStream(in);
deploymentBuilder.addZipInputStream(zipInputStream);
注:打zip包的时候,不要有文件夹,直接对bpmn和png文件打包

示例:

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
@Test
public void testDeploy() {
    /**
     * RepositoryService是Activiti的仓库服务类,流程定义和部署对象相关的Service
     * 所谓的仓库指流程定义文档的两个文件:bpmn文件和流程图片
     */
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 创建一个部署对象DeploymentBuilder,用来定义流程部署的相关参数
    DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
    // 添加部署的名称
    deploymentBuilder.name("流程定义");
  
    // 第一种方式:添加hello.bpmn和hello.png
//        deploymentBuilder.addClasspathResource("diagrams/hello.bpmn");
//        deploymentBuilder.addClasspathResource("diagrams/hello.png");
  
//        // 第二种方式:通用zip文件
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrams/hello.zip");
    ZipInputStream zipInputStream = new ZipInputStream(in);
    deploymentBuilder.addZipInputStream(zipInputStream);
  
    // 部署流程定义
    Deployment deployment = deploymentBuilder.deploy();
  
    System.out.println("部署ID:" + deployment.getId());// 1
    System.out.println("部署名称:" + deployment.getName());// activiti入门程序
}

部署流程定义操作的数据表

1、act_re_deployment (部署对象表)
存放流程定义的显示名和部署时间,每部署一次增加一条记录 
2、 act_re_procdef(流程定义表)
存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录。
注意:当流程定义的 key 相同的情况下,使用的是版本升级
3、 act_ge_bytearray(资源文件表)
存储流程定义相关的部署信息。即流程定义文档的存放地。每部署一次就会增加两条记录,一条是关于 bpmn 规则文件的,一条是图片的(如果部署时只指定了 bpmn 一个文件, activiti 会在部署时解析 bpmn 文件内容自动生成流程图)。两个文件不是很大,都是以二进制形
式存储在数据库中。 
4、act_ge_property(主键生成策略表)

查看流程定义

1. 流程定义和部署对象相关的 Service 都是 RepositoryService 。
 
2. 创建流程定义查询对象,可以在 ProcessDefinitionQuery 上设置查询的相关参数
3. 调用 ProcessDefinitionQuery 对象的 list 方法,执行查询,获得符合条件的流程定义列表
4. 由运行结果可以看出: Key 和 Name 的值为: bpmn 文件 process 节点的 id 和 name 的属性值
5. key 属性被用来区别不同的流程定义。
6. 带有特定 key 的流程定义第一次部署时, version 为 1 。之后每次部署都会在当前最高版本号上加 1
7. Id 的值的生成规则为 :{processDefinitionKey}:{processDefinitionVersion}:{generated-id}, 这里的 generated-id 是一个自动生成的唯一的数字,由act_ge_property表生成的 next.dbid维护
8. 重复部署一次, deploymentId 的值以一定的形式变化
 

示例:

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
/** 查询流程定义 */
@Test
public void processDefinitionQueryTest() {
    RepositoryService service = processEngine.getRepositoryService();
    /**
     * 创建一个流程定义的查询
     * .list();返回一个集合 .singleResult();//返回惟一结果集
     * .count();//返回结果集数量
     * .listPage(firstResult, maxResults);//分页查询
     */
    ProcessDefinitionQuery pdq = service.createProcessDefinitionQuery();
    // pdq.deploymentId(deploymentId)//使用部署对象ID查询
    // pdq.processDefinitionId(processDefinitionId)//使用流程定义ID查询
    // pdq.processDefinitionKey(processDefinitionKey)//使用流程定义的key查询
    // pdq.processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询
    pdq.orderByProcessDefinitionVersion().asc();// 按照版本的升序排列
    // pdq.orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列
    List<ProcessDefinition> list = pdq.list();
  
    if (list != null && list.size() > 0) {
        for (ProcessDefinition pd : list) {
            // 流程定义的key+版本+随机生成数
            System.out.println("流程定义ID:" + pd.getId());
            // 对应hello.bpmn文件中的name属性值
            System.out.println("流程定义的名称:" + pd.getName());
            // 对应hello.bpmn文件中的id属性值
            System.out.println("流程定义的key:" + pd.getKey());
            // 当流程定义的key值相同的相同下,版本升级,默认1
            System.out.println("流程定义的版本:" + pd.getVersion());
            System.out.println("资源名称bpmn文件:" + pd.getResourceName());
            System.out.println("资源名称png文件:" + pd.getDiagramResourceName());
            System.out.println("部署对象ID:" + pd.getDeploymentId());
            System.out.println("############################");
        }
    }
}

删除流程定义

因为删除的是流程定义,而流程定义的部署是属于仓库服务的,所以应该先得到 RepositoryService
如果该流程定义下没有正在运行的流程,则可以用普通删除。如果是有关联的信息,用级联删除。项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/** 删除流程定义 */
@Test
public void deleteProcessDefinition() {
    // 使用部署ID,完成删除
    String deploymentId = "15001";
  
    //不带级联的删除 只能删除没有启动的流程,如果流程启动,就会抛出异常
    // processEngine.getRepositoryService().deleteDeployment(deploymentId);
  
    /**
     * 级联删除 不管流程是否启动,都能可以删除
     */
    processEngine.getRepositoryService().deleteDeployment(deploymentId, true);
    System.out.println("删除成功!");
}

获取流程定义文档的资源(查看流程图附件)

查询出流程定义文档。主要查的是图片,用于显示流程用。
1、deploymentId 为流程部署 ID
2、resourceName 为 act_ge_bytearray 表中 NAME_ 列的值
3、使用 repositoryService 的 getDeploymentResourceNames 方法可以获取指定部署下得所有文件的名称
4、使用 repositoryService 的 getResourceAsStream 方法传入部署 ID 和资源图片名称可以获取部署下指定名称文件的输入流
5、最后的有关 IO 流的操作,使用 FileUtils 工具的 copyInputStreamToFile 方法完成流程流程到文件的拷贝,将资源文件以流的形式输出到指定文件夹下
 

示例:

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
/** 查看流程图 */
@Test
public void viewPic() throws IOException {
    RepositoryService service = processEngine.getRepositoryService();
    /** 将生成图片放到文件夹下 */
    String deploymentId = "1";
    // 获取图片资源名称
    List<String> list = service.getDeploymentResourceNames(deploymentId);
  
    // 定义图片资源的名称
    String resourceName = "";
    if (list != null && list.size() > 0) {
        for (String name : list) {
            if (name.indexOf(".png") >= 0) {
                resourceName = name;
            }
        }
    }
  
    // 获取图片的输入流
    InputStream in = service.getResourceAsStream(deploymentId, resourceName);
  
    // 将图片生成到D盘的目录下
    File file = new File("D:/" + resourceName);
    // 将输入流的图片写到D盘下
    FileUtils.copyInputStreamToFile(in, file);
}

查询最新版本的流程定义

查询的思路:
1、使用流程定义的版本升序排列 

2、创建LinkedHashMap<String, ProcessDefinition>,对相同key的进行覆盖

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
/***查询最新版本的流程定义*/
@Test
public void findLastVersionProcessDefinition() {
    List<ProcessDefinition> list = processEngine.getRepositoryService()
            .createProcessDefinitionQuery()//
            .orderByProcessDefinitionVersion().asc()// 使用流程定义的版本升序排列
            .list();
    /**
     * Map<String,ProcessDefinition>
     * map集合的key:流程定义的key
     * map集合的value:流程定义的对象
     * map集合的特点:当map集合key值相同的情况下,后一次的值将替换前一次的值
     */
    Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();
    if (list != null && list.size() > 0) {
        for (ProcessDefinition pd : list) {
            map.put(pd.getKey(), pd);
        }
    }
    List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(map.values());
    if (pdList != null && pdList.size() > 0) {
        for (ProcessDefinition pd : pdList) {
            System.out.println("流程定义ID:" + pd.getId());
            System.out.println("流程定义的名称:" + pd.getName());
            System.out.println("流程定义的key:" + pd.getKey());
            System.out.println("流程定义的版本:" + pd.getVersion());
            System.out.println("资源名称bpmn文件:" + pd.getResourceName());
            System.out.println("资源名称png文件:" + pd.getDiagramResourceName());
            System.out.println("部署对象ID:" + pd.getDeploymentId());
            System.out.println("#########################################");
        }
    }
}

删除key相同的所有不同版本的流程定义

思路:把所有相同key的流程定义查出来,然后遍历删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**删除流程定义(删除key相同的所有不同版本的流程定义)*/
@Test
public void deleteProcessDefinitionByKey() {
    // 流程定义的key
    String processDefinitionKey = "hello";
    // 先使用流程定义的key查询流程定义,查询出所有的版本
    List<ProcessDefinition> list = processEngine.getRepositoryService()//
            .createProcessDefinitionQuery()//
            .processDefinitionKey(processDefinitionKey)// 使用流程定义的key查询
            .list();
    // 遍历,获取每个流程定义的部署ID
    if (list != null && list.size() > 0) {
        for (ProcessDefinition pd : list) {
            // 获取部署ID
            String deploymentId = pd.getDeploymentId();
            processEngine.getRepositoryService()//
                    .deleteDeployment(deploymentId, true);
        }
    }
}

深入了解Activiti工作流流程定义的更多相关文章

  1. 六、activiti工作流-流程定义查询

    本节主要讲流程定义查询.查询某个流程设计图片并保存到本地中.查询最新版本的流程定义集合.删除所有key相同的定义 先创建一个java类 package com.java.procdef; import ...

  2. activiti部署流程定义时出错:INSERT INTO ACT_GE_BYTEARRAY,修改数据库编码

    activiti部署流程定义时出错 // 部署流程定义 Deployment deployment = deploymentBuilder.deploy(); 错误信息:(有乱码的...没留下截图.. ...

  3. Activiti工作流的定义部署和执行

        工作流引擎 个人觉得直接理解工作流引擎概念有点难度,我们可以先通过了解工作流引擎的职责再反过来理解工作流引擎,工作流引擎一般都做两件事情: 1.定义流程,也就是给我们提供某种规范来定义规则,以 ...

  4. Activiti 删除流程定义

    package com.mycom.processDefinition; import java.io.InputStream; import java.util.List; import java. ...

  5. Activiti 查询流程定义

    package com.mycom.processDefinition; import java.io.InputStream; import java.util.List; import java. ...

  6. Activiti 部署流程定义及相关的表(classpath部署、zip部署)

    package com.mycom.processDefinition; import org.activiti.engine.ProcessEngine; import org.activiti.e ...

  7. 多数据库下activiti的流程定义缓存问题

    我们使用activiti(5.14版本号)作为流程引擎,今天在产品中发现一个问题,某流程的审批记录中, 活动实例表中记录的活动名称(ACT_HI_ACTINST表的ACT_NAME)居然是该流程中不存 ...

  8. activiti--5 -----------------Activiti 工作流 流程各个步骤所涉及到的表

    ACT_RE_*: 'RE'表示repository. 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等). ACT_RU_*: 'RU'表示runtime. 这些运行时的表,包含流程实例 ...

  9. (四)Activiti之流程定义部署之ZIP方式和流程定义查询

    一.流程定义部署之ZIP方式 上一章节我们使用classpath的方式加载流程定义文件,这里我们使用ZIP的方式. 1.1 用activiti插件生成bpmn和png图片之后,压缩到一个zip格式的压 ...

随机推荐

  1. 在O(N)时间内求解 正数数组中 两个数相加的 最大值

    一,问题描述 给定一个正数数组arr(即数组元素全是正数),找出该数组中,两个元素相加的最大值,其中被加数的下标大于加数的下标.由加法运算的可逆性,j >i 这个条件可以去掉. 即求出: max ...

  2. Jquery中click事件重复执行的问题

    平常没注意事件绑定问题,在此注意一下: function testClick(obj){ $("select").off().on("click", funct ...

  3. 二、主目录 Makefile 分析(3)

    2.8 编译选项 重新回到 主 makefile 中执行 2.8.1 u-boot  的编译顺序 代码166 到 189 行,这些是 u-boot 文件编译的顺序,由代码可以看到,首先是从cpu/$( ...

  4. IDA Pro使用技巧

    DA Pro基本简介 IDA加载完程序后,3个立即可见的窗口分别为IDA-View,Named,和消息输出窗口(output Window). IDA图形视图会有执行流,Yes箭头默认为绿色,No箭头 ...

  5. UE4的AI学习(1)——基本概念

    AI学习当中,不学习行为树基本概念就不能明白具体实例中的操作意义,但是没有经过具体实例实验,又觉得基本概念抽象难以理解.建议先泛读(1)(2)后再对具体的细节进行死磕,能较深的理解行为树的具体概念.第 ...

  6. 【tomcat】sessionId学习(未完待续)

    这里主要研究tomcat中session的管理方式以及sessionId的原理,下文将研究sessionid存到redis中以及基于redis实现session共享. 平时也就是了解session是基 ...

  7. Subarray Sum & Maximum Size Subarray Sum Equals K && Subarray Sum Equals K

    Subarray Sum Given an integer array, find a subarray where the sum of numbers is zero. Your code sho ...

  8. Linux之V4L2基础编程【转】

    转自:https://www.cnblogs.com/emouse/archive/2013/03/04/2943243.html 本文内容来源于网络,本博客进行整理. 1. 定义 V4L2(Vide ...

  9. 转载:分布式文件系统 - FastDFS 在 CentOS 下配置安装部署(2)

    原文:http://blog.mayongfa.cn/193.html 一.安装 Nginx 和 fastdfs-nginx-module 安装 Nginx 请看:从零开始学 Java - CentO ...

  10. PYTHON-面向对象 继承 派生

    1. 什么是继承 继承是一种新建类的方式,新建的类称之为子类/派生类,被继承的类称之为父类/基类/超类 继承有3个特点: 1. 子类可以遗传/重用父类的属性(解决类与类之间代码冗余的问题) 2. 在p ...