Activiti-工作流入门

  工作流概述  

    工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。

  工作流Activity连接数据库(xml文件配置方法)

    --activiti.cfg.xml

    

    

    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- 连接数据库的配置 -->
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/study?useUnicode=true&amp;characterEncoding=utf8"></property>
        <property name="jdbcUsername" value="root"></property>
        <property name="jdbcPassword" value="123456"></property>
        
        <!-- 没有表创建表 -->
        <property name="databaseSchemaUpdate" value="true"></property>
    </bean>

  

 Activity工作流的23张数据库表

     1) ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。

     2) ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。这样运行时表可以一直很小速度很快。

    3) ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。

         4) ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。

         5) ACT_GE_*: 通用数据, 用于不同场景下。

  Activity工作流的核心——ProcessEngine(工作流的引擎)

  Activity工作流操作api

    RepositoryService 管理流程定义(仓库)

    RuntimeService 执行管理,包括启动、推进、删除流程实例等操作

    TaskService 任务管理

   Activity工作流的流程定义

    

package com.study.processdefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.junit.Test;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FileUtils;

public class ProcessDefinitions {
    
    ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
    
    /**
     * 部署流程定义(从classpath)
     */
    @Test
    public void deploymentProcessDefinition_classpath() {
        Deployment deployment =processEngine.getRepositoryService()
            .createDeployment()
            .name("流程定义")
            .addClasspathResource("diagrams/helloworld.bpmn")
            .addClasspathResource("diagrams/helloworld.png")
            .deploy();
        
        System.out.println("部署ID:"+deployment.getId());
        System.out.println("部署名称:"+deployment.getName());
        
    }

    /**
     * 部署流程定义(从zip)
     */
    @Test
    public void deploymentProcessDefinition_zip() {
        InputStream in=this.getClass().getClassLoader().getResourceAsStream("helloworld.zip");
        ZipInputStream zipin=new ZipInputStream(in);
        
        Deployment deployment=processEngine.getRepositoryService()
                    .createDeployment()
                    .name("流程定义")
                    .addZipInputStream(zipin)
                    .deploy();
        

        System.out.println("部署ID:"+deployment.getId());
        System.out.println("部署名称:"+deployment.getName());
    }
    
    /**
     * 查询流程定义
     */
    @Test
    public void findProcessDefinition() {
    List<ProcessDefinition> list=    processEngine.getRepositoryService()
        .createProcessDefinitionQuery()
//        .deploymentId(deploymentId)//使用部署对象ID查询
//        .processDefinitionKey(processDefinitionKey)//使用流程定义ID查询
//        .processDefinitionName(processDefinitionName)//使用流程定义的key查询
        
        /**排序*/
        .orderByProcessDefinitionCategory().asc()//按照版本的升序排列
//        .orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列
        
        /**
         * 返回的结果集
         */
        .list();//返回一个集合列表,封装流程定义
//        .singleResult();//返回唯一结果集
//        .count();//返回结果集数量
//        .listPage(firstResult, maxResults);//分页查询
        
        if(list!=null && list.size()>0) {
            for (ProcessDefinition pd : list) {
                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("###########################");
            }
        }
    }
    /**
     * 删除流程定义
     */
    @Test
    public void deleteProcessDefinition() {
        String deploymentId="";
        
        /**
         *不带级联的删除
         *    只能删除没有启动的流程,如果流程启动,就会抛出异常
         */
        processEngine.getRepositoryService()
                .deleteDeployment(deploymentId);
        
        /**
         * 级联删除
         *   不管流程是否启动,都可以删除
         */
        processEngine.getRepositoryService()
            .deleteDeployment(deploymentId,true);
        System.out.println("删除成功!!");
    }
    
    /**
     * 查看流程图
     * @throws IOException 
     */
    @Test
    public void viewPic() throws IOException {
        /**
         * 将生成图片写到文件夹下
         */
        String deploymentId="12501";
        //获取图片资源的名称
        List<String> list=processEngine.getRepositoryService()
                                    .getDeploymentResourceNames(deploymentId);
        
        //定义图片资源名称
        String resourceName="";
        if(list!=null && list.size()>0) {
            for (String name : list) {
                if(name.indexOf(".png")>=0) {
                    resourceName=name;
                }
            }
        }
        
        //获取图片的输入流
        InputStream in=processEngine.getRepositoryService()//
                                .getResourceAsStream(deploymentId, resourceName);
        
        //将图片生成 到D盘的目录下
        File file=new File("D:/"+resourceName);
        //将输入流的图片写到D盘下
        FileUtils.copyInputStreamToFile(in, file);
    }
    
    /**
     * 查询最新版本的流程定义
     */
    @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相同下不同版本的流程定义)
     */
    @Test
    public void deleteProcessDefinitionByKey() {
        //流程定义的key
        String key="";
        //先使用流程定义的key查询流程定义,查询出所有的版本
        List<ProcessDefinition> list=processEngine.getRepositoryService()
                                                    .createProcessDefinitionQuery()
                                                    .processDefinitionKey(key)
                                                    .list();
        //遍历,获取每个流程定义的部署ID
        if(list!=null && list.size()>0) {
            for (ProcessDefinition pd : list) {
                //获取部署ID
                String deploymentId=pd.getDeploymentId();
                processEngine.getRepositoryService()
                            .deleteDeployment(deploymentId,true);
            }
        }
    }
}

  流程定义不能被修改  

  流程定义相关的表

    act_re_deployment 部署对象表

    act_re_procdef    流程定义表

    act_ge_bytearray  资源文件表

    act_ge_property     主键生成策略表

  

  Activity工作流执行任务

    

package com.study.activiti;

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;



public class HelloWorld {

        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        
        /**
         * 部署流程定义
         */
        @Test
        public void deploymentProcessDefinition() {
            Deployment deployment=processEngine.getRepositoryService() //与流程定义和部署对象相关的service
                                .createDeployment() //创建一个部署对象
                                .name("helloworld入门程序")//添加部署的名称
                                .addClasspathResource("diagrams/helloworld.bpmn")//从classpath的资源中加载,一次只能加载一个文件
                                .addClasspathResource("diagrams/helloworld.png")//从classpath的资源中加载,一次只能加载一个文件
                                .deploy();//完成部署
            System.out.println("部署ID:"+deployment.getId());
            System.out.println("部署名称:"+deployment.getName());//helloworld入门程序
        }
        
        /**
         * 启动流程实例
         */
        @Test
        public void startProcessInstance() {
            
            //流程定义的key
            String processDefinitionKey="helloworldId";
            ProcessInstance pi=processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service
                    .startProcessInstanceByKey(processDefinitionKey);//使用流程定义的key启动流程实例,key对应helloworld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动
            
            System.out.println("流程实例ID:"+pi.getId());
            System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
        }
        
        /**
         * 查询当前人的个人任务
         */
        @Test 
        public void findMyPersonalTask() {
            String assignee="王五";
            List<Task> list=processEngine.getTaskService()//与正在执行的任务管理相关的Service
                            .createTaskQuery()//创建任务查询对象
                            .taskAssignee(assignee)//指定个人任务查询,指定办理人
                            .list();
            
            if(list!=null && list.size()>0) {
                for (Task task : list) {
                    System.out.println("任务ID:"+task.getId());
                    System.out.println("任务名称:"+task.getName());
                    System.out.println("任务的创建时间:"+task.getCreateTime());
                    System.out.println("任务的办理人:"+task.getAssignee());
                    System.out.println("流程实例ID:"+task.getProcessInstanceId());
                    System.out.println("执行对象ID:"+task.getExecutionId());
                    System.out.println("流程定义ID:"+task.getProcessDefinitionId());
                    System.out.println("####################################");
                }
            }
        }
        
        /**
         * 完成我的任务
         */
        @Test
        public void completeMyPersonalTask() {
            //任务ID
            String taskId="7502";
            processEngine.getTaskService()//与正在执行的任务管理相关的Service
                        .complete(taskId);
            System.out.println("完成任务:任务ID:"+taskId);
        }
        
        /**
         * 查询流程状态
         *     判断流程是否正在执行,还是结束
         */
        @Test
        public void isProcessEnd() {
            String processInstanceId="15001";
            ProcessInstance pi=processEngine.getRuntimeService()//表示正在执行的流程实例和执行对象
                    
                                            .createProcessInstanceQuery()//创建流程实例查询
                                            .processInstanceId(processInstanceId)//表示正在执行的流程实例和执行对象
                                            .singleResult();
            
            if(pi==null) {
                System.out.println("流程已经结束");
            }else {
                System.out.println("流程没有结束");
            }
            
        }
}

  执行流程相关的数据表

  act_ru_execution 正在执行的执行对象表

  act_hi_procinst 流程实例的历史表

  act_ru_task    正在执行的任务表(只有节点是UserTask的时候该表存在数据)

  act_hi_task   任务历史表(只有节点是UserTask的时候该表存在数据)

  act_hi_actinst  所有活动节点的历史表

  * 如果是单例流程(没有分支和聚合),那么流程实例ID和执行对象ID是相同

 *一个流程实例只有一个,执行对象可以存在多个(如果存在分支和聚合)

猜你喜欢

转载自www.cnblogs.com/Lshiyun/p/9698726.html