工作流引擎之五

目录

一,流程定义部署

1.1 什么是流程定义部署

1.1.2 ClassPath 部署方式

1.1.2 压缩包部署方式

1.1.3  InputStream

1.1.4 字符串方式

1.2 操作数据表

二,流程定义查询

      2.1 代码实现:

2.2 流程定义的表和api

 三,流程定义删除

3.1 代码实现

3.2 activiti api 实现sql 步骤

第一步:

第二步:

第三步:

第四步:

第五步:

第六步:

第七步:

第八步:

第九步:

第十步:

第十一步:

四,流程定义资源查询 并获取

4.1 方法一

4.2 方法二

五,流程历史信息的查看


一,流程定义部署

1.1 什么是流程定义部署

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

源码:


public interface DeploymentBuilder {

  DeploymentBuilder addInputStream(String resourceName, InputStream inputStream);

  DeploymentBuilder addClasspathResource(String resource);

  DeploymentBuilder addString(String resourceName, String text);
  
  DeploymentBuilder addBytes(String resourceName, byte[] bytes);

  DeploymentBuilder addZipInputStream(ZipInputStream zipInputStream);

  DeploymentBuilder addBpmnModel(String resourceName, BpmnModel bpmnModel);

  /**
   * If called, no XML schema validation against the BPMN 2.0 XSD.
   * 
   * Not recommended in general.
   */
  DeploymentBuilder disableSchemaValidation();

  /**
   * If called, no validation that the process definition is executable on the engine will be done against the process definition.
   * 
   * Not recommended in general.
   */
  DeploymentBuilder disableBpmnValidation();

  /**
   * Gives the deployment the given name.
   */
  DeploymentBuilder name(String name);

  /**
   * Gives the deployment the given category.
   */
  DeploymentBuilder category(String category);
  
  /**
   * Gives the deployment the given key.
   */
  DeploymentBuilder key(String key);

  /**
   * Gives the deployment the given tenant id.
   */
  DeploymentBuilder tenantId(String tenantId);

  /**
   * If set, this deployment will be compared to any previous deployment. This means that every (non-generated) resource will be compared with the provided resources of this deployment.
   */
  DeploymentBuilder enableDuplicateFiltering();

  /**
   * Sets the date on which the process definitions contained in this deployment will be activated. This means that all process definitions will be deployed as usual, but they will be suspended from
   * the start until the given activation date.
   */
  DeploymentBuilder activateProcessDefinitionsOn(Date date);
  
  /**
   * Allows to add a property to this {@link DeploymentBuilder} that influences the deployment.
   */
  DeploymentBuilder deploymentProperty(String propertyKey, Object propertyValue);

  /**
   * Deploys all provided sources to the Activiti engine.
   */
  Deployment deploy();

}

部署流程资源有很多种方法,包括classpath、InputStream、字符串、zip格式压缩包,下面将一一介绍 

1.1.2 ClassPath 部署方式

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

public class deployDemo {

    @Test
    public void demo1() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("processes/Holiday.bpmn")
                .addClasspathResource("processes/Holiday.png")
                .name("请假申请单")
                .deploy();

        System.out.println("name:"+deployment.getName());
        System.out.println("id:"+deployment.getId());

    }
}

1.1.2 压缩包部署方式

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

   /**
     * 压缩包部署方式
     */
    @Test
    public void deployProcessByZip() {
        // 定义zip输入流
        InputStream inputStream = this
                .getClass()
                .getClassLoader()
                .getResourceAsStream("processes/holiday.zip");
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        // 获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 流程部署
        Deployment deployment = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .name("请假申请单")
                .deploy();
        System.out.println("流程部署id:" + deployment.getId());
        System.out.println("流程部署名称:" + deployment.getName());
    }

1.1.3  InputStream

        使用InputStream方式部署流程资源需要传入一个输入流及资源的名称,输入流的来源不限

  //Inputstream方式
    @Test
    public void deployementProcessDefinitionByInputStream() throws FileNotFoundException {
        //获取资源绝对路径
        InputStream  pngfileInputStream =this.getClass().getClassLoader().getResourceAsStream("processes/Holiday.png");
        InputStream  bpmnfileInputStream=this.getClass().getClassLoader().getResourceAsStream("processes/Holiday.bpmn");

        Deployment deployment = processEngine.getRepositoryService()//获取流程定义和部署对象相关的Service
                .createDeployment()//创建部署对象
                .addInputStream("Holiday.bpmn",bpmnfileInputStream)
                .addInputStream("Holiday.png", pngfileInputStream)
                .name("请假申请单")
                .deploy();//完成部署
        System.out.println("部署ID:"+deployment.getId());
        System.out.println("部署时间:"+deployment.getDeploymentTime());
    }

可以从classpath读取,也可以从一个绝对路径文件读取,也可以是从网络上读取。

1.1.4 字符串方式

        利用字符串方式可以直接传入纯文本作为资源的来源,和前两种方式类似,字符串方式的实现原理是把一组字符串的内容转化为字节流后再部署。

        因为该方法需要配置自动生成流程图,所以下次再说

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

1.2 操作数据表

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

SELECT * FROM act_re_deployment #流程定义部署表,记录流程部署信息 .

SELECT * FROM act_re_procdef #流程定义表,记录流程定义信息

SELECT * FROM act_ge_bytearray #资源表

说明:

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

建议:

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

二,流程定义查询

      2.1 代码实现:

public class flowSelect {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    @Test
    public void queryProceccDefinition() {
        // 流程定义key
        String processDefinitionKey = "myProcess_1";
        String processDefinitionName = "请假申请单";
        // 获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 查询流程定义
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        //遍历查询结果
        List<ProcessDefinition> list = processDefinitionQuery
                .processDefinitionKey(processDefinitionKey)//
                //.processDefinitionNameLike(processDefinitionName)
                .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());
        }
    }
}

2.2 流程定义的表和api

        流程定义的表为:act_re_procdef,

        流程定义表:就是一条流程设计图可以有多个版本。

        流程定义的API :

ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();

ProcessDefinitionQuery 这个类就是act_re_procdef表的查询api,通过这个api,可以查询act_re_procdef中的各个字段。

 三,流程定义删除

3.1 代码实现

    @Test
    public void DelProcessDefinition(){
        //通过流程部署id,参数流程定义数据,如果该流程定义已有流程实例则删除出错
        repositoryService.deleteDeployment("1");
        //设置true,级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式
        //repositoryService.deleteDeployment("1",true);
    }

        说明:

        1) 使用 repositoryService 删除流程定义

        2) 如果该流程定义下没有正在运行的流程,则可以用普通删除。

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

3.2 activiti api 实现sql 步骤

        我们可以通过执行上面的代码,查看到执行日志里的sql

第一步:

select * from ACT_RE_DEPLOYMENT where ID_ = '1'   

        这个1就是我们传过去的参数

第二步:

select distinct RES.* from ACT_RE_PROCDEF RES WHERE RES.DEPLOYMENT_ID_ = '1' order by RES.ID_ asc LIMIT '2147483647' OFFSET '0' 

        第一个参数也是我们传过去的参数:1,

第三步:

select distinct RES.* from ACT_RE_MODEL RES WHERE RES.DEPLOYMENT_ID_ = ? order by RES.ID_ asc LIMIT ? OFFSET ? 

        Parameters: 1(String), 2147483647(Integer), 0(Integer)

第四步:

select * from ACT_PROCDEF_INFO where PROC_DEF_ID_ = ? 

Parameters: myProcess_1:1:4(String) 这个参数是第二步查出来的结果

第五步:

select J.* from ACT_RU_TIMER_JOB J where J.HANDLER_TYPE_ = ? and J.PROC_DEF_ID_ = ?  

Parameters: timer-start-event(String), myProcess_1:1:4(String)

第六步:

select * from ACT_RE_PROCDEF where KEY_ = ? and (TENANT_ID_ = '' or TENANT_ID_ is null) and VERSION_ = (select max(VERSION_) from ACT_RE_PROCDEF where KEY_ = ? and (TENANT_ID_ = '' or TENANT_ID_ is null)) 

  Parameters: myProcess_1(String), myProcess_1(String) 

第七步:

delete from ACT_GE_BYTEARRAY where DEPLOYMENT_ID_ = ?  

 Parameters: 1(String) 

第八步:

delete from ACT_RE_DEPLOYMENT where ID_ = ? 

 Parameters: 1(String)

第九步:

delete from ACT_RU_EVENT_SUBSCR where PROC_DEF_ID_ = ? and EXECUTION_ID_ is null and PROC_INST_ID_ is null  

Parameters: myProcess_1:1:4(String)        

第十步:

 delete from ACT_RU_IDENTITYLINK where PROC_DEF_ID_ = ?  

Parameters: myProcess_1:1:4(String)        

第十一步:

 delete from ACT_RE_PROCDEF where DEPLOYMENT_ID_ = ? 

 Parameters: 1(String)        

四,流程定义资源查询 并获取

4.1 方法一

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


    @Test
    public void getProcessResources() throws IOException {
        // 流程定义id
        String processDefinitionId = "myProcess_1:2:2504";
        // 获取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("e:/01.png");
        File file_bpmn = new File("e:/01.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);
        }
    }

4.2 方法二

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


    // 获取流程定义图片资源
    @Test
    public void getProcessResourcesPng() throws IOException {
        //流程部署id
        String deploymentId = "2501";
        // 通过流程引擎获取repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //读取资源名称
        List<String> resources =repositoryService.getDeploymentResourceNames(deploymentId);
        String resource_image = null;
        String resource_bpmn = null;
        //获取图片
        for(String resource_name :resources){
            if(resource_name.indexOf(".png")>=0){
                resource_image = resource_name;
            }
            if(resource_name.indexOf(".bpmn")>=0){
                resource_bpmn = resource_name;
            }
        }
        //图片输入流
        InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resource_image);
        InputStream inputStreamBpmn = repositoryService.getResourceAsStream(deploymentId, resource_bpmn);
        File exportFile = new File("e:/02.png");
        File exportFileBpmn = new File("e:/02.bpmn");
        FileOutputStream fileOutputStream = new FileOutputStream(exportFile);
        FileOutputStream fileOutputStreamBpmn = new FileOutputStream(exportFileBpmn);

        byte[] buffer = new byte[1024];
        int len = -1;
        //输出图片
        while((len = inputStream.read(buffer))!=-1){
            fileOutputStream.write(buffer, 0, len);
        }
        //输出BPMN
        while((len = inputStreamBpmn.read(buffer))!=-1){
            fileOutputStreamBpmn.write(buffer, 0, len);
        }
        inputStream.close();
        fileOutputStream.close();
        inputStreamBpmn.close();
        fileOutputStreamBpmn.close();
    }

说明:

1) deploymentId 为流程部署 ID

2) resource_name 为 act_ge_bytearray 表中 NAME_列的值

3) 使用 repositoryService 的 getDeploymentResourceNames方法可以获取指定部署下得所有文件的名 称

4) 使用 repositoryService 的 getResourceAsStream 方法传入部署 ID和资源图片名称可以获取部署下 指定名称文件的输入流

5) 最后的将输入流中的图片资源进行输出。

五,流程历史信息的查看

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


    /**
     * 查询历史流程信息
     */
    @Test
    public void testHistoric01(){

        HistoryService historyService = processEngine.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("==============================");
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vegetari

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值