• Activiti第二篇【管理流程定义、执行任务和流程实例、流程变量】


    上篇Activiti只是一个快速入门案例,这篇就讲定义、部署、查看任务等等的一些细节【涉及到的数据库表、对象等等】…

    管理流程定义

    管理流程定义主要涉及到以下的4张表:

    -- 流程部署相关的表
    SELECT * FROM act_ge_bytearray # 通用字节资源表
    
    SELECT * FROM act_ge_property # 通用属性表,可以生成部署id
    
    SELECT * FROM act_re_deployment  #部署表
    
    SELECT * FROM act_re_procdef    # 流程定义表

    PNG资源

    在Eclipse中Activiti插件会自动生成一个BPMN与之对应的PNG图片,是需要通过加载PNG图片的

    
        @Test
        public void deploy() {
    
            //获取仓库服务 :管理流程定义
            RepositoryService repositoryService = processEngine.getRepositoryService();
            Deployment deploy = repositoryService.createDeployment()//创建一个部署的构建器
                    .addClasspathResource("LeaveActiviti.bpmn")//从类路径中添加资源,一次只能添加一个资源
                    .name("请求单流程")//设置部署的名称
                    .category("办公类别")//设置部署的类别
                    .deploy();
    
            System.out.println("部署的id"+deploy.getId());
            System.out.println("部署的名称"+deploy.getName());
        }

    而我们的Intellij idea插件不会自动生成PNG图片,但是我们在加载BPMN文件的时候,好像会自动插入PNG图片,数据库是有对应的记录的【我们是没有手动加载PNG图片资源的】

    这里写图片描述

    我们查看一下

    
        //查看bpmn 资源图片
        @Test
        public void viewImage() throws Exception{
            String deploymentId="201";
            String imageName=null;
            //取得某个部署的资源的名称  deploymentId
            List<String> resourceNames = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId);
            // buybill.bpmn  buybill.png
            if(resourceNames!=null&&resourceNames.size()>0){
                for(String temp :resourceNames){
                    if(temp.indexOf(".png")>0){
                        imageName=temp;
                    }
                }
            }
    
            /**
             * 读取资源
             * deploymentId:部署的id
             * resourceName:资源的文件名
             */
            InputStream resourceAsStream = processEngine.getRepositoryService()
                    .getResourceAsStream(deploymentId, imageName);
    
            //把文件输入流写入到文件中
            File file=new File("d:/"+imageName);
            FileUtils.copyInputStreamToFile(resourceAsStream, file);
        }

    可惜的是,查看出来的图片的中文数据会乱码

    这里写图片描述

    查看流程定义

    我们当时候查询流程定义是通过我们设置流程图的id来查看的….其实我们可以通过其他的属性来查询…并且可以查询出更加详细的数据

    
        //查看流程定义
        @Test
        public void queryProcessDefination(){
            String processDefiKey="buyBill";//流程定义key
            //获取流程定义列表
            List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
            //查询 ,好比where
    //      .processDefinitionId(proDefiId) //流程定义id
             // 流程定义id  : buyBill:2:704   组成 : proDefikey(流程定义key)+version(版本)+自动生成id
            .processDefinitionKey(processDefiKey)//流程定义key 由bpmn 的 process 的  id属性决定
    //      .processDefinitionName(name)//流程定义名称  由bpmn 的 process 的  name属性决定
    //      .processDefinitionVersion(version)//流程定义的版本
            .latestVersion()//最新版本
    
            //排序
            .orderByProcessDefinitionVersion().desc()//按版本的降序排序
    
            //结果
    //      .count()//统计结果
    //      .listPage(arg0, arg1)//分页查询
            .list();
    
    
            //遍历结果
            if(list!=null&&list.size()>0){
                for(ProcessDefinition temp:list){
                    System.out.print("流程定义的id: "+temp.getId());
                    System.out.print("流程定义的key: "+temp.getKey());
                    System.out.print("流程定义的版本: "+temp.getVersion());
                    System.out.print("流程定义部署的id: "+temp.getDeploymentId());
                    System.out.println("流程定义的名称: "+temp.getName());
                }
            }
        }

    资源来自ZIP

    我们还可以加载的是ZIP类型的资源数据

    
        //部署流程定义,资源来自zip格式
        @Test
        public void deployProcessDefiByZip(){
            InputStream in=getClass().getClassLoader().getResourceAsStream("BuyBill.zip");
            Deployment deploy = processEngine.getRepositoryService()
                    .createDeployment()
                    .name("采购流程")
                    .addZipInputStream(new ZipInputStream(in))
                    .deploy();
    
            System.out.println("部署名称:"+deploy.getName());
            System.out.println("部署id:"+deploy.getId());
        }

    删除流程定义

        //删除流程定义
        @Test
        public void deleteProcessDefi(){
            //通过部署id来删除流程定义
            String deploymentId="101";
            processEngine.getRepositoryService().deleteDeployment(deploymentId);
        }
    

    再次查询的时候,已经没有101这个流程定义的数据了。

    这里写图片描述


    流程实例与任务执行

    流程实例与任务执行的常用表有以下几个:

    
    -- 流程实例与任务
    
    SELECT * FROM act_ru_execution  # 流程执行对象信息
    SELECT * FROM act_ru_task   # 正在运行的任务表
    
    SELECT * FROM act_hi_procinst # 历史流程实例表
    SELECT * FROM act_hi_taskinst  # 历史流程任务表
    
    

    这里就简单简述一下流程实例与流程对象的区别:

    • (1)如果是单例流程,执行对象ID就是流程实例ID
    • (2)如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同
    • (3)一个流程中,流程实例只有1个,执行对象可以存在多个。

    开始流程

    
        @Test
        public void startProcess(){
            String processDefiKey="leaveActiviti";//bpmn 的 process id属性
            ProcessInstance pi = processEngine.getRuntimeService()
                    .startProcessInstanceByKey(processDefiKey);
    
            System.out.println("流程执行对象的id:"+pi.getId());//Execution 对象
            System.out.println("流程实例的id:"+pi.getProcessInstanceId());//ProcessInstance 对象
            System.out.println("流程定义的id:"+pi.getProcessDefinitionId());//默认执行的是最新版本的流程定义
        }

    查看正在运行的任务

    
    //查询正在运行任务 
        @Test
        public void queryTask(){
            //取得任务服务
            TaskService taskService = processEngine.getTaskService();
            //创建一个任务查询对象
            TaskQuery taskQuery = taskService.createTaskQuery();
            //办理人的任务列表
            List<Task> list = taskQuery.list();
            //遍历任务列表
            if(list!=null&&list.size()>0){
                for(Task task:list){
                    System.out.println("任务的办理人:"+task.getAssignee());
                    System.out.println("任务的id:"+task.getId());
                    System.out.println("任务的名称:"+task.getName());
    
                }
            }
    
        }

    查询SELECT * FROM act_ru_task 表

    这里写图片描述

    这里写图片描述


    获取流程实例的状态

    有的时候,我们需要判断它是在该流程,还是该流程已经结束了。我们可以根据获取出来的对象是否为空来进行判断

    
        //获取流程实例的状态
        @Test
        public void getProcessInstanceState(){
            String processInstanceId="605";
            ProcessInstance pi = processEngine.getRuntimeService()
                    .createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();//返回的数据要么是单行,要么是空 ,其他情况报错
            //判断流程实例的状态
            if(pi!=null){
                System.out.println("该流程实例"+processInstanceId+"正在运行...  "+"当前活动的任务:"+pi.getActivityId());
            }else{
                System.out.println("当前的流程实例"+processInstanceId+" 已经结束!");
            }
    
        }
    

    这里写图片描述


    查看历史流程实例的信息

    
        //查看历史执行流程实例信息
        @Test
        public void queryHistoryProcInst(){
            List<HistoricProcessInstance> list = processEngine.getHistoryService()
            .createHistoricProcessInstanceQuery()
            .list();
            if(list!=null&&list.size()>0){
                for(HistoricProcessInstance temp:list){
                    System.out.println("历史流程实例id:"+temp.getId());
                    System.out.println("历史流程定义的id:"+temp.getProcessDefinitionId());
                    System.out.println("历史流程实例开始时间--结束时间:"+temp.getStartTime()+"-->"+temp.getEndTime());
                }
            }
        }

    查询表:

    这里写图片描述

    这里写图片描述

    查看历史实例执行任务信息

    
        @Test
        public void queryHistoryTask(){
            String processInstanceId="605";
            List<HistoricTaskInstance> list = processEngine.getHistoryService()
                    .createHistoricTaskInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .list();
            if(list!=null&&list.size()>0){
                for(HistoricTaskInstance temp:list){
                    System.out.print("历史流程实例任务id:"+temp.getId());
                    System.out.print("历史流程定义的id:"+temp.getProcessDefinitionId());
                    System.out.print("历史流程实例任务名称:"+temp.getName());
                    System.out.println("历史流程实例任务处理人:"+temp.getAssignee());
                }
            }
        }

    给予对应的实例id就可以查询出执行到哪个任务了…

    这里写图片描述

    这里写图片描述

    执行任务

    根据任务的id,就可以把该任务执行了。

        @Test
        public void compileTask(){
            String taskId="608";
            //taskId:任务id
            processEngine.getTaskService().complete(taskId);
            System.out.println("当前任务执行完毕");
        }
    

    流程变量

    流程变量涉及到的数据库表:

    
    act_ru_variable:正在执行的流程变量表
    act_hi_varinst:流程变量历史表
    
    

    流程变量在工作流中扮演着一个非常重要的角色。例如:请假流程中有请假天数、请假原因等一些参数都为流程变量的范围。流程变量的作用域范围是只对应一个流程实例。也就是说各个流程实例的流程变量是不相互影响的。流程实例结束完成以后流程变量还保存在数据库中(存放到流程变量的历史表中)。

    这里写图片描述

    设置流程变量

    我们有两种服务可以设置流程变量,TaskService【任务服务】和RuntimeService【运行时服务】

    场景

    • 在流程开始的时候设置流程变量
    • 在完成某个任务的时候设置流程变量
    • 使用TaskService设置服务
    • 使用RuntimeService设置服务

    作用:

    • 传递业务参数
    • 动指定代理人【我们快速入门的例子是固定在流程定义图上写上代理人的】态
    • 指定连接【决定流程往哪边走】

    流程变量支持类型

    如果我们使用JavaBean来作为流程的变量,那么我们需要将JavaBean实现Serializable接口

    Javabean类型设置获取流程变量,除了需要这个javabean实现了Serializable接口外,还要求流程变量对象的属性不能发生变化,否则抛出异常。解决方案,固定序列化ID

    这里写图片描述

    setVariable和setVariableLocal的区别

    这里写图片描述

    例子

    
    //模拟流程变量设置
        @Test
        public void  getAndSetProcessVariable(){
            //有两种服务可以设置流程变量
    //      TaskService taskService = processEngine.getTaskService();
    //      RuntimeService runtimeService = processEngine.getRuntimeService();
    
            /**1.通过 runtimeService 来设置流程变量
             * executionId: 执行对象
             * variableName:变量名
             * values:变量值
             */
    //      runtimeService.setVariable(executionId, variableName, values);
    //      runtimeService.setVariableLocal(executionId, variableName, values);
            //设置本执行对象的变量 ,该变量的作用域只在当前的execution对象
    //      runtimeService.setVariables(executionId, variables); 
              //可以设置多个变量  放在 Map<key,value>  Map<String,Object>
    
            /**2. 通过TaskService来设置流程变量
             * taskId:任务id
             */
    //      taskService.setVariable(taskId, variableName, values);
    //      taskService.setVariableLocal(taskId, variableName, values);
    ////        设置本执行对象的变量 ,该变量的作用域只在当前的execution对象
    //      taskService.setVariables(taskId, variables); //设置的是Map<key,values>
    
            /**3. 当流程开始执行的时候,设置变量参数
             * processDefiKey: 流程定义的key
             * variables: 设置多个变量  Map<key,values>
             */
    //      processEngine.getRuntimeService()
    //      .startProcessInstanceByKey(processDefiKey, variables)
    
            /**4. 当执行任务时候,可以设置流程变量
             * taskId:任务id
             * variables: 设置多个变量  Map<key,values>
             */
    //      processEngine.getTaskService().complete(taskId, variables);
    
    
            /** 5. 通过RuntimeService取变量值
             * exxcutionId: 执行对象
             * 
             */
    //      runtimeService.getVariable(executionId, variableName);//取变量
    //      runtimeService.getVariableLocal(executionId, variableName);//取本执行对象的某个变量
    //      runtimeService.getVariables(variablesName);//取当前执行对象的所有变量
            /** 6. 通过TaskService取变量值
             * TaskId: 执行对象
             * 
             */
    //      taskService.getVariable(taskId, variableName);//取变量
    //      taskService.getVariableLocal(taskId, variableName);//取本执行对象的某个变量
    //      taskService.getVariables(taskId);//取当前执行对象的所有变量
        }
    
        //设置流程变量值
        @Test
        public void setVariable(){
            String taskId="1804";//任务id
            //采用TaskService来设置流程变量
    
            //1. 第一次设置流程变量
    //      TaskService taskService = processEngine.getTaskService();
    //      taskService.setVariable(taskId, "cost", 1000);//设置单一的变量,作用域在整个流程实例
    //      taskService.setVariable(taskId, "申请时间", new Date());
    //      taskService.setVariableLocal(taskId, "申请人", "何某某");//该变量只有在本任务中是有效的
    
    
            //2. 在不同的任务中设置变量
    //      TaskService taskService = processEngine.getTaskService();
    //      taskService.setVariable(taskId, "cost", 5000);//设置单一的变量,作用域在整个流程实例
    //      taskService.setVariable(taskId, "申请时间", new Date());
    //      taskService.setVariableLocal(taskId, "申请人", "李某某");//该变量只有在本任务中是有效的
    
            /**
             * 3. 变量支持的类型
             * - 简单的类型 :String 、boolean、Integer、double、date 
             * - 自定义对象bean  
             */
            TaskService taskService = processEngine.getTaskService();
            //传递的一个自定义bean对象
            AppayBillBean appayBillBean=new AppayBillBean();
            appayBillBean.setId(1);
            appayBillBean.setCost(300);
            appayBillBean.setDate(new Date());
            appayBillBean.setAppayPerson("何某某");
            taskService.setVariable(taskId, "appayBillBean", appayBillBean);
    
    
            System.out.println("设置成功!");
    
        }
    
    
        //查询流程变量
        @Test
        public void getVariable(){
            String taskId="1804";//任务id
    //      TaskService taskService = processEngine.getTaskService();
    //      Integer cost=(Integer) taskService.getVariable(taskId, "cost");//取变量
    //      Date date=(Date) taskService.getVariable(taskId, "申请时间");//取本任务中的变量
    ////        Date date=(Date) taskService.getVariableLocal(taskId, "申请时间");//取本任务中的变量
    //      String appayPerson=(String) taskService.getVariableLocal(taskId, "申请人");//取本任务中的变量
    ////        String appayPerson=(String) taskService.getVariable(taskId, "申请人");//取本任务中的变量
    //      
    //      System.out.println("金额:"+cost);
    //      System.out.println("申请时间:"+date);
    //      System.out.println("申请人:"+appayPerson);
    
    
            //读取实现序列化的对象变量数据
            TaskService taskService = processEngine.getTaskService();
            AppayBillBean appayBillBean=(AppayBillBean) taskService.getVariable(taskId, "appayBillBean");
            System.out.println(appayBillBean.getCost());
            System.out.println(appayBillBean.getAppayPerson());
    
        }
    
    
    public class AppayBillBean  implements Serializable{
        private Integer id;
        private Integer cost;//金额
        private String appayPerson;//申请人
        private Date date;//申请日期
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public Integer getCost() {
            return cost;
        }
        public void setCost(Integer cost) {
            this.cost = cost;
        }
        public String getAppayPerson() {
            return appayPerson;
        }
        public void setAppayPerson(String appayPerson) {
            this.appayPerson = appayPerson;
        }
        public Date getDate() {
            return date;
        }
        public void setDate(Date date) {
            this.date = date;
        }
    
    
    }

  • 相关阅读:
    有关Angular 2.0的一切
    后Angular时代二三事
    构建单页Web应用
    用JS渲染的单页面应用其实性能还是比较差的
    给一位打算从事前端,但是又有疑惑的在校大学生的回信
    企业文化与价值观 — 给新员工的一封信
    老码农的技术理想
    (OK) install vmware12 in fedora23
    ECMAScript——wikipedia
    《ECMAScript 6入门》——JavaScript
  • 原文地址:https://www.cnblogs.com/zhong-fucheng/p/7554367.html
Copyright © 2020-2023  润新知