zoukankan      html  css  js  c++  java
  • 学习文档-activiti工作流-单独篇

    activiti工作流

    一、导包与配置文件

            <properties>
                <java.version>1.8</java.version>
                <slf4j.version>1.6.6</slf4j.version>
                <log4j.version>1.2.12</log4j.version>
                <activiti.version>7.1.0.M6</activiti.version>
            </properties>		
    
    		<!-- activiti -->
    		<dependency>
    			<groupId>org.activiti</groupId>
    			<artifactId>activiti-engine</artifactId>
    			<version>${activiti.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.activiti</groupId>
    			<artifactId>activiti-spring</artifactId>
    			<version>${activiti.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.activiti</groupId>
    			<artifactId>activiti-bpmn-model</artifactId>
    			<version>${activiti.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.activiti</groupId>
    			<artifactId>activiti-bpmn-converter</artifactId>
    			<version>${activiti.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.activiti</groupId>
    			<artifactId>activiti-json-converter</artifactId>
    			<version>${activiti.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.activiti</groupId>
    			<artifactId>activiti-bpmn-layout</artifactId>
    			<version>${activiti.version}</version>
    		</dependency>
    
    
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    		</dependency>
    
    		<!-- log start -->
    		<dependency>
    			<groupId>log4j</groupId>
    			<artifactId>log4j</artifactId>
    			<version>${log4j.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-api</artifactId>
    			<version>${slf4j.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-log4j12</artifactId>
    			<version>${slf4j.version}</version>
    		</dependency>
    		<!-- log end -->
    
    		<dependency>
    			<groupId>org.mybatis</groupId>
    			<artifactId>mybatis</artifactId>
    			<version>3.4.5</version>
    		</dependency>
    
    		<dependency>
    			<groupId>commons-dbcp</groupId>
    			<artifactId>commons-dbcp</artifactId>
    			<version>1.4</version>
    		</dependency>
    

    配置文件 activiti.cfg.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    						http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd
    						http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!--数据源配置dbcp-->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://localhost:3306/activiti?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=UTC" />
            <property name="username" value="root" />
            <property name="password" value="root" />
        </bean>
        <!--activiti单独运行的ProcessEngine配置对象(processEngineConfiguration),使用单独启动方式
            默认情况下:bean的id=processEngineConfiguration
        -->
    
        <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!--代表数据源-->
        <property name="dataSource" ref="dataSource"></property>
        <property name="databaseSchemaUpdate" value="true"/>
        </bean>
    </beans>
    

    二、processEngine 创建方式

    // 方式一
        @Test
        public void testName() throws Exception {
            ProcessEngineConfiguration config = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
            config.setJdbcDriver("com.mysql.jdbc.Driver");
            config.setJdbcUrl("jdbc:mysql://localhost:3306/activiti?createDatabaseIfNotExist=true");
            config.setJdbcUsername("root");
            config.setJdbcPassword("4230");
            config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
            ProcessEngine engine = config.buildProcessEngine();
            System.out.println(engine);
            System.out.println(engine);
        }
    // 方式二
        @Test
        public void testXml() throws Exception {
            ProcessEngineConfiguration config = ProcessEngineConfiguration
                    .createProcessEngineConfigurationFromResource("activiti.cfg.xml");
            ProcessEngine engine = config.buildProcessEngine();
            System.out.println(engine);
        }
    
    // 方式3:缺省的方式,需要保证配置文件的名称为activiti.cfg.xml
    	@Test
        public void testdefault() throws Exception {
            ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
            System.out.println(engine);
        }
    

    但我们调用这个方法,就会加载配置文件,在数据库自动生成表。

    ProcessEngine 流程引擎

    1. EngineServers:该接口定义了获取各种服务类实例对象的方法。

    2. ProcessEngine:继承EngineServers接口,并增加了对流程引擎名称的获取以及关闭。

    3. ProcessEngineImplement:对ProcessEngine接口中定义的方法实现。

    4. ProcessEngines:该类负责管理所有的引擎ProcessEngine的集合,并负责流程引擎实例对象的注册、获取、注销等操作。

    5. PricwssEngineConfiguration:该抽象类实现接口EngineServer,提供了一系列创建流程引擎配置类ProcessEngineConfigureaction实例对象的方法

    6. ProcessEngineConfigurationImpl:该抽象类继承PricwssEngineConfiguration,负责创建一系列服务类实例对象、流程引擎实例对象以及ProcessEngineImpl类实例对象。该类可以通过流程配置文件交给Spring容器管理或者使用编程方式动态构造。

    7. SpringProcessEngineConfiguration:主要用于整合Spring框架时使用,提供了几个重要的功能:

    • 创建流程引擎实例对象;
    • 流程引擎启动之后自动部署配置的流程文档(需要配置)
    • 设置流程引擎连接的数据源、事务管理器等
    1. StandaloneProcessEngineConfigueration:标准的流程引擎配置类。

    2. MultiSchemaMultiTenantProcessEngineConfiguration:“多数据库多租户”流程引擎配置类,Activiti通过此类为开发人员提供了自动路由机制,这样当流程引擎需要连接对各数据库进行操作时,客户端无需关心引擎到底连接的是哪个数据库,该类通过路由规则自动选择需要自动操作的数据库,数据库的操作对客户端来说是透明的,客户端无需关心其内部路由的实现机制。

    3. JtaProcessEnginConfiguration:故名自已,通过类名也知道该类支持JTA(Java Transaction API)

    4. StandaloneInMenProcessEngineConfiguration:该类通常可以在开发环境中自测使用,默认采用H2数据可存储数据

    EngineServer 提供了一下服务

    1. RepositoryServer:操作流程定义的方法。

    2. Runtime:操作流程实例的方法。

    3. FormServer:操作流程表单的方法。

    4. TaskServer:操作任务的方法,例如(任务的完成、挂起、激活、添加处理人、认领、删除等操作)

    5. HistoryServer:查询历史流程实例、历史变量、历史任务的方法

    6. IdentityServer:操作用户或者用户组的方法。

    7. ManagementServer:查询数据库表中的数据、表的元数据以及命令等方法。

    参考文献:https://www.jianshu.com/p/406d6a2dad9c

    三、表字段说明

    ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。

    ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。

    ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。

    ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例变量任务等等。

    ACT_GE_*: 'GE'表示general。通用数据, 用于不同场景下,如存放资源文件。

    详细解析 ===》 点我

    四、文件部署

        //流程定义部署
        public static void main(String[] args) {
            //1.创建ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到RepositoryService实例
            RepositoryService repositoryService = processEngine.getRepositoryService();
    
            //3.进行部署
            Deployment deployment = repositoryService.createDeployment()
                    .addClasspathResource("diagram/test1.bpmn")  //添加bpmn资源
                    .addClasspathResource("diagram/test1.png")
                    .name("请假申请单流程")
                    .deploy();
    
            //4.输出部署的一些信息
            System.out.println(deployment.getName());
            System.out.println(deployment.getId());
        }
    
    
    
    	//流程定义部署  流程制作出来后要上传到服务器 zip文件更便于上传
        public static void main(String[] args) {
            //1.创建ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到RepositoryService实例
            RepositoryService repositoryService = processEngine.getRepositoryService();
    
            //3.转化出ZipInputStream流对象
            InputStream is = ActivitiDeployment.class.getClassLoader().getResourceAsStream("diagram/holidayBPMN.zip");
    
            //将 inputstream流转化为ZipInputStream流
            ZipInputStream zipInputStream = new ZipInputStream(is);
    
            //3.进行部署
            Deployment deployment = repositoryService.createDeployment()
                    .addZipInputStream(zipInputStream)
                    .name("请假申请单流程")
                    .deploy();
    
            //4.输出部署的一些信息
            System.out.println(deployment.getName());
            System.out.println(deployment.getId());
        }
    

    流程定义的部署影响的表

    act_re_deployment 部署信息

    act_re_procdef 流程定义的一些信息

    act_ge_bytearray 流程定义的bpmn文件及png文件

    五、启动流程实例

        public static void main(String[] args) {
            //1.得到RunService对象
            RuntimeService runtimeService = ProcessEngines.getDefaultProcessEngine().getRuntimeService();
    
            //2.创建流程实例  流程定义的key需要知道 holiday
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("test1");
            //3.输出实例的相关信息
            System.out.println("流程部署ID:"+processInstance.getDeploymentId());
            System.out.println("流程定义ID:"+processInstance.getProcessDefinitionId());
            System.out.println("流程实例ID:"+processInstance.getId());
            System.out.println("活动ID:"+processInstance.getActivityId());
    
        }
    

    启动流程实例影响的表

    act_hi_actinst 已完成的活动信息

    act_hi_identitylink 参与者信息

    act_hi_procinst 流程实例

    act_hi_taskinst 任务实例

    act_ru_execution 执行表

    act_ru_identitylink 参与者信息

    act_ru_task 任务

    六、处理当前用户的任务

     public static void main(String[] args) {
    
            //1.得到TaskService对象
            TaskService taskService = ProcessEngines.getDefaultProcessEngine().getTaskService();
    
            //2.查询当前用户的任务
            // 当数据大于1时必须用list
            // org.activiti.engine.ActivitiException: Query return 3 results instead of max 1
            List<Task> taskList = taskService.createTaskQuery()
                    .processDefinitionKey("test1")  // 流程ID
                    .taskAssignee("zhangsan")       // 当前用户
                    .list();
    
            taskList.stream().forEach(task -> {
                //3.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
                taskService.complete(task.getId());
                //4.输出任务的id
                System.out.println(task.getId());
            });
        }
    

    处理当前用户的任务 背后操作的表

    act_hi_actinst已完成的活动信息

    act_hi_identitylink参与者信息

    act_hi_taskinst任务实例

    act_ru_identitylink参与者信息

    act_ru_task任务

    七、其他

    1. 启动时传入变量

    // 启动流程实例,同时还要指定业务标识businessKey  它本身就是请假单的id
    // 第一个参数:是指流程定义key
    // 第二个参数:业务标识businessKey
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("test1", "1001");
    
    
    // 设置assignee的取值   用户可以在界面上设置流程的执行人
        Map<String,Object> map = new HashMap<>();
        map.put("assignee0","zhangsan");
        map.put("assignee1","lishi");
        map.put("assignee2","wangwu");
    
    // 启动流程实例,同时还要设置流程定义的assignee的值
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday2", map);
    

    2. 任务办理时设置变量

    // 定义流程变量 
    Map<String, Object> variables = new HashMap<String, Object>(); 
    //变量名是holiday,变量值是holiday对象 
    variables.put("holiday", holiday); 
    taskService.complete(taskId, variables);
    

    3. 通过当前流程实例设置变量

    //4.通过实例id,来设置流程变量
    //第一个参数:流程实例的id
    //第二个参数:流程变量名
    //第三个变量:流程变量名,所对应的值
    runtimeService.setVariable("2501","holiday",holiday);
    
    runtimeService.setVariables();
    // 本地变量
    runtimeService.setVariableLocal();
    

    4. 通过当前任务设置变量

    //给指定任务设置任务变量。此处变量类型为String
    taskService.setVariable(taskId,"variable1", "hello");
    
    // 本地变量
    taskService.setVariableLocal();
    

    任务拾取

    Ps: 注意taskAssignee 与 taskCandidateUser 的区别

    .taskAssignee("zhangsan")        // 当前用户任务的查询
    .taskCandidateUser("zhangsan")   // 后选者任务查询
    
    taskList.stream().forEach(task -> {
        taskService.claim(task.getId(), "zhangsan");
        System.out.println("任务拾取成功");
        //3.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
        taskService.complete(task.getId());
        //4.输出任务的id
        System.out.println(task.getId());
    });
    

    任务归还与交接

    // 校验userId是否是taskId的负责人,如果是负责人才可以归还组任务 
    Task task = taskService.createTaskQuery().taskId(taskId) .taskAssignee(userId).singleResult(); if (task != null) { 
        // 如果设置为null,归还组任务,该 任务没有负责人 
        taskService.setAssignee(taskId, null); 
        // taskService.setAssignee(taskId, "lisi"); 
    }
    

    删除已经部署的流程定义

     /**
         * 注意事项:
         *     1.当我们正在执行的这一套流程没有完全审批结束的时候,此时如果要删除流程定义信息就会失败
         *     2.如果公司层面要强制删除,可以使用repositoryService.deleteDeployment("1",true);
         *     //参数true代表级联删除,此时就会先删除没有完成的流程结点,最后就可以删除流程定义信息  false的值代表不级联
         *
         * @param args
         */
        public static void main(String[] args) {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            //2.创建RepositoryService对象
            RepositoryService repositoryService = processEngine.getRepositoryService();
            //3.执行删除流程定义  参数代表流程部署的id
            repositoryService.deleteDeployment("1");
        }
    

    历史数据的查看

    public static void main(String[] args) throws IOException {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            //2.得到HistoryService
            HistoryService historyService = processEngine.getHistoryService();
            //3.得到HistoricActivitiInstanceQuery对象
            HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
            historicActivityInstanceQuery.processInstanceId("2501");//设置流程实例的id
            //4.执行查询
            List<HistoricActivityInstance> list = historicActivityInstanceQuery
                    .orderByHistoricActivityInstanceStartTime().asc().list();//排序StartTime
            //5.遍历查询结果
            for (HistoricActivityInstance instance :list){
                System.out.println(instance.getActivityId());
                System.out.println(instance.getActivityName());
                System.out.println(instance.getProcessDefinitionId());
                System.out.println(instance.getProcessInstanceId());
                System.out.println("=============================");
            }
        }
    

    从Activiti的act_ge_bytearray表中读取两个资源文件

    public static void main(String[] args) throws IOException {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
            //2.得到RepositoryService对象
            RepositoryService repositoryService = processEngine.getRepositoryService();
    
            //3.得到查询器:ProcessDefinitionQuery对象
            ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
    
            //4.设置查询条件
            processDefinitionQuery.processDefinitionKey("holiday");//参数是流程定义的key
    
            //5.执行查询操作,查询出想要的流程定义
            ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
    
            //6.通过流程定义信息,得到部署ID
            String deploymentId = processDefinition.getDeploymentId();
    
            //7.通过repositoryService的方法,实现读取图片信息及bpmn文件信息(输入流)
            //getResourceAsStream()方法的参数说明:第一个参数部署id,第二个参数代表资源名称
            //processDefinition.getDiagramResourceName() 代表获取png图片资源的名称
            //processDefinition.getResourceName()代表获取bpmn文件的名称
            InputStream pngIs = repositoryService
                    .getResourceAsStream(deploymentId,processDefinition.getDiagramResourceName());
            InputStream bpmnIs = repositoryService
                    .getResourceAsStream(deploymentId,processDefinition.getResourceName());
    
            //8.构建出OutputStream流
            OutputStream pngOs =
                    new FileOutputStream("G:\"+processDefinition.getDiagramResourceName());
    
            OutputStream bpmnOs =
                    new FileOutputStream("G:\"+processDefinition.getResourceName());
    
            //9.输入流,输出流的转换  commons-io-xx.jar中的方法
            IOUtils.copy(pngIs,pngOs);
            IOUtils.copy(bpmnIs,bpmnOs);
            //10.关闭流
            pngOs.close();
            bpmnOs.close();
            pngIs.close();
            bpmnIs.close();
    
        }
    

    查询流程定义信息

    public static void main(String[] args) {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            //2.创建RepositoryService对象
            RepositoryService repositoryService = processEngine.getRepositoryService();
            //3.得到ProcessDefinitionQuery对象,可以认为它就是一个查询器
            ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
            //4.设置条件,并查询出当前的所有流程定义   查询条件:流程定义的key=holiday
            //orderByProcessDefinitionVersion() 设置排序方式,根据流程定义的版本号进行排序
            List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("test1")
                    .orderByProcessDefinitionVersion()
                    .desc().list();
            //5.输出流程定义信息
            for(ProcessDefinition processDefinition :list){
                System.out.println("流程定义ID:"+processDefinition.getId());
                System.out.println("流程定义名称:"+processDefinition.getName());
                System.out.println("流程定义的Key:"+processDefinition.getKey());
                System.out.println("流程定义的版本号:"+processDefinition.getVersion());
                System.out.println("流程部署的ID:"+processDefinition.getDeploymentId());
    
            }
        }
    

    单个流程实例挂起与激活

    public static void main(String[] args) {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            //2.得到RuntimeService
            RuntimeService runtimeService = processEngine.getRuntimeService();
            //3.查询流程实例对象
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId("2501").singleResult();
            //4.得到当前流程定义的实例是否都为暂停状态
            boolean suspended = processInstance.isSuspended();
            String processInstanceId = processInstance.getId();
            //5.判断
            if(suspended){
                //说明是暂停,就可以激活操作
                runtimeService.activateProcessInstanceById(processInstanceId);
                System.out.println("流程:"+processInstanceId+"激活");
            }else{
                runtimeService.suspendProcessInstanceById(processInstanceId);
                System.out.println("流程定义:"+processInstanceId+"挂起");
            }
        }
    

    全部流程实例挂起与激活

    public static void main(String[] args) {
            //1.得到ProcessEngine对象
            ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
            //2.得到RepositoryService
            RepositoryService repositoryService = processEngine.getRepositoryService();
            //3.查询流程定义的对象
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey("test1").singleResult();
            //4.得到当前流程定义的实例是否都为暂停状态
            boolean suspended = processDefinition.isSuspended();
            String processDefinitionId = processDefinition.getId();
            //5.判断
            if(suspended){
                //说明是暂停,就可以激活操作
                repositoryService.activateProcessDefinitionById(processDefinitionId,true
                ,null);
                System.out.println("流程定义:"+processDefinitionId+"激活");
            }else{
                repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
                System.out.println("流程定义:"+processDefinitionId+"挂起");
            }
        }
    

    八、网关

    排他网关:任务执行之后的分支,经过排他网关分支只有一条有效。
    并行网关:任务执行后,可以多条分支,多条分支总会汇聚,汇聚完成,并行网关结束。
    包含网关:是排他网关和并行网关结合体。

  • 相关阅读:
    Deploying a web application to Jetty
    在java语言中执行jruby
    自制chuncked http streaming 流
    ubuntu11.10 rails开发集成vim相关问题
    通过drb集成java和ruby环境
    使用Java Web Start部署JRuby应用
    JRuby使用经验 Ruby language ITeye论坛
    使用Trinidad當Jruby Server.
    高雄 linux usergroup
    Jruby On Rails 的安装及部署实践
  • 原文地址:https://www.cnblogs.com/chang1024/p/13950213.html
Copyright © 2011-2022 走看看