zoukankan      html  css  js  c++  java
  • Activiti5工作流笔记一

    介绍工作流

      网上工作流的定义一大堆,这里就不去复制了,通俗的理解,工作流就是类似OA系统中请假审批、报销审批等一系列流程,下级提交的申请只有直系领导才能审批,其他人是没有权限的,而只有直系领导审批通过后,直系领导的直系领导才可以看到申请,并进行审批,以此类推。。。

      而Activiti工作流就可以实现类似的功能,本笔记将以最简单的方式让你明白怎么使用Activiti工作流,直接上代码

    准备环境

    1) JDK1.6或者更高版本

    2) 支持的数据库有:h2, mysql, oracle, postgres, mssql, db2等。

    3) 支持activiti5运行的jar包

    4) 开发环境为Eclipse3.7或者以上版本,myeclipse为8.6版本

    安装流程设计器(eclipse插件)

    方案一:

    有网络的情况下,安装流程设计器步骤如下:

    1) 打开 Help -> Install New Software. 在如下面板中:

    2) 在如下Install界面板中,点击Add按钮:

     

    3) 然后填入下列字段

    Name: Activiti BPMN 2.0 designer

    Location: http://activiti.org/designer/update/

    4) 回到Install界面,在面板正中列表中把所有展示出来的项目都勾上:

    5) 点击复选框

    Detail部分记得选中 "Contact all updates sites.." , 因为它会检查所有当前安装所需要的插件并可以被Eclipse下载.

    6) 安装完以后,点击新建工程new->Other…打开面板,如果看到下图内容:

    说明安装成功了。

     

    方案二

    没有网络的情况下,安装流程设计器步骤如下:

    首先下载离线插件包:

     https://files.cnblogs.com/files/lm970585581/activiti.zip

    将压缩包解压后

    这两个文件夹复制到Eclipse根目录下 ,重启即可

    注意:

    打开菜单Windows->Preferences->Activiti->Save下流程流程图片的生成方式:

    虽然流程引擎在单独部署bpmn文件时会自动生成图片,但在实际开发过程中,自动生成的图片会导致和BPMN中的坐标有出入,在实际项目中展示流程当前位置图会有问题。

    所在完成以上配置后,会由我们自己来管理流程图片。在发布流程时把流程规则文件和流程图片一起上传就行了。

    准备Activiti5开发环境

    activiti-5.13->wars目录下是一些示例项目,解压activiti-rest项目,导入activiti-rest目录中WEB-INFlib下所有包。添加到classpath中。

    另外需要根据我们正在使用的数据库添加相应的数据库jar包

    初始化数据库

    可以在activiti-restWEB-INFclasses下找到配置文件:如下

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
        <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://192.168.220.130:3306/activiti?useUnicode=true&amp;characterEncoding=utf8"></property>
            <property name="jdbcUsername" value="root"></property>
            <property name="jdbcPassword" value="root"></property>
            <!-- 
                创建表的策略
             -->
            <property name="databaseSchemaUpdate" value="true"></property>
        </bean>
    </beans>

    调用以下java代码,即可把需要的表创建出来

    import org.activiti.engine.ProcessEngine;
    import org.activiti.engine.ProcessEngineConfiguration;
    import org.junit.Test;
    
    public class CreateTable {
        @Test
        public void testCreateTable(){
            ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml")
                .buildProcessEngine();
        }
    }

    HelloWorld程序

     先画请假流程图

    注意:

    properties=>General中的ID和NAME可以设置每个步骤的名称:

    每个审批过程的properties=>Main config=>Assignee:设置能够审批的对象,这里部门经理审批设置为:张三,总经理审批设置为:李四

    保存后,在根目录下生成:

    JAVA程序如下:

    import java.util.List;
    
    import org.activiti.engine.ProcessEngine;
    import org.activiti.engine.ProcessEngineConfiguration;
    import org.activiti.engine.ProcessEngines;
    import org.activiti.engine.task.Task;
    import org.junit.Test;
    
    /**
     * 1、部署流程图
     * 2、启动流程实例
     * 3、发起申请
     * 4、审批
     * @author zd
     *
     */
    public class HelloWorld {
        /**
         * 部署流程图
         */
        @Test
        public void testDeploy(){
            //产生流程引擎
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            //获取仓库流程的实例
            processEngine.getRepositoryService()
            .createDeployment()
            .addClasspathResource("qingjia.bpmn")
            .addClasspathResource("qingjia.png")
            .deploy();
            /**
             * 这里使用RepositoryService部署流程定义
               addClasspathResource表示从类路径下加载资源文件,一次只能加载一个文件
             */
        }
        
        /**
         * 启动流程实例  pi=process instance
         */
        @Test
        public void testStartPI(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            processEngine.getRuntimeService()
            .startProcessInstanceById("qingjia:1:4");//ID在act_re_procdef这个表中可以看到
            //这里使用RuntimeService启动流程实例
        }
        
        /**
         * 完成任务
         */
        @Test
        public void testFinishTask(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            processEngine.getTaskService()
            .complete("104");//act_ru_task表中获取
        }
        
        /**
         * 根据张三查询任务
         */
        @Test
        public void testQueryTask(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            //查询任务列表
            List<Task> tasks = processEngine.getTaskService()
            .createTaskQuery()
            .taskAssignee("张三")
            .list();
            for (Task task : tasks) {
                System.out.println(task.getName());
            }
        }
    }

    流程定义

    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.List;
    import java.util.zip.ZipInputStream;
    
    import org.activiti.engine.ProcessEngine;
    import org.activiti.engine.ProcessEngines;
    import org.activiti.engine.repository.Deployment;
    import org.activiti.engine.repository.ProcessDefinition;
    import org.junit.Test;
    import org.springframework.transaction.annotation.Transactional;
    
    /**
     * pd=process definition
     * @author zd
     *   1、把流程图部署到activiti的引擎中   重点
     *       classpath
     *       inputstream
     *       zipinputstream
     *   2、对流程图进行删除   重点
     *   3、获取到流程图和bpmn文件  重点
     *   4、查询  了解
     *      查询部署
     *      查询流程定义
     */
    public class PDTest {
        /**
         * 涉及到的表
         *     act_ge_bytearray
         *         1、说明
         *             该表存储了bpmn文件和png图片
         *             从字段可以看出,根据deploymentID可以查询bpmn文件和png图片
         *         2、字段
         *             name_:存储该文件的路径名称
         *             deploymentid_id_:部署表的ID
         *             byte_:存放值(bpmn和png)
         *     act_re_deployment
         *         1、说明
         *             该表存储了部署的动作
         *         2、字段
         *            ID_:部署ID 主键
         *     act_re_procdef
         *         1、说明
         *             流程定义表
         *         2、字段
         *                id: 是由${name}:${version}:随机数   确定唯一的流程
         *             name_: 流程定义名称
         *             key_:  流程定义名称
         *             version_:  某一个流程定义的版本
         *             deployment_id_:部署表的ID
         *             
         *  说明:
         *      1、根据deploymentID-->查询图片和bpmn文件
         *      2、根据deploymentID-->查询流程定义
         *      3、只要流程名称不变,部署一次,版本号加1,id就发生变化,生成了一个新的deploymentID
         *      4、所以deploymentID和pdid是一一对应的关系
         */
        @Test
        public void testDeployFromClasspath(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            processEngine.getRepositoryService()
            .createDeployment()
            .addClasspathResource("qingjia.bpmn")
            .addClasspathResource("qingjia.png")
            .deploy();
        }
        
        /**
         * 通过inputStream的方式部署
         */
        @Test
        public void testDeployFromInputStream(){
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("qingjia.bpmn");
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            processEngine.getRepositoryService()
            .createDeployment()
            .addInputStream("qingjia.bpmn", inputStream)
            .deploy();
        }
        
        /**
         * 通过zip的方式部署
         */
        @Test
        public void testDeployFromZip(){
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("qingjia.zip");
            ZipInputStream zipInputStream = new ZipInputStream(inputStream);
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            processEngine.getRepositoryService()
            .createDeployment()
            .addZipInputStream(zipInputStream)
            .deploy();
        }
        
        /**
         * 把查询出来的图片放到E盘的根目录下
         */
        @Test
        public void testShowImage() throws Exception{
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            InputStream inputStream = processEngine.getRepositoryService()
            /**
             * 参数为pdid
             */
            .getProcessDiagram("qingjia:1:4");
            /**
             * 得到一个图片
             */
            //    OutputStream outputStream = new FileOutputStream("e:/processimg.png");
            //    for(int b=-1;(b=inputStream.read())!=-1;){
            //        outputStream.write(b);
            //    }
            //    inputStream.close();
            //    outputStream.close();
            /***************************************************************************************/
            /**
             *   第一个参数为deploymentId
             *   第二个参数为resourceName
             */
            /********************************************************************************/
            /**
             * 得到的是一个图片
             */
                //        InputStream inputStream2 = processEngine.getRepositoryService()
                //        .getResourceAsStream("101", "qingjia.png");
                //        
                //        OutputStream outputStream2 = new FileOutputStream("e:/processimg2.png");
                //        for(int b=-1;(b=inputStream2.read())!=-1;){
                //            outputStream2.write(b);
                //        }
                //        inputStream2.close();
                //        outputStream2.close();
                /**********************************************************************************/
            /**
             * 得到的是bpmn文件 
             */
            InputStream inputStream3 = processEngine.getRepositoryService()
            .getProcessModel("qingjia:1:4");
            OutputStream outputStream3 = new FileOutputStream("e:/processimg3.bpmn");
            for(int b=-1;(b=inputStream3.read())!=-1;){
                outputStream3.write(b);
            }
            inputStream3.close();
            outputStream3.close();
            /*************************************************************************************/
    
        }
        
        /**
         * 查询流程部署
         */
        @Test
        public void testQueryDeploy(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<Deployment> deployments = processEngine.getRepositoryService()
            .createDeploymentQuery()
            .list();
            for (Deployment deployment : deployments) {
                System.out.println(deployment.getId());
            }
        }
        
        /**
         * 根据部署ID查询部署  一个结果
         */
        @Test
        public void testQueryDeployById(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            Deployment deployment = processEngine.getRepositoryService()
            .createDeploymentQuery()
            .deploymentId("1")
            .singleResult();
            
                System.out.println(deployment.getId());
            
        }
        
        /**
         * 查询所有的流程定义
         */
        @Test
        public void testQueryPD(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<ProcessDefinition> processDefinitions = processEngine.getRepositoryService()
            .createProcessDefinitionQuery()
            .list();
            for (ProcessDefinition processDefinition : processDefinitions) {
                System.out.println(processDefinition.getKey());
                System.out.println(processDefinition.getId());
                System.out.println(processDefinition.getVersion());
            }
        }
        
        /**
         * 按照版本的从高到低进行排序
         */
        @Test
        public void testQueryPDByVersion(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<ProcessDefinition> processDefinitions = processEngine.getRepositoryService()
            .createProcessDefinitionQuery()
            .orderByProcessDefinitionVersion()
            .desc()
            .list();
            for (ProcessDefinition processDefinition : processDefinitions) {
                System.out.println(processDefinition.getKey());
                System.out.println(processDefinition.getId());
                System.out.println(processDefinition.getVersion());
            }
        }
        
        /**
         * 根据pdid查询流程定义
         * 根据 pdkey查询流程定义
         */
        //略。。
        
        /**
         * 删除
         */
        @Test
        public void testDelete(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            processEngine.getRepositoryService()
            //.deleteDeployment("");//该方法只能删除流程定义,一般不会使用
            .deleteDeployment("1", true);//该方法不仅能够删除流程定义,而且能够删除正在运行的流程实例
        }
    }

    流程实例、任务的执行

    import java.util.List;
    
    import org.activiti.engine.ProcessEngine;
    import org.activiti.engine.ProcessEngines;
    import org.activiti.engine.history.HistoricActivityInstance;
    import org.activiti.engine.history.HistoricTaskInstance;
    import org.activiti.engine.impl.bpmn.parser.handler.ProcessParseHandler;
    import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
    import org.activiti.engine.impl.pvm.process.ActivityImpl;
    import org.activiti.engine.runtime.ProcessInstance;
    import org.activiti.engine.task.Task;
    import org.junit.Test;
    
    /**
     * pi=process instance
     * @author zd
     * 1、启动流程实例
     * 2、完成任务
     * 3、任务的查询
     *         1、根据任务的执行人查询任务
     *         2、可以根据任务查询任务的执行人
     *         3、查看历史任务
     * 4、怎么样查看流程实例是否结束
     */
    public class PITest {
        /**
         * 启动流程实例
         *    涉及到的表
         *       act_hi_actinst   hi:history   actinst:action instance
         *          1、概念
         *               所有的正在执行的或者已经完成的节点
         *          2、字段
         *              act_type_:为节点的类型
         *              end_time_: 如果有值,说明该节点已经结束了
         *       act_hi_procinst   procinst:process instance
         *          1、概念
         *               所有的正在执行的或者已经完成的流程实例
         *          2、字段
         *               end_time_:如果该字段有值,说明这个流程实例已经结束了
         *               end_act_id_:说明该流程实例是在哪个节点结束的
         *       act_hi_taskinst   taskinst:task instance
         *          1、概念
         *              所有的正在执行的或者已经完成的任务节点
         *          2、字段
         *              end_time_:如果该字段有值,说明任务已经完成了
         *              delete_reason:如果该值为completed,说明该任务处于完成的状态
         *       act_ru_execution  ru:runtime   
         *          1、概念
         *              代表正在执行的流程实例 
         *          2、字段
         *              id_:主键  executionid
         *              proc_inst_id_:  process instanceid
         *              proc_def_id_:pdid
         *              act_id_:当前的流程实例正在执行的节点的ID的值
         *       act_ru_task
         *          1、概念
         *              代表正在执行的任务
         *          2、字段
         *             id_:主键   任务ID
         *             execution_id_:piid,executionid
         *             name_:任务名称
         *          3、说明
         *               该表是一个临时表,该表中的任务完成以后,这一行会被删除掉   
         *              
         */
        @Test
        public void testStartPI(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            ProcessInstance pi = processEngine.getRuntimeService()
            .startProcessInstanceById("qingjia:1:304");
            System.out.println(pi.getId());
        }
        
        /**
         * 查询所有的正在执行的流程实例
         */
        @Test
        public void testQueryPI(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<ProcessInstance> processInstances = processEngine.getRuntimeService()
            .createProcessInstanceQuery()
            .list();
            for (ProcessInstance processInstance : processInstances) {
                System.out.println(processInstance.getActivityId());
                System.out.println(processInstance.getId());
            }
        }
        
        /**
         * 查询当前正在执行的节点
         */
        @Test
        public void testQueryActivity(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<String> strings = processEngine.getRuntimeService()
            .getActiveActivityIds("401");
            for (String string : strings) {
                System.out.println(string);
            }
        }
        
        /**
         *获取当前的流程实例正在运行的节点的坐标
         */
        @Test
        public void getPix(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            /**
             * processDefinitionEntity代表流程图对象的实体
             * 
             * 根据pdid获取到流程定义实体
             */
            ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
                    .getProcessDefinition("qingjia:1:304");
            List<String> strings = processEngine.getRuntimeService()
                    .getActiveActivityIds("401");  //piid
            for (String string : strings) {
                /**
                 * ActivityImpl代表流程图上的每一个节点
                 */
                ActivityImpl activityImpl = processDefinitionEntity.findActivity(string);
                /**
                 * 获取到正在执行的流程节点的坐标
                 */
                System.out.println(activityImpl.getHeight());
                System.out.println(activityImpl.getWidth());
                System.out.println(activityImpl.getX());
                System.out.println(activityImpl.getY());
            }
        }
        
        /**
         * 查询所有的任务
         */
        @Test
        public void testQueryAllTask(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<Task> tasks = processEngine.getTaskService()
            .createTaskQuery()
            .list();
            for (Task task : tasks) {
                System.out.println(task.getId());
                System.out.println(task.getName());
            }
        }
        
        /**
         * 完成任务
         *    需要一个参数:taskId
         */
        @Test
        public void testFinishTask(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            processEngine.getTaskService()
            .complete("602");
        }
        
        /**
         * 根据任务的执行人查看任务
         */
        @Test
        public void testQueryTaskByAssignee(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<Task> tasks = processEngine.getTaskService()
            .createTaskQuery()
            .taskAssignee("张三")
            .list();
            for (Task task : tasks) {
                System.out.println(task.getId());
                System.out.println(task.getName());
            }
        }
        
        /**
         * 根据任务的执行人查看任务,并且按照时间的倒叙排序
         */
        @Test
        public void testQueryTaskByAssigneeByTime_DESC(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<Task> tasks = processEngine.getTaskService()
            .createTaskQuery()
            .taskAssignee("张三")
            .orderByTaskCreateTime()
            .desc()
            .list();
            for (Task task : tasks) {
                System.out.println(task.getId());
                System.out.println(task.getName());
            }
        }
        
        /**
         * 根据piid判断流程实例是否结束
         */
        @Test
        public void testQueryPIByPIID(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            ProcessInstance pi = processEngine.getRuntimeService()
            .createProcessInstanceQuery()
            .processInstanceId("401")
            .singleResult();
            if(pi==null){
                System.out.println("该流程实例已经结束了");
            }else{
                System.out.println("该流程实例正在执行中");
            }
        }
        
        
        /**
         * 查询已经完成的任务
         */
        @Test
        public void testQueryHistoryTask(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<HistoricTaskInstance> historicTaskInstances = processEngine.getHistoryService()
            .createHistoricTaskInstanceQuery()
            .finished()
            .list();
            for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
                System.out.println(historicTaskInstance.getAssignee());
                System.out.println(historicTaskInstance.getName());
                System.out.println(historicTaskInstance.getId());
            }
        }
        
        /**
         * 查询已经完成的activityimpl
         */
        @Test
        public void testQueryHistoryActivityImpl(){
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            List<HistoricActivityInstance> historicActivityInstances = processEngine.getHistoryService()
            .createHistoricActivityInstanceQuery()
            .list();
            for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
                System.out.println(historicActivityInstance.getActivityName());
            }
        }
    }

    Activiti5工作流笔记二

  • 相关阅读:
    洛谷P1352没有上司的舞会+树形二维DP
    高精度模板(从洛谷题解中骗来的
    Codeforces#398 &767C. Garland 树形求子节点的和
    LuoGu-P1122 最大子树和+树形dp入门
    HDU-3549Flow Problem 最大流模板题
    Codeforces Round #486 (Div. 3)988E. Divisibility by 25技巧暴力||更暴力的分类
    Codeforces Round #486 (Div. 3)988D. Points and Powers of Two
    数据结构&字符串:01字典树
    数据结构:可持久化平衡树
    数据结构:并查集-拆点
  • 原文地址:https://www.cnblogs.com/lm970585581/p/9308745.html
Copyright © 2011-2022 走看看