zoukankan      html  css  js  c++  java
  • Activiti第一篇【介绍、配置开发环境、快速入门】

    Activiti介绍

    什么是Activiti?

    Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss jBPM的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务
    流程图。

    我们即将学习的是一个业务流程管理框架, 常见开源工作流引擎框架 : OSWorkFlow、jBPM(jboss business process management),Activiti工作流(是对jBPM升级)。一般我们称作为工作流框架..

    为什么要学习Activiti

    那我们为什么要学习业务流程管理框架呢???学习它干嘛???工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”

    我们来提出一个常见的需求来更好地理解:

    我们在学生时代,肯定会遇到请假写请假条的情况,如果学校的请假抓得非常严,就需要经过多层的同意才能确定能不能请假..

    这里写图片描述

    班主任->任课老师->教学总监->校长这么一个流程,首先我们先明确一点:我们作为一个学生,不可能直接跳过老师,去找校长申请请假的【校长是你随便找的吗??】

    因此我们请假的流程是一步一步的,并不能做跳跃

    也就是说,当班主任没有批准请假的时候,即使你去找任课老师了,任课老师会让你回去找班主任的,作为任课老师了,只关注班主任有没有批准你请假,同理,作为校长,只关注教学总监有没有批准你请假

    进一步说:当教学总监还没有批准你请假时,你请假的请求是不会出现在校长的范围里的

    其实是非常好理解的,就是一步步往下执行,当还没有执行到自己处理的点子上时,是不会有对应的处理请求的。分工有序

    对上面的请假流程进行分析,如果我们没有使用框架,而把这么一个请假流程写到我们的网站中,我们会怎么做呢??

    这里写图片描述

    我们需要维护一个变量,来不断传递过去给下一个处理者…如果一切正常,需求不会变,并没有条件的处理。这是我们非常希望看到的…但是,如果有条件判断【请假三天以下、请假三天以上的处理方式不一样】,需求会变【不需要校长批准了,教学总监批准完,你就能够请假了】,那么我们的代码就会变得乱

    基于这么一个原因,我们是需要学习一个框架来帮我们完成工作流的…

    采用工作流管理系统的优点

    • 1、提高系统的柔性,适应业务流程的变化
    • 2、实现更好的业务过程控制,提高顾客服务质量
    • 3、降低系统开发和维护成本

    快速入门Activiti

    首先我们来梳理一下Activiti的开发步骤:

    1. 我们要用到一个工作流,首先就要把这个工作流定义出来【也就是工作流的步骤的怎么样的】,Activiti支持以“图”的方式来定义工作流
    2. 定义完工作流,就要部署到起来【我们可以联想到Tomcat,我们光下载了Tomcat是没有用的,要把它部署起来】
    3. 随后我们就执行该工作流,该工作流就随着我们定义的步骤来一一执行!

    BPMN

    业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)

    BPMN这个就是我们所谓把工作流定义出来的流程图..

    数据库相关

    我们在执行工作流步骤的时候会涉及到很多数据【执行该流程的人是谁、所需要的参数是什么、包括想查看之前流程执行的记录等等】,因此我们会需要用到数据库的表来保存数据…

    由于我们使用的是Activiti框架,这个框架会自动帮我们把对应的数据库表创建起来,它涉及的表有23个,但是常用的并不是很多,因此也不用很慌…

    下面就列举一下表的情况

    
    Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。
    ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
    ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
    ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
    ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
    ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。

    搭建配置环境

    我这里使用的Intellij idea来使用Activiti,首先,我们得下载插件来使用Activiti【因为定义流程图需要用到插件】

    详情可以看这篇博文:http://blog.sina.com.cn/s/blog_4b3196670102woix.html

    Activiti插件中文乱码问题:

    http://www.cnblogs.com/mymelody/p/6049291.html

    流程之前的连线是通过图中的蓝色小点点拖动来进行连接的

    导入对应的jar包

    • activation-1.1.jar
    • activiti-bpmn-converter-5.13.jar
    • activiti-bpmn-layout-5.13.jar
    • activiti-bpmn-model-5.13.jar
    • activiti-common-rest-5.13.jar
    • activiti-engine-5.13.jar
    • activiti-json-converter-5.13.jar
    • activiti-rest-5.13.jar
    • activiti-simple-workflow-5.13.jar
    • activiti-spring-5.13.jar
    • aopalliance-1.0.jar
    • commons-dbcp-1.4.jar
    • commons-email-1.2.jar
    • commons-fileupload-1.2.2.jar
    • commons-io-2.0.1.jar
    • commons-lang-2.4.jar
    • commons-pool-1.5.4.jar
    • h2-1.3.170.jar
    • hamcrest-core-1.3.jar
    • jackson-core-asl-1.9.9.jar
    • jackson-mapper-asl-1.9.9.jar
    • javaGeom-0.11.0.jar
    • jcl-over-slf4j-1.7.2.jar
    • jgraphx-1.10.4.2.jar
    • joda-time-2.1.jar
    • junit-4.11.jar
    • log4j-1.2.17.jar
    • mail-1.4.1.jar
    • mybatis-3.2.2.jar
    • mysql-connector-java.jar
    • org.restlet.ext.fileupload-2.0.15.jar
    • org.restlet.ext.jackson-2.0.15.jar
    • org.restlet.ext.servlet-2.0.15.jar
    • org.restlet-2.0.15.jar
    • slf4j-api-1.7.2.jar
    • slf4j-log4j12-1.7.2.jar
    • spring-aop-3.1.2.RELEASE.jar
    • spring-asm-3.1.2.RELEASE.jar
    • spring-beans-3.1.2.RELEASE.jar
    • spring-context-3.1.2.RELEASE.jar
    • spring-core-3.1.2.RELEASE.jar
    • spring-expression-3.1.2.RELEASE.jar
    • spring-jdbc-3.1.2.RELEASE.jar
    • spring-orm-3.1.2.RELEASE.jar
    • spring-tx-3.1.2.RELEASE.jar

    开发步骤

    上面已经说过了,我们要想使用Activiti就需要有数据库的支持,虽然Activiti是自动帮我们创建对应的数据库表,但是我们是需要配置数据库的信息的。我们配置数据库的信息,接着拿到Activiti最重要的API——Activiti引擎

    这里写图片描述

    得到工作流引擎

    Activiti提供使用代码的方式来配置数据库的信息

    
    
        @Test
        public void createActivitiEngine(){
    
    /*        *1.通过代码形式创建
             *  - 取得ProcessEngineConfiguration对象
             *  - 设置数据库连接属性
             *  - 设置创建表的策略 (当没有表时,自动创建表)
             *  - 通过ProcessEngineConfiguration对象创建 ProcessEngine 对象*/
    
             //取得ProcessEngineConfiguration对象
             ProcessEngineConfiguration engineConfiguration=ProcessEngineConfiguration.
             createStandaloneProcessEngineConfiguration();
             //设置数据库连接属性
             engineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
             engineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activitiDB?createDatabaseIfNotExist=true"
             + "&useUnicode=true&characterEncoding=utf8");
             engineConfiguration.setJdbcUsername("root");
             engineConfiguration.setJdbcPassword("root");
    
    
             // 设置创建表的策略 (当没有表时,自动创建表)
             //       public static final java.lang.String DB_SCHEMA_UPDATE_FALSE = "false";//不会自动创建表,没有表,则抛异常
             //       public static final java.lang.String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";//先删除,再创建表
             //       public static final java.lang.String DB_SCHEMA_UPDATE_TRUE = "true";//假如没有表,则自动创建
             engineConfiguration.setDatabaseSchemaUpdate("true");
             //通过ProcessEngineConfiguration对象创建 ProcessEngine 对象
            ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
             System.out.println("流程引擎创建成功!");
    
        }

    Activiti也可以通过配置文件来配置数据库的信息,加载配置文件从而得到工作流引擎

    
            /**2. 通过加载 activiti.cfg.xml 获取 流程引擎 和自动创建数据库及表
             * 
    
            ProcessEngineConfiguration engineConfiguration=
                    ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
                //从类加载路径中查找资源  activiti.cfg.xm文件名可以自定义
            ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
            System.out.println("使用配置文件Activiti.cfg.xml获取流程引擎");
            */

    这里写图片描述

    上面的那种加载配置文件方式,配置文件的名字是可以自定义的,如果我们配置文件的名字默认就是activiti.cfg.xml的话,也是放在类路径下,我们就可以使用默认的方式来进行加载了!

    
    
        @Test
        public void createActivitiEngine(){
            /**
             * 3. 通过ProcessEngines 来获取默认的流程引擎
             */
            //  默认会加载类路径下的 activiti.cfg.xml
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            System.out.println("通过ProcessEngines 来获取流程引擎");
        }
    

    定义工作流

    定义工作流就需要我们刚才下载的插件了,我们是使用图形的方式来定义工作流的….

    这里写图片描述

    在每个流程中,我们都可以指定对应的处理人是谁,交由谁处理

    部署工作流

    我们上面已经定义了工作流了,工作流引擎我们也已经拿到了,接下来就是把工作流部署到工作流引擎中了

        @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());
        }
    

    相对应的数据库表就会插入数据、涉及到的数据库表后面会详细说明。现在我们只要了解到,我们工作流引擎执行操作会有数据库表记录

    这里写图片描述


    执行工作流

    指定指定工作流就是我们定义时工作流程表的id

    这里写图片描述

    
    
        @Test
        public void startProcess(){
    
            //指定执行我们刚才部署的工作流程
            String processDefiKey="leaveBill";
            //取运行时服务
            RuntimeService runtimeService = processEngine.getRuntimeService();
            //取得流程实例
            ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefiKey);//通过流程定义的key 来执行流程
            System.out.println("流程实例id:"+pi.getId());//流程实例id
            System.out.println("流程定义id:"+pi.getProcessDefinitionId());//输出流程定义的id
        }

    查询当前任务的信息

    刚才我们已经开始了工作流了,随后工作流应该去到了申请请假的流程,申请请假的处理人是钟福成,我们可以查询出对应的信息:

        //查询任务
        @Test
        public void queryTask(){
            //任务的办理人
            String assignee="钟福成";
            //取得任务服务
            TaskService taskService = processEngine.getTaskService();
            //创建一个任务查询对象
            TaskQuery taskQuery = taskService.createTaskQuery();
            //办理人的任务列表
            List<Task> list = taskQuery.taskAssignee(assignee)//指定办理人
                    .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());
                }
            }
        }
    

    这里写图片描述

    处理任务

    我们现在处理流程去到“申请请假”中,处理人是钟福成…接着就是钟福成去处理任务,根据任务的id使得流程继续往下走

    任务的id刚才我们已经查询出来了【上面】,我们如果是在web端操作数据的话,那么只要传递过去就行了!

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

    这里写图片描述

    当我们处理完该任务的时候,就到了批准【班主任】任务了,我们查询一下是不是如我们想象的效果:

    这里写图片描述

    我们按照定义的工作流程图一步一步往下走,最终把流程走完

    这里写图片描述


  • 相关阅读:
    字节码编程,Javassist篇四《通过字节码插桩监控方法采集运行时入参出参和异常信息》
    字节码编程,Javassist篇三《使用Javassist在运行时重新加载类「替换原方法输出不一样的结果」》
    字节码编程,Javassist篇二《定义属性以及创建方法时多种入参和出参类型的使用》
    字节码编程,Javassist篇一《基于javassist的第一个案例helloworld》
    CPU瞒着内存竟干出这种事
    可怕!CPU竟成了黑客的帮凶!
    完了!CPU一味求快出事儿了!
    如果平行宇宙也有编程语言
    你离黑客的距离,就差这20个神器了
    哈希表哪家强?几大编程语言吵起来了!
  • 原文地址:https://www.cnblogs.com/zhong-fucheng/p/7554368.html
Copyright © 2011-2022 走看看