zoukankan      html  css  js  c++  java
  • day57_BOS项目_09

    • 今天内容安排:
      • 1、工作流概念
      • 2、安装流程设计器插件(是eclipse插件)--> 可以设计流程图
      • 3、了解activiti 框架目录结构
      • 4、创建activiti 数据库(共23张表)
      • 5、使用activiti 的API操作流程
      • 6、总结activiti 的API

    1、工作流概念

    • 工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。
    • 工作流管理系统(Workflow Management System, WfMS)是一个软件系统,它完成工作量的定义和管理,并按照在系统中预先定义好的工作流逻辑进行工作流实例的执行。工作流管理系统不是企业的业务系统,而是为企业的业务系统的运行提供了一个软件的支撑环境。
    • 工作流管理联盟(WfMC,Workflow Management Coalition)给出的关于工作流管理系统的定义是:工作流管理系统是一个软件系统,它通过执行经过计算的流程定义去支持一批专门设定的业务流程。工作流管理系统被用来定义、管理、和执行工作流程。
    • 工作流管理系统的目标:管理工作的流程以确保工作在正确的时间被期望的人员所执行--在自动化进行的业务过程中插入人工的执行和干预。

    2、安装流程设计器插件(是eclipse插件)--> 可以设计流程图

    方式一:
      第一步:获得activiti-eclipse-plugin.zip文件
      第二步:将zip文件解压到eclipse的dropins目录中


      第三步:重启eclipse,打开Window --> Preferences --> Activiti -- > Save --> 勾选 Export marshallers 选项
      方式一不一定能安装成功,因为activiti版本可能与eclipse的版本不符。
    方式二:
      第一步:点击eclipse上方工具栏的Help,选择 Install New Software… --> Add..
      第二步:填写插件名称和安装地址
        Name: Activiti BPMN 2.0 designer
        Location: http://activiti.org/designer/update/
        之后点击OK

        之后点击Next --> I accept the terms of the license agreements --> Finish,稍等几分钟,等待安装。
      第三步:安装完成后,我们在new的时候,操作面板中便有activiti的相关文件了。
      方式二也有可能不成功,我们这里推荐方式三。
    方式三:
      第一步:先下载好对应的离线包,可以是jar或者zip格式的,下载地址为:http://www.activiti.org/designer/archived/activiti-designer-5.18.0.zip
      第二步:然后还是在下述对话框中,只是不再输入url,而是改为选择已经下来的zip离线包的路径

      第三步:然后下一步下一步安装即可。
      注意:由于我在第一步中已经使用在线的方式安装过,所以即使我这里选择了离线包,后续安装的时候eclipse还是会尝试从网络上去下载,所以需要在Install New SoftWare 对话框中选择 "Avaible Software Suits"或 "Manage..",在弹出的对话框中选中刚才http路径的那个资源,把他删了,然后再来使用离线方式安装,此时才会真正使用离线安装包。
      第四步:重启eclipse,打开Window --> Preferences --> Activiti -- > Save --> 勾选 Export marshallers 选项

      第五步:使用安装好的插件设计流程图,点击新建工程New --> Other… 打开面板,如果看到下图内容:

    演示使用效果:

    3、了解activiti 框架目录结构

    • 工作流框架底层需要有数据库支持。
    • activiti5.13版本对应23张表,activiti框架底层使用mybatis操作数据库。
    • JBPM4.4框架底层对应18张表,底层使用hibernate操作数据库。
    • BPMN业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)。

    4、创建activiti 数据库(共23张表)

    4.1、执行框架提供的sql文件建表(建议)


    23张表如下:

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

    4.2、使用框架提供的自动建表方式(不建议)

    第一步:创建普通Java项目并导入jar包
    第二步:提供配置文件activiti-context.xml,进行相应的配置

    <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 name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti_day01"/>
            <property name="jdbcUsername" value="root"/>
            <property name="jdbcPassword" value="root"/>
            <property name="databaseSchemaUpdate" value="true"/><!-- 自动建表 -->
        </bean>
        <!-- 使用工厂创建流程引擎对象 -->
        <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
            <property name="processEngineConfiguration" ref="processEngineConfiguration"></property>
        </bean> 
    </beans>

    第三步:创建流程引擎对象,自动建表(2种方式)

    package com.itheima.activiti;

    import org.activiti.engine.ProcessEngine;
    import org.activiti.engine.ProcessEngineConfiguration;
    import org.activiti.engine.ProcessEngines;
    import org.junit.Test;

    public class HelloWorld {
        /**
         * 使用框架提供的自动建表方式创建23张表
         */

        @Test
        public void test1() {
            String resource = "activiti-context.xml"// 配置文件
            String beanName = "processEngineConfiguration";
            // 读取配置文件,获得流程引擎对象
            ProcessEngineConfiguration config = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(resource, beanName);
            ProcessEngine processEngine = config.buildProcessEngine();
        }

        /**
         * 使用默认配置的要求:
         *      1、配置文件必须在classpath根目录下
         *      2、配置文件名称必须为activiti-context.xml或者activiti.cfg.xml
         *      3、配置文件中配置对象的id必须为processEngineConfiguration 
         *      4、工厂对象的id必须为processEngine
         */

        @Test
        public void test2() {
            // 获得默认的流程引擎对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        }
    }

    5、使用activiti 的API操作流程

    使用插件设计一个流程图:

    5.1、部署流程定义

    • 即就是将流程定义规则保存到数据库。
      示例代码如下:
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        /**
         * 部署 流程定义,一共操作了3张数据表:
         *      act_re_deployment(部署表)
         *      act_re_procdef(流程定义表)
         *      act_ge_bytearray(二进制表)
         */

        @Test
        public void test3() 
    {
            // 创建一个部署构建器对象
            DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment();
            // 读取流程定义文件(bpmn、png)
            deploymentBuilder.addClasspathResource("qingjialiucheng.bpmn");
            deploymentBuilder.addClasspathResource("qingjialiucheng.png");
            // 部署流程定义
            Deployment deployment = deploymentBuilder.deploy();
            System.out.println(deployment.getId());
        }

    5.2、查询流程定义

        /**
         * 查询 流程定义,activiti框架一共操作了1张数据库表:
         *      act_re_procdef(流程定义表)
         */

        @Test
        public void test4() 
    {
            // 创建流程定义查询对象
            ProcessDefinitionQuery query = processEngine.getRepositoryService().createProcessDefinitionQuery();
            List<ProcessDefinition> list = query.list();
            for (ProcessDefinition pd : list) {
                System.out.println(" id = " + pd.getId() + 
                                   " name = " + pd.getName() + 
                                   " version = " + pd.getVersion() + 
                                   " key = " + pd.getKey());
            }
        }

    5.3、根据流程定义启动流程实例

    • 流程实例:根据某个流程定义一次具体的执行过程就是一个流程实例。流程定义和流程实例的关系是一对多。
        /**
         * 根据流程定义启动流程实例,activiti框架一共操作了2张数据库表:
         *      act_ru_execution(流程实例表)
         *      act_ru_task(任务表)
         */

        @Test
        public void test5() 
    {
            String processDefinitionId = "qingjialiucheng:2:104"// 流程定义id
            // 创建流程实例对象
            ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceById(processDefinitionId);
            System.out.println(processInstance.getId());
        }

    5.4、查询个人任务

        /**
         * 查询 个人任务,activiti框架一共操作了1张数据库表:
         *      act_ru_task(任务表)
         */

        @Test
        public void test6() 
    {
            // 创建任务查询对象
            TaskQuery query = processEngine.getTaskService().createTaskQuery();
            query.taskAssignee("王五"); // 根据办理人过滤
            query.orderByTaskCreateTime().desc(); // 根据任务创建时间排序,降序
            List<Task> list = query.listPage(010);
            for (Task task : list) {
                System.out.println(" id = " + task.getId() + 
                                   " name = " + task.getName() + 
                                   " processInstanceId = " + task.getProcessInstanceId());
            }
        }

    5.5、办理个人任务

        /**
         * 办理 个人任务,activiti框架一共操作了2张数据库表:
         *      act_ru_execution(流程实例表)
         *      act_ru_task(任务表)
         */

        @Test
        public void test7() 
    {
            String taskId = "304"// 任务id
            processEngine.getTaskService().complete(taskId);
        }

    6、总结activiti 的API

    • 几个接口(和表有对应关系):

      • Deployment --> act_re_deployment(部署表)
      • ProcessDefinition --> act_re_procdef(流程定义表)
      • ProcessInstance --> act_ru_execution(流程实例表)
      • Task --> act_ru_task(任务表)
    • 几个Query对象

      • DeploymentQuery --> act_re_deployment
      • ProcessDefinitionQuery --> act_re_procdef
      • ProcessInstanceQuery --> act_ru_execution
      • TaskQuery --> act_ru_task
    • 几个Service

      • RepositoryService --> 操作部署表、流程定义表、二进制表等静态资源信息表
      • RuntimeService --> 操作流程实例表、任务表等动态信息表
      • TaskService --> 操作任务表
      • HistoryService --> 操作历史表
      • IdentityService --> 操作用户表、组表、关系表

    示例代码如下:

    package com.itheima.activiti;

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    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.DeploymentBuilder;
    import org.activiti.engine.repository.ProcessDefinition;
    import org.activiti.engine.repository.ProcessDefinitionQuery;
    import org.activiti.engine.runtime.ProcessInstance;
    import org.activiti.engine.task.Task;
    import org.activiti.engine.task.TaskQuery;
    import org.apache.commons.io.FileUtils;
    import org.junit.Test;

    public class ActivitiAPITest {

        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        /**
         * 部署 流程定义 
         *      方式一:加载单个的流程定义文件 方式二:加载zip文件
         * @throws FileNotFoundException 
         */

        @Test
        public void test1() throws FileNotFoundException {
            DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment();

            // 方式一:加载单个的流程定义文件
            // deploymentBuilder.addClasspathResource("qingjialiucheng.bpmn");
            // deploymentBuilder.addClasspathResource("qingjialiucheng.png");
            // deploymentBuilder.deploy();

            // 方式二:加载zip文件
            // 从根路径下读一个文件,并返回该文件对应的输入流,使用类加载器对象获取classpath路径下的文件
            // ZipInputStream zipInputStream = new ZipInputStream(this.getClass().getClassLoader().getResourceAsStream("process.zip"));
            // 直接new一个文件输入流,文件位置灵活
            ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(new File("e:\process.zip"))); // 将.png文件和.bpmn文件压缩到process.zip中
            deploymentBuilder.addZipInputStream(zipInputStream);
            deploymentBuilder.deploy();
        }

        /**
         * 删除 流程定义
         */

        @Test
        public void test2() {
            String deploymentId = "501"// 部署id
            boolean cascade = true// 级联删除(cascade级联),很少使用
            processEngine.getRepositoryService().deleteDeployment(deploymentId, cascade);
        }

        /**
         * 查询 流程定义
                processEngine.getRepositoryService().createDeploymentQuery().list();
                processEngine.getRepositoryService().createProcessDefinitionQuery().list();
                processEngine.getRuntimeService().createProcessInstanceQuery().list();
                processEngine.getTaskService().createTaskQuery().list();
                processEngine.getIdentityService().createUserQuery().list();
                processEngine.getHistoryService().createHistoricActivityInstanceQuery().list();
         */

        @Test
        public void test3() {
            ProcessDefinitionQuery query = processEngine.getRepositoryService().createProcessDefinitionQuery();
            query.processDefinitionKey("qingjialiucheng"); // 根据key过滤,在流程定义表中,key是流程的标识,key相同,表示同一流程
            query.orderByProcessDefinitionVersion().asc();
            List<ProcessDefinition> list = query.listPage(010);
            for (ProcessDefinition processDefinition : list) {
                System.out.println(processDefinition.getId());
            }
        }

        /**
         * 方法一:查询 部署对应的流程定义文件的名称和输入流,该方式需要部署的id和文件名称,不够直接
         * 案例中两种方式都会用到
         *      我们知道,一旦我们将流程部署完毕,我们就跟项目中的process目录没有关系了,我们在浏览器上看到的png图片文件来自于二进制表,图片已经被我们存成二进制数据了
         * @throws FileNotFoundException 
         */

        @Test
        public void test4() throws Exception {
            String deploymentId = "501"// 部署id
            List<String> names = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId);
            for (String name : names) {
                // 获取文件输入流
                InputStream in = processEngine.getRepositoryService().getResourceAsStream(deploymentId, name);

                // 方式一:原始方法
                // 将文件输入流读取出来,然后通过文件输出流写入到磁盘上
                /*
                OutputStream out = new FileOutputStream(new File("e:\" + name));
                byte[] b = new byte[1024];
                int len = 0;
                while ((len = in.read(b)) != -1) {
                    out.write(b, 0, len);
                }
                out.close();
                in.close();
                */


                // 方式二:通过工具类
                FileUtils.copyInputStreamToFile(in, new File("e:\" + name));
                in.close();
            }
        }

        /**
         * 
         * 方法二:查询 部署对应的流程定义文件的输入流,该方式只需要流程定义id即可,够直接,但注意,该方法只能返回图片的输入流,xml的输入流返回不了
         * 案例中两种方式都会用到
         * @throws FileNotFoundException 
         */

        @Test
        public void test5() throws Exception {
            String processDefinitionId = "qingjialiucheng:1:504"// 流程定义id
            InputStream pngStream = processEngine.getRepositoryService().getProcessDiagram(processDefinitionId); 
            FileUtils.copyInputStreamToFile(pngStream, new File("e:\abc.png"));
        }

        /**
         * 根据流程定义启动流程实例
         *      方式一:根据流程定义id启动流程实例
         *      方式二:根据流程定义key启动流程实例(建议方式) --> 因为该方式可以根据当前最新版本的流程定义启动流程实例(即最新version值)
         */

        @Test
        public void test6() throws Exception {
            // 方式一:根据流程定义id启动流程实例
            // String processDefinitionId = "qingjialiucheng:1:504"; // 流程定义id
            // ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceById(processDefinitionId);
            // System.out.println(processInstance.getId() + " " + processInstance.getProcessDefinitionId());

            // 方式二:根据流程定义key启动流程实例
            String processDefinitionKey = "qingjialiucheng";
            ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(processDefinitionKey);
            System.out.println(processInstance.getId() + " " + processInstance.getProcessDefinitionId());
        }

        /**
         * 查询 流程实例
         */

        @Test
        public void test7() throws Exception {
            List<ProcessInstance> list = processEngine.getRuntimeService().createProcessInstanceQuery().list();
            for (ProcessInstance processInstance : list) {
                System.out.println(processInstance.getId());
            }
        }

        /**
         * 删除 流程实例
         */

        @Test
        public void test8() throws Exception {
            String processInstanceId = "701";
            String deleteReason = "女票过来安慰我了,突然又不想请假了";
            processEngine.getRuntimeService().deleteProcessInstance(processInstanceId, deleteReason);
        }

        /**
         * 查询 个人任务
         */

        @Test
        public void test9() throws Exception {
            TaskQuery query = processEngine.getTaskService().createTaskQuery();
            query.taskAssignee("张三"); // 任务处理人
            query.orderByTaskCreateTime().desc(); // 根据任务创建时间排序,降序
            List<Task> list = query.list();
            for (Task task : list) {
                System.out.println(task.getId());
            }
        }

        /**
         * 办理 个人任务
         */

        @Test
        public void test10() throws Exception{
            String taskId = "1004"// 任务id
            processEngine.getTaskService().complete(taskId);
        }
    }
  • 相关阅读:
    站立会议09
    站立会议08
    2020寒假生活学习日记(一)
    软件工程阅读笔记(六)之ASP.NET动态网站设计
    软件工程阅读笔记(五)之ASP.NET动态网站设计
    软件工程阅读笔记(四)之Python网络爬虫
    软件工程阅读笔记(三)之Android
    软件工程阅读笔记(二)之Android
    软件工程阅读笔记(一)之Python网络爬虫
    mapreduce数据清洗-第三阶段
  • 原文地址:https://www.cnblogs.com/chenmingjun/p/9794830.html
Copyright © 2011-2022 走看看