前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Activiti7工作流引擎-流程定义

Activiti7工作流引擎-流程定义

作者头像
cwl_java
发布2020-01-02 11:35:30
1.7K0
发布2020-01-02 11:35:30
举报
文章被收录于专栏:cwl_Javacwl_Java

第6章 流程定义

6.1 流程定义

6.1.1 什么是流程定义

流程定义是线下按照 bpmn2.0 标准去描述 业务流程,通常使用 activiti-explorer(web 控制台)activiti-eclipse-designer 插件对业务流程进行建模,这两种方式都遵循 bpmn2.0 标准。本教程使用activiti-eclipse-designer 插件完成流程建模。使用 designer 设计器绘制流程,会生成两个文件:.bpmn和.png

6.1.2 .bpmn 文件

使用 activiti-desinger 设计业务流程,会生成.bpmn 文件, 首先将 holiday.bpmn 文件改名为 holiday.xml,如下图:

在这里插入图片描述
在这里插入图片描述

.bpmn 内容如下:

代码语言:javascript
复制
<?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:omgdc="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
             xmlns:tns="http://www.activiti.org/test"
             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="m1539820628606" name=""
             targetNamespace="http://www.activiti.org/test"
             typeLanguage="http://www.w3.org/2001/XMLSchema">
    <process id="myProcess_1" isClosed="false" isExecutable="true" processType="None">
        <startEvent id="_2" name="StartEvent"/>
        <userTask activiti:exclusive="true" id="_3" name="UserTask"/>
        <sequenceFlow id="_4" sourceRef="_2" targetRef="_3"/>
        <userTask activiti:exclusive="true" id="_5" name="UserTask"/>
        <sequenceFlow id="_6" sourceRef="_3" targetRef="_5"/>
    </process>
    <bpmndi:BPMNDiagram
            documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842
.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageab
leY=5.0" id="Diagram-_1" name="New Diagram">
        <bpmndi:BPMNPlane bpmnElement="myProcess_1">
            <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
                <omgdc:Bounds height="32.0" width="32.0" x="200.0" y="70.0"/>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
                <omgdc:Bounds height="55.0" width="85.0" x="165.0" y="175.0"/>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
                <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="295.0"/>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNShape>
            <bpmndi:BPMNEdge bpmnElement="_4" id="BPMNEdge__4" sourceElement="_2"
                             targetElement="_3">
                <omgdi:waypoint x="216.0" y="102.0"/>
                <omgdi:waypoint x="216.0" y="175.0"/>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
            <bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_3"
                             targetElement="_5">
                <omgdi:waypoint x="205.0" y="230.0"/>
                <omgdi:waypoint x="205.0" y="295.0"/>
                <bpmndi:BPMNLabel>
                    <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
                </bpmndi:BPMNLabel>
            </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>
</definitions>

BPMN 2.0 根节点是 definitions 节点。 这个元素中,可以定义多个流程定义(不过我们建议每个文件只包含一个流程定义, 可以简化开发过程中的维护难度)。 注意,definitions 元素 最少也要包含 xmlns 和 targetNamespace 的声明。 targetNamespace 可以是任意值,它用来对流程实例进行分类。

流程定义部分:定义了流程每个结点的描述及结点之间的流程流转。 流程布局定义:定义流程每个结点在流程图上的位置坐标等信息。

6.1.3 .png 图片文件

Eclipse 工具中的操作
流程图片生成的两种方式:

使用 activiti-designer 设计流程图时自动生成 需在 eclipse 中进行配置:

在这里插入图片描述
在这里插入图片描述

使用 designer 设计流程图的同时自动生成与 bpmn 文件同名的图片文件(.png)

由 activiti 自动生成图形 流程图设计完毕向 activiti 中部署流程定义文件 bpmn,部署时由 activiti 自动生成流程图片。(流程部署在下面的章节讲解)

注意:此方法生成时如果图形中有中文生成的图片上显示乱码,且.bpmn 中的坐标和图片显示错位。

IDEA 工具中的操作方式

第一步:将 holiday.bpmn 文件改为扩展名 xml 的文件名称:holiday.xml修改前的 bpmn 文件,效果如下:

在这里插入图片描述
在这里插入图片描述

第二步:在 holiday.xml 文件上面,点右键并选择 Diagrams 菜单,再选择 Show BPMN2.0 Designer

在这里插入图片描述
在这里插入图片描述

第三步:打开后的效果图如下:

在这里插入图片描述
在这里插入图片描述

第四步:点击 Export To File 的小图标,如下:

在这里插入图片描述
在这里插入图片描述

打开如下窗口,注意填写文件名及扩展名,选择好保存图片的位置:

在这里插入图片描述
在这里插入图片描述

第五步:中文乱码的解决

  1. 打开 IDEA 安装路径,找到如下的安装目录
在这里插入图片描述
在这里插入图片描述

根据自己所安装的版本来决定,我使用的是 64 位的 idea,所以在 idea64.exe.vmoptions 文件的最后 一行追加一条命令: -Dfile.encoding=UTF-8 如下所示:

在这里插入图片描述
在这里插入图片描述

一定注意,不要有空格,否则重启 IDEA 时会打不开,然后 重启 IDEA,把原来的 png 图片删掉,再重新生成,即可解决乱码问题

6.2 流程定义部署

6.2.1 什么是流程定义部署

将线下定义的流程部署到 activiti 数据库中,这就是流程定义部署,通过调用 activiti 的 api 将流程定义的 bpmn 和 png 两个文件一个一个添加部署到 activiti 中,也可以将两个文件打成 zip 包进行部署。

6.2.2 单个文件部署方式

分别将 bpmn 文件和 png图片文件部署。

代码语言:javascript
复制
    @Test
    public void deployProcess() {
        // 获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // bpmn输入流
        InputStream inputStream_bpmn = this
                .getClass()
                .getClassLoader()
                .getResourceAsStream(
                        "diagram/holiday.bpmn");
        // 图片输入流
        InputStream inputStream_png = this
                .getClass()
                .getClassLoader()
                .getResourceAsStream(
                        " diagram/holiday.png");
        // 流程部署对象
        Deployment deployment = repositoryService.createDeployment()
                .addInputStream("holiday.bpmn", inputStream_bpmn)
                .addInputStream("holiday.png", inputStream_png)
                .deploy();
        System.out.println("流程部署id:" + deployment.getId());
        System.out.println("流程部署名称:" + deployment.getName());
    }

执行此操作后 activiti 会将上边代码中指定的 bpm 文件和图片文件保存在 activiti 数据库。

6.2.3 压缩包部署方式

将 holiday.bpmn 和 holiday.png 压缩成 zip 包。

代码语言:javascript
复制
    @Test
    public void deployProcessByZip() {
        // 定义zip输入流
        InputStream inputStream = this
                .getClass()
                .getClassLoader()
                .getResourceAsStream(
                        " diagram/holiday.zip");
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        // 获取repositoryService
        RepositoryService repositoryService = processEngine
                .getRepositoryService();
        // 流程部署
        Deployment deployment = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream).deploy();
        System.out.println("流程部署id:" + deployment.getId());
        System.out.println("流程部署名称:" + deployment.getName());
    }

执行此操作后 activiti 会将上边代码中指定的 bpm 文件和图片文件保存在 activiti 数据库。

6.2.4 操作数据表

流程定义部署后操作 activiti 数据表如下:

代码语言:javascript
复制
#流程定义部署表,记录流程部署信息
SELECT * FROM act_re_deployment 
#流程定义表,记录流程定义信息
SELECT * FROM act_re_procdef 
#资源表
SELECT * FROM act_ge_bytearray 

说明act_re_deploymentact_re_procdef 一对多关系,一次部署在流程部署表生成一条记录,但一次部署可以部署多个流程定义,每个流程定义在流程定义表生成一条记录。每一个流程定义在act_ge_bytearray 会存在两个资源记录,bpmn 和 png。

建议:一次部署一个流程,这样部署表和流程定义表是一对一有关系,方便读取流程部署及流程定义信息。

6.3 流程定义查询

查询部署的流程定义。

代码语言:javascript
复制
    // 流程定义查询
    @Test
    public void queryProceccDefinition() {
        // 流程定义key
        String processDefinitionKey = "holiday";
        // 获取repositoryService
        RepositoryService repositoryService = processEngine
                .getRepositoryService();
        // 查询流程定义
        ProcessDefinitionQuery processDefinitionQuery = repositoryService
                .createProcessDefinitionQuery();
        //遍历查询结果
        List<ProcessDefinition> list = processDefinitionQuery
                .processDefinitionKey(processDefinitionKey).orderByProcessDefinitionVersion().desc().list();
        for (ProcessDefinition processDefinition : list) {
            System.out.println("------------------------");
            System.out.println(" 流 程 部 署 id : " +
                    processDefinition.getDeploymentId());
            System.out.println("流程定义id:" + processDefinition.getId());
            System.out.println("流程定义名称:" + processDefinition.getName());
            System.out.println("流程定义key:" + processDefinition.getKey());
            System.out.println("流程定义版本:" + processDefinition.getVersion());
        }
    }

6.4 流程定义删除

删除已经部署成功的流程定义。

代码语言:javascript
复制
    public void deleteDeployment() {
        // 流程部署id
        String deploymentId = "8801";
        // 通过流程引擎获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //删除流程定义,如果该流程定义已有流程实例启动则删除时出错
        repositoryService.deleteDeployment(deploymentId);
        //设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设
        置为false非级别删除方式,如果流程
        //repositoryService.deleteDeployment(deploymentId, true);
    }

说明:

  1. 使用 repositoryService 删除流程定义
  2. 如果该流程定义下没有正在运行的流程,则可以用普通删除。
  3. 如果该流程定义下存在已经运行的流程,使用普通删除报错,可用级联删除方法将流程及相关记录全部删除。项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用。

6.5 流程定义资源查询

6.5.1 方式 1

通过流程定义对象获取流程定义资源,获取 bpmn 和 png。

代码语言:javascript
复制
@Test
    public void getProcessResources() throws IOException {
        // 流程定义id
        String processDefinitionId = "";
        // 获取repositoryService
        RepositoryService repositoryService = processEngine
                .getRepositoryService();
        // 流程定义对象
        ProcessDefinition processDefinition = repositoryService
                .createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId).singleResult();
        //获取bpmn
        String resource_bpmn = processDefinition.getResourceName();
        //获取png
        String resource_png = processDefinition.getDiagramResourceName();
        // 资源信息
        System.out.println("bpmn:" + resource_bpmn);
        System.out.println("png:" + resource_png);
        File file_png = new File("d:/purchasingflow01.png");
        File file_bpmn = new File("d:/purchasingflow01.bpmn");
        // 输出bpmn   
        InputStream resourceAsStream = null;
        resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resource_bpmn);

        FileOutputStream fileOutputStream = new
                FileOutputStream(file_bpmn);
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            fileOutputStream.write(b, 0, len);
        }
        // 输出图片
        resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resource_png);
        fileOutputStream = new FileOutputStream(file_png);
        // byte[] b = new byte[1024];
        // int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            fileOutputStream.write(b, 0, len);
        }
    }

6.5.2 方式 2

通过查询流程部署信息获取流程定义资源。

代码语言:javascript
复制
// 获取流程定义图片资源
    @Test
    public void getProcessResources() throws IOException {
        //流程部署id
        String deploymentId = "9001";
        // 通过流程引擎获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //读取资源名称
        List<String> resources = repositoryService.getDeploymentResourceNames(deploymentId);
        String resource_image = null;
        //获取图片
        for (String resource_name : resources) {
            if (resource_name.indexOf(".png") >= 0) {
                resource_image = resource_name;
            }
        }//图片输入流
        InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resource_image);
        File exportFile = new File("d:/holiday.png");
        FileOutputStream fileOutputStream = new FileOutputStream(exportFile);
        byte[] buffer = new byte[1024];
        int len = -1;
        //输出图片
        while ((len = inputStream.read(buffer)) != -1) {
            fileOutputStream.write(buffer, 0, len);
        }
        inputStream.close();
        fileOutputStream.close();
    }

说明:

  1. deploymentId 为流程部署 ID
  2. resource_name 为 act_ge_bytearray 表中 NAME_列的值
  3. 使用 repositoryService 的 getDeploymentResourceNames方法可以获取指定部署下得所有文件的名 称
  4. 使用 repositoryService 的 getResourceAsStream 方法传入部署 ID和资源图片名称可以获取部署下 指定名称文件的输入流
  5. 最后的将输入流中的图片资源进行输出。

6.6 流程历史信息的查看

即使流程定义已经删除了,流程执行的历史信息通过前面的分析,依然保存在 activiti 的 act_hi_*相关的表中。所以我们还是可以查询流程执行的历史信息,可以通过 HistoryService 来查看相关的历史记录。

代码语言:javascript
复制
public void testHistoric01() {
        HistoryService historyService = pe.getHistoryService();
        HistoricActivityInstanceQuery query =
                historyService.createHistoricActivityInstanceQuery();
        query.processInstanceId("1501");

        List<HistoricActivityInstance> list = query.list();
        for (HistoricActivityInstance ai : list) {
            System.out.println(ai.getActivityId());
            System.out.println(ai.getActivityName());
            System.out.println(ai.getProcessDefinitionId());
            System.out.println(ai.getProcessInstanceId());
            System.out.println("==============================");
        }
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第6章 流程定义
    • 6.1 流程定义
      • 6.1.1 什么是流程定义
      • 6.1.2 .bpmn 文件
      • 6.1.3 .png 图片文件
    • 6.2 流程定义部署
      • 6.2.1 什么是流程定义部署
      • 6.2.2 单个文件部署方式
      • 6.2.3 压缩包部署方式
      • 6.2.4 操作数据表
    • 6.3 流程定义查询
      • 6.4 流程定义删除
        • 6.5 流程定义资源查询
          • 6.5.1 方式 1
          • 6.5.2 方式 2
        • 6.6 流程历史信息的查看
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档