您的位置:首页 > 其它

【Activiti工作流】7.流程定义的CRUD(上)

2017-10-24 20:01 489 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。

工作流的23张表是如何存取的?每一步操作逻辑是什么样子的?我们来学习一下。

一、管理流程定义

1设计流程定义文档

1.1流程图

我们之前已经看过,常见流程图如下如所示:



包含了开始节点/结束节点/任务/流向线

1.2bpmn文件

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



说明:流程定义文档有两部分组成:

1)bpmn文件

流程规则文件。在部署后,每次系统启动时都会被解析,把内容封装成流程定义放入项目缓存中。Activiti框架结合这个xml文件自动管理流程,流程的执行就是按照bpmn文件定义的规则执行的,bpmn文件是给计算机执行用的。

2)展示流程图的图片

在系统里需要展示流程的进展图片,图片是给用户看的。

2部署流程定义(classpath路径加载文件)

[java]
view plain
copy

/**部署流程定义*/  
@Test  
public void deploymentProcessDefinition(){  
    //与流程定义和部署对象相关的Service  
    RepositoryService repositoryService=processEngine.getRepositoryService();  
      
    DeploymentBuilder deploymentBuilder=repositoryService.createDeployment();//创建一个部署对象  
    deploymentBuilder.name("helloWorld入门程序");//添加部署的名称  
    deploymentBuilder.addClasspathResource("diagrams/MyProcess.bpmn");//从classpath的资源加载,一次只能加载一个文件  
    deploymentBuilder.addClasspathResource("diagrams/MyProcess.png");//从classpath的资源加载,一次只能加载一个文件  
      
    Deployment deployment=deploymentBuilder.deploy();//完成部署  
      
    //打印我们的流程信息  
    System.out.println("部署Id:"+deployment.getId());  
    System.out.println("部署名称Name:"+deployment.getName());  
}  

说明:

1)先获取流程引擎对象:在创建时会自动加载classpath下的activiti.cfg.xml

//获取流程引擎对象

//getDefaultProcessEngine方法内部会自动读取名为activiti.cfg.xml文件的配置信息

ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();

2)首先获得默认的流程引擎,通过流程引擎获取了一个RepositoryService对象(仓库对象)

3)由仓库的服务对象产生一个部署对象配置对象,用来封装部署操作的相关配置。

4)这是一个链式编程,在部署配置对象中设置显示名,上传流程定义规则文件

5)向数据库表中存放流程定义的规则信息。

6)这一步在数据库中将操作三张表:

    a)act_re_deployment(部署对象表)

        存放流程定义的显示名和部署时间,每部署一次增加一条记录

    注:如果部署相同Key的流程,那么Version将会升级,也就是版本升级:

    图7.2.jpg

    启动该Key的流程时,默认启动最新版本(Version)的流程。

    b)act_re_procdef(流程定义表)

        存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录。

    注意:当流程定义的key相同的情况下,使用的是版本升级。

    c)act_ge_bytearray(资源文件表)

        存储流程定义相关的部署信息。即流程定义文档的存放地。每部署一次就会增加两条记录,    

    一条是关于bpmn规则文件的,一条是图片的(如果部署时只指定了bpmn一个文件,activiti    

    会在部署时解析bpmn文件内容自动生成流程图)。两个文件不是很大,都是以二进制形式存储在数据库中。

注意,部署流程定义的时候,可以把bpmn文件和png文件压缩成ZIP格式的压缩文件

进行上传:



处理代码有所改变:

[java]
view plain
copy

/**部署流程定义(Zip)*/  
@Test  
public void deploymentProcessDefinitionZip(){  
    //获得上传文件的输入流程  
    InputStream in=this.getClass().getClassLoader().getResourceAsStream("diagrams/MyProcess.zip");  
    ZipInputStream zipInputStream=new ZipInputStream(in);  
    //获取仓库服务,从类路径下完成部署  
    RepositoryService repositoryService=processEngine.getRepositoryService();  
    DeploymentBuilder deploymentBuilder=repositoryService.createDeployment();//创建一个部署对象  
    deploymentBuilder.name("helloWorld入门程序");//添加部署的名称  
    deploymentBuilder.addZipInputStream(zipInputStream);  
    Deployment deployment=deploymentBuilder.deploy();//完成部署  
      
    //打印我们的流程信息  
    System.out.println("部署Id:"+deployment.getId());  
    System.out.println("部署名称Name:"+deployment.getName());  
}  

3.查看流程定义

查询流程定义的信息

[java]
view plain
copy

/**查看流程定义 
 *  id:(key):(version):(随机值) 
 *  name:对应流程文件process节点的name属性 
 *  key:对应流程文件process节点的id属性 
 *  version:发布时自动生成的。如果是第一次发布的流程,version默认从1开始; 
 *  如果当前流程引擎中已存在相同的流程,则找到当前key对应的最高版本号,在最高版本号上加1*/  
@Test  
public void queryProcessDefinition() throws Exception{  
    //获取仓库服务对象,使用版本的升级排列,查询列表  
    List<ProcessDefinition> pdList=processEngine.getRepositoryService()  
                                .createProcessDefinitionQuery()  
                                //添加查询条件  
                                //.processDefinitionId(processDefinitionId)  
                                //.processDefinitionKey(processDefinitionKey)  
                                //.processDefinitionName(processDefinitionName)  
                                //排序(可以按照id/key/name/version/Cagetory排序)  
                                .orderByProcessDefinitionVersion().asc()  
                                //.count()  
                                //.listPage(firstResult, maxResults)  
                                //.singleResult()  
                                .list();//总的结果集数量  
    //便利集合,查看内容  
    for (ProcessDefinition pd:pdList) {  
        System.out.println("id:"+pd.getId());  
        System.out.println("name:"+pd.getName());  
        System.out.println("key:"+pd.getKey());  
        System.out.println("version:"+pd.getVersion());  
        System.out.println("resourceName:"+pd.getDiagramResourceName());  
        System.out.println("###########################################");  
    }  
}  

结果:



我们再次部署一次HelloWorld流程(用刚刚的Zip):



那么查询流程定义的信息的运行结果为:



可以看到流程定义的key值相同的情况下,版本是从1开始逐次升级的

流程定义的Id是【key:版本:生成ID】

说明:

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是一个自动生成的唯一的数字

8)重复部署一次,deploymentId的值以一定的形式变化

   规则act_ge_property表生成

4.删除流程定义

删除部署到activiti中的流程定义。

[java]
view plain
copy

/**删除流程*/  
@Test  
public void deleteDeployment(){  
    //删除发布信息  
    String deploymentId="1";  
    //获取仓库服务对象  
    RepositoryService repositoryService=processEngine.getRepositoryService();  
    //普通删除,如果当前规则下有正在执行的流程,则抛异常  
    //repositoryService.deleteDeployment(deploymentId);  
    //级联删除,会删除和当前规则相关的所有信息,正在执行的信息,也包括历史信息  
    repositoryService.deleteDeployment(deploymentId, true);  
      
}  

说明:

1)因为删除的是流程定义,而流程定义的部署是属于仓库服务的,所以应该先得到RepositoryService

2)如果该流程定义下没有正在运行的流程,则可以用普通删除。如果是有关联的信息,用级联删除。项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用。

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

查询出流程定义文档。主要查的是图片,用于显示流程用。

[java]
view plain
copy

/**查看流程附件(查看流程图片)*/  
@Test  
public void viewImage() throws Exception{  
    //从仓库中找需要展示的文件  
    String deploymentId="1";  
    List<String> names=processEngine.getRepositoryService()  
                                    .getDeploymentResourceNames(deploymentId);  
    String imageName=null;  
    for(String name:names){  
        System.out.println("name:"+name);  
        if(name.indexOf(".png")>0){  
            imageName=name;  
            break;  
        }  
    }  
    System.out.println("imageName:"+imageName);  
    if(imageName!=null){  
        File f=new File("e:/"+imageName);  
        //通过部署ID和文件名称得到文件的输入流  
        InputStream in = processEngine.getRepositoryService()  
                                      .getResourceAsStream(deploymentId, imageName);  
        FileUtils.copyInputStreamToFile(in, f);  
    }  
}  

运行结果:







说明:

1)deploymentId为流程部署ID

2)resourceName为act_ge_bytearray表中NAME_列的值

图7.9.jpg

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

图7.10.jpg

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

5)最后的有关IO流的操作,使用FileUtils工具的copyInputStreamToFile方法完成流程流程到文件的拷贝,将资源文件以流的形式输出到指定文件夹下。

如果我们的流程需要修改应该怎么操作呢?请看下一篇

转载请注明出处:http://blog.csdn.net/acmman/article/details/60981267

0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: