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


    深入了解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);
            }
        }
    }
  • 相关阅读:
    隐藏win10中“此电脑”里的6个子文件夹
    k2安装LEDE
    ubuntu下用apt-get安装lamp缺少mcrypt , curl
    Devexpress TreeList选择父级联动
    iPhone10.3.X越狱后SSH连接不上的问题(已解决)
    C#保存Base64格式图片
    PHP服务器文件管理器开发小结(九):jQuery动态表单实现文件下载
    利用Content-disposition实现无刷新下载图片文件
    jQuery多文件下载
    参考资料
  • 原文地址:https://www.cnblogs.com/zhanghengscnc/p/8835451.html
Copyright © 2020-2023  润新知