• activity 工作流学习(一)


     

    一、了解工作流

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

    2、工作流管理系统(Workflow Management System, WfMS)是一个软件系统,它完成工作量的定义和管理,并按照在系统中预先定义好的工作流逻辑进行工作流实例的执行。工作流管理系统不是企业的业务系统,而是为企业的业务系统的运行提供了一个软件的支撑环境。

    3、常见的工作流框架有Activity、JBPM、OSWorkFlow、WorkFlow。本系列使用activiti5.13版本。

    4、工作流框架底层需要有数据库提供支持,activiti5.13版本,有23张表。JBPM4.4框架有18张表。JBPM底层使用hibernate操作数据库。Activiti框架底层使用的mybatis操作数据库。

    二、Activiti介绍

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

    三、下载与目录结构

    官网:https://www.activiti.org/  ,没啥用,打开了也没啥东西。直接在GitHub上下载。

    GitHub:https://github.com/Activiti/Activiti  这里下载的时activity-dev

    目录结构如下:

    database :提供了建表语句。

    docs:该目录包含了三种文档:javadocs、userguide、xsd。

    1. javadocs:API文档,包名按照功能模块划分,org.activiti.engine.*。
    2. userguide:用户手册,包含环境配置、10分钟快速入门以及各个功能模块的使用教程。
    3. xsd:包含BPMN2.0规范的XSD文件以及Activiti扩展的自定义标签XSD。

    libs:开发用的jar包和源码包。

    wars:提供了两个例子程序。

    安装activiti流程设计器插件

    1、eclipse中安装如下:

    1.1、获得插件的安装包

     

    1.2、解压安装包,复制到eclipse中的dropins目录中

     

    1.3、重启eclipse,勾选save选项

     

    IDEA 安装Activiti Designer插件---actiBPM


    打开IDEA,按ctrl+alt+S,打开Pluging

    IDEA <wbr>安装Activiti <wbr>Designer插件---actiBPM



    IDEA <wbr>安装Activiti <wbr>Designer插件---actiBPM


    IDEA <wbr>安装Activiti <wbr>Designer插件---actiBPM

    IDEA <wbr>安装Activiti <wbr>Designer插件---actiBPM
     

    安装成功后,创建数据库:

    初始化表结构

    方式1、使用activiti框架提供的建表语句

    在database目录下找到相应数据库的建表语句,执行即可。这里我用的是mysql(可以手动执行,也可用工具)

     

    手动执行:

    工具的话就不用说了吧

    方式2、使用activiti框架的自动建表功能。activiti框架提供了和hibernate类似的自动建表功能。

    创建一个java项目,导入jar包,不知道导哪些jar包,可以到war目录解压示例程序。把lib目录中的jar包拷过来即可。当然数据库驱动包时必不可少的。

    1、 不使用配置文件(不建议)

     @Test
        public void test1(){
            //1.创建一个流程引擎配置对象
            ProcessEngineConfiguration configuration=  ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
            //设置数据源
            configuration.setJdbcDriver("com.mysql.jdbc.Driver");
            configuration.setJdbcUrl("jdbc:mysql:///activiti_demo");
            configuration.setJdbcUsername("root");
            configuration.setJdbcPassword("123456");
    
            //设置自动建表
            configuration.setDatabaseSchema("true");
    
            //创建一个流程引擎对象,在创建流程引擎对象时会自动建表
            ProcessEngine engine= configuration.buildProcessEngine();
        }

    2、使用配置文件

     配置文件可以到示例程序的class目录拷贝 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.StandaloneInMemProcessEngineConfiguration">
            <property name="jdbcDriver"  value="com.mysql.jdbc.Driver"/>
            <property name="jdbcUrl" value="jdbc:mysql:///activiti_demo"/>
            <property name="jdbcUsername" value="root" />
            <property name="jdbcPassword" value="123456" />
            <property name="databaseSchemaUpdate" value="true"/>
        </bean>
    </bean>

    java代码

       //使用配置文件
        @Test
        public void test2(){
            //1.创建一个流程引擎配置对象
            String resource="activiti-context.xml";
            String beanName="processEngineConfiguration";
            ProcessEngineConfiguration configuration=  ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(resource,beanName);
    
            //创建一个流程引擎对象,在创建流程引擎对象时会自动建表
            ProcessEngine engine= configuration.buildProcessEngine();
        }

    3、使用配置文件(使用默认配置),要求配置文件名称必须为activiti-context.xml或者activiti.cfg.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.StandaloneInMemProcessEngineConfiguration">
            <property name="jdbcDriver"  value="com.mysql.jdbc.Driver"/>
            <property name="jdbcUrl" value="jdbc:mysql:///activiti_demo"/>
            <property name="jdbcUsername" value="root" />
            <property name="jdbcPassword" value="123456" />
            <property name="databaseSchemaUpdate" value="true"/>
        </bean>
        <!--配置工厂,用于创建流程引擎 id必须为processEngine-->
        <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
            <property name="processEngineConfiguration" ref="processEngineConfiguration" />
        </bean>
    </bean>

    java代码

        //使用默认配置文件
        @Test
        public void test3(){
            ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        }

    了解25张表

    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_*: 通用数据, 用于不同场景下。

    使用框架提供的API完成流程操作

    可以在项目中加入log4j,将框架执行的sql输出到控制台,log4j提供的日志级别:Fatal error warn info debug trace

    部署流程定义

    需要先画好流程图

    /**
         * 部署流程定义(操作数据表:act_re_deployment、act_re_procdef、act_ge_bytearray)
         */
        @Test
        public void test4() {
            // 获得一个部署构建器对象,用于加载流程定义文件(test1.bpmn,test.png)完成流程定义的部署
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            DeploymentBuilder builder= processEngine.getRepositoryService().createDeployment();
            // 加载流程定义文件
            builder.addClasspathResource("process/test1.bpmn");
            builder.addClasspathResource("process/test1.png");
            // 部署流程定义
            Deployment deployment = builder.deploy();
            System.out.println(deployment.getId());
        }

    查询流程定义列表

        @Test
        public void test5() {
            //流程定义查询对象,用于查询act_re_procdef表
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            ProcessDefinitionQuery query = processEngine.getRepositoryService().createProcessDefinitionQuery();
            //添加查询条件
            query.processDefinitionKey("bxlc");
            query.orderByDeploymentId().desc();
            //分页查询
            query.listPage(0, 10);
            List<ProcessDefinition> list = query.list();
            for (ProcessDefinition item : list) {
                System.out.print(item.getId());
            }
        }
     

    启动流程实例

    什么是流程实例?根据一个流程定义具体的一次执行过程就是一个流程实例,一个流程定义对应多个流程实例(一对多关系)

     为了演示:在流程图中指定办理人是谁,现在是写死的,表示只能张三能提交请假申请。后面会讲解如何动态指定。

        //根据流程定义的Id启动一个流程实例(操作ACT_RU_EXECUTION、ACT_RU_TASK、ACT_HI_PROCINST、ACT_HI_ACTINST、ACT_HI_TASKINST、ACT_RU_IDENTITYLINK、ACT_HI_IDENTITYLINK表)
        @Test
        public void test6() {
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            String processDefinitionId="qjlc:1:104";
            ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceById(processDefinitionId);
            System.out.print(processInstance.getId());//201
        }

    查询个人任务列表

        @Test
        public void test7() {
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            TaskQuery query = processEngine.getTaskService().createTaskQuery();
            query.taskAssignee("张三");
            List<Task> list = query.list();
            for (Task item : list) {
                System.out.print(item.getId()+"==="+item.getName());//204===提交请假申请
            }
        }

    办理任务

        //办理任务(主要操作ACT_RU_EXECUTION、ACT_RU_TASK表)
        @Test
        public void test8() {
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            processEngine.getTaskService().complete("204");
        }

    办理任务后,流程就走到了下一个节点,再次查询张三个人任务列表就查不到了,此时用李四去查就可以了。

    使用Activiti框架的API操作流程

    /**
     * 使用Activiti框架的API操作流程
    */
    public class ActivitiAPITest {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        /**
         * 部署流程定义 方式一:读取单个的流程定义文件 方式二:读取zip压缩文件
         */
        @Test
        public void test1() {
            DeploymentBuilder deploymentBuilder = processEngine.getRepositoryService().createDeployment();
    
            // 方式一:读取单个的流程定义文件
            deploymentBuilder.addClasspathResource("test1.bpmn");
            deploymentBuilder.addClasspathResource("test1.png"); 
            Deployment deployment = deploymentBuilder.deploy();
    
            // 方式二:读取zip压缩文件
            /*ZipInputStream zipInputStream = new ZipInputStream(this.getClass().getClassLoader().getResourceAsStream("process.zip"));
            deploymentBuilder.addZipInputStream(zipInputStream);
            deploymentBuilder.name("请假流程部署");
            Deployment deployment = deploymentBuilder.deploy();*/
        }
    
        /**
         * 查询部署列表
         */
        @Test
        public void test2() {
            // 部署查询对象,查询表act_re_deployment
            DeploymentQuery query = processEngine.getRepositoryService().createDeploymentQuery();
            List<Deployment> list = query.list();
            for (Deployment deployment : list) {
                String id = deployment.getId();
                System.out.println(id);
            }
        }
    
        /**
         * 查询流程定义列表
         */
        @Test
        public void test3() {
            // 流程定义查询对象,查询表act_re_procdef
            ProcessDefinitionQuery query = processEngine.getRepositoryService().createProcessDefinitionQuery();
            List<ProcessDefinition> list = query.list();
            for (ProcessDefinition pd : list) {
                System.out.println(pd.getName() + "" + pd.getId());
            }
        }
    
        /**
         * 删除部署信息
         */
        @Test
        public void test4() {
            String deploymentId = "1001";
            // processEngine.getRepositoryService().deleteDeployment(deploymentId);
            processEngine.getRepositoryService().deleteDeployment(deploymentId,true);
        }
    
        /**
         * 删除流程定义(通过删除部署信息达到删除流程定义的目的)
         */
        @Test
        public void test5() {
            String deploymentId = "1401";
            // processEngine.getRepositoryService().deleteDeployment(deploymentId);
            processEngine.getRepositoryService().deleteDeployment(deploymentId,
                    true);
        }
    
        /**
         * 查询一次部署对应的流程定义文件名称和对应的输入流(bpmn png)
         * 
         * @throws Exception
         */
        @Test
        public void test6() throws Exception {
            String deploymentId = "101";
            List<String> names = processEngine.getRepositoryService()
                    .getDeploymentResourceNames(deploymentId);
            for (String name : names) {
                System.out.println(name);
                InputStream in = processEngine.getRepositoryService()
                        .getResourceAsStream(deploymentId, name);
                // 将文件保存到本地磁盘
                /*
                 * OutputStream out = new FileOutputStream(new File("d:\" + name));
                 * byte[] b = new byte[1024]; int len = 0; while((len =
                 * in.read(b))!=-1) { out.write(b, 0, len); } out.close();
                 */
                FileUtils.copyInputStreamToFile(in, new File("d:\" + name));
                in.close();
            }
        }
    
        /**
         * 获得png文件的输入流
         * 
         * @throws Exception
         */
        @Test
        public void test7() throws Exception {
            String processDefinitionId = "qjlc:9:1204";
            InputStream pngInputStream = processEngine.getRepositoryService()
                    .getProcessDiagram(processDefinitionId);
            FileUtils.copyInputStreamToFile(pngInputStream, new File("d:\my.png"));
        }
    
        /**
         * 启动流程实例 方式一:根据流程定义的id启动 方式二:根据流程定义的key启动(自动选择最新版本的流程定义启动流程实例)
         */
        @Test
        public void test8() {
            /*
             * String processDefinitionId = "qjlc:9:1204"; ProcessInstance
             * processInstance =
             * processEngine.getRuntimeService().startProcessInstanceById
             * (processDefinitionId ); System.out.println(processInstance.getId());
             */
    
            String processDefinitionKey = "qjlc";
            ProcessInstance processInstance = processEngine.getRuntimeService()
                    .startProcessInstanceByKey(processDefinitionKey);
            System.out.println(processInstance.getId());
        }
    
        /**
         * 查询流程实例列表,查询act_ru_execution表
         */
        @Test
        public void test9(){
            //流程实例查询对象,查询act_ru_execution表
            ProcessInstanceQuery query = processEngine.getRuntimeService().createProcessInstanceQuery();
            query.processDefinitionKey("qjlc");
            query.orderByProcessInstanceId().desc();
            query.listPage(0, 2);
            List<ProcessInstance> list = query.list();
            for (ProcessInstance pi : list) {
                System.out.println(pi.getId() + " " + pi.getActivityId());
            }
        }
    
        /**
         * 结束流程实例,操作的表act_ru_execution act_ru_task
         */
        @Test
        public void test10(){
            String processInstanceId = "1601";
            processEngine.getRuntimeService().deleteProcessInstance(processInstanceId , "我愿意");
        }
    
        /**
         * 查询任务列表
         */
        @Test
        public void test11(){
            //任务查询对象,查询act_ru_task表
            TaskQuery query = processEngine.getTaskService().createTaskQuery();
            String assignee = "李四";
            query.taskAssignee(assignee);
            query.orderByTaskCreateTime().desc();
            List<Task> list = query.list();
            for (Task task : list) {
                System.out.println(task.getId());
            }
        }
    
        /**
         * 办理任务
         */
        @Test
        public void test12(){
            String taskId = "2902";
            processEngine.getTaskService().complete(taskId);
        }
    
        /**
         * 直接将流程向下执行一步
         */
        @Test
        public void test13(){
            String executionId = "2701";//流程实例id
            processEngine.getRuntimeService().signal(executionId);
        }
        
        /**
         * 查询最新版本的流程定义列表
         */
        @Test
        public void test14(){
            ProcessDefinitionQuery query = processEngine.getRepositoryService().createProcessDefinitionQuery();
            query.orderByProcessDefinitionVersion().asc();
            List<ProcessDefinition> list = query.list();
            Map<String, ProcessDefinition> map = new HashMap<String, ProcessDefinition>();
            for (ProcessDefinition pd : list) {
                map.put(pd.getKey(), pd);
            }
            ArrayList<ProcessDefinition> lastList = new ArrayList<>(map.values());
            for (ProcessDefinition processDefinition : lastList) {
                System.out.println(processDefinition.getName() + "  "+ processDefinition.getVersion() );
            }
        }
    }

    Activiti框架提供的Service对象

    1. RepositoryService----操作静态的资源(流程定义,bpmn、png)
    2. RuntimeService-----操作流程实例(启动流程实例、查询流程实例、结束流程实例)
    3. TaskService-----操作任务(查询任务、办理任务)
    4. HistoryService----操作历史数据

    Activiti框架提供的对象(和表有对应关系)

    • Deployment-----act_re_deployment
    • ProcessDefinition----act_re_procdef
    • ProcessInstance-----act_ru_execution
    • Task-----act_ru_task

    使用网页版流程设计器

    1、将activiti-explorer.war复制到tomcat中

    2、启动tomcat,访问http://lcoalhost:8080/activiti-explorer

    3、使用kermit/kermit登录

    4、

    5、

     参考文档:http://www.cnblogs.com/llzgzljl/archive/2013/10/07/3356108.html

    学习资源:http://www.mossle.com/index.do

    转自:https://www.cnblogs.com/ginb/p/7624820.html

    目前还在学习中,希望会对大家有所帮助,觉得不错,就点赞支持一下。 另外,转载时请附带链接。谢谢!
  • 相关阅读:
    Oracle 建用户、 表空间脚本
    Java常见Jar包的用途
    EF:无法检查模型兼容性,因为数据库不包含模型元数据。
    Eclipse -Xms256M -Xmx640M -XX:PermSize=256m -XX:MaxPermSize=768m
    CentOS远程连接Windows操作系统
    spring boot / cloud (二十) 相同服务,发布不同版本,支撑并行的业务需求
    jvm
    jvm
    spring boot / cloud (十九) 并发消费消息,如何保证入库的数据是最新的?
    spring boot / cloud (十八) 使用docker快速搭建本地环境
  • 原文地址:https://www.cnblogs.com/dangkai/p/9364331.html
Copyright © 2020-2023  润新知