Activiti框架學習記錄-01

Activiti框架學習記錄-01

本篇主要是Activiti工作流框架的學習記錄,以及對於該框架的基本使用和一些淺顯的理解:

  • 1、工作流框架基本概念
  • 2、在eclipse中使用工作流框架
  • 3、創建工作框架
  • 4、使用框架提供API,操作框架實現業務邏輯

1、工作流框架基本概念(摘自百度百科)

  • 工作流(Workflow),就是“業務過程的部分或整體在計算機應用環境下的自動化”,它主要解決的是“使在多個參與者之間按照某種預定義的規則傳遞文檔、信息或任務的過程自動進行,從而實現某個預期的業務目標,或者促使此目標的實現”。
  • 工作流管理系統(Workflow Management System, WfMS)是一個軟件系統,它完成工作量的定義和管理,並按照在系統中預先定義好的工作流邏輯進行工作流實例的執行。工作流管理系統不是企業的業務系統,而是爲企業的業務系統的運行提供了一個軟件的支撐環境。
  • 常見的工作流框架:JBPM4.4、activiti5.13、OSWorkFlow;

2、在eclipse中使用工作流框架

1、可以離線安裝插件,將activit文件夾拷貝到eclipse-luna的安裝目錄下的
盤符:\Eclipse\eclipse_luna\dropins\ 文件夾下,重啓eclipse,進入eclipse後再Window下preference中出現Acitviti選項爲安裝插件成功,如下圖1所示:
插件安裝成功後的效果圖
並且勾選create process definition image when saving the diagram,這樣在我們保存一個流程的時候同時會保存一張png圖片;

2、可以選擇在線安裝:
Name:Activiti BPMN 2.0 designer
Location:http://activiti.org/designer/update/
等待一會兒安裝成功後操作以及界面同1所示;
當我們需要使用的時候,點擊new->others,如下圖2所示:
創建新的工作流


3、創建工作框架

  • 1、建立表結構(兩種方式);
  • 2、初步分析23張表的結構與意義;
  • 3、框架中表的設計結構;

知識點分析1:表結構的建立
1)利用sql文件創建表,在我們activiti框架的目錄:
…\activiti-5.13\database\create\
sql文件目錄
執行sql文件,進入mysql命令行:

source E:\activiti-5.13\database\create\activiti.mysql.create.engine.sql
source E:\activiti-5.13\database\create\activiti.mysql.create.history.sql
source E:\activiti-5.13\database\create\activiti.mysql.create.identity.sql

2)利用API創建表
步驟一:配置文件,使用默認的配置文件:文件必須在類路徑下,名稱必須爲activiti-context.xml
文件中bean的ID規定好的

<!-- 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">

    <!-- 配置流程引擎配置對象  activiti-day01 -->
    <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:///activiti-demo01"></property>
        <property name="jdbcUsername" value="root" ></property>
        <property name="jdbcPassword" value="root"></property>
        <!-- 注入自動建表設置 -->
        <property name="databaseSchemaUpdate" value="true"></property>
    </bean>

    <!-- 提供工廠bean,創建流程引擎對象 -->
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"></property>
    </bean>
</beans>
//Java代碼片段-01-使用配置文件
@Test
public void test() {
//使用的是默認文件的創建規則
ProcessEngine processEngine = 
ProcessEngines.getDefaultProcessEngine();
}
//Java代碼片段-02-不使用配置文件
//使用activit框架提供的自動創建表的方式創建23張表
    /**
     * 自動建表的方式
     */
    @SuppressWarnings("unused")
    @Test
    public void test1() {
        //創建一個流程引擎配置對象
        ProcessEngineConfiguration configuration = 
                ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
        //設置數據源信息
        configuration.setJdbcDriver("com.mysql.jdbc.Driver");
        configuration.setJdbcUrl("jdbc:mysql:///activiti-day01");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("1234");
        //設置自動建表的操作
        configuration.setDatabaseSchemaUpdate("true");
        //使用配置對象創建一個流程引擎對象
        ProcessEngine processEngine = configuration.buildProcessEngine();
    }

知識點分析2:初步分析23張表的結構與意義
Activiti的後臺是有數據庫的支持,所有的表都以ACT_開頭。 第二部分是表示表的用途的兩個字母標識。 用途也和服務的API對應。

  • ACT_RE_*: ‘RE’表示repository。 這個前綴的表包含了流程定義和流程靜態資源 (圖片,規則,等等)。

  • ACT_RU_*: ‘RU’表示runtime。 這些運行時的表,包含流程實例,任務,變量,異步任務,等運行中的數據。 Activiti只在流程實例執行過程中保存這些數據, 在流程結束時就會刪除這些記錄。 這樣運行時表可以一直很小速度很快。

  • ACT_ID_*: ‘ID’表示identity。 這些表包含身份信息,比如用戶,組等等。

  • ACT_HI_*: ‘HI’表示history。 這些表包含歷史數據,比如歷史流程實例, 變量,任務等等。 ACT_GE_*: 通用數據, 用於不同場景下。

知識點分析3:初步分析23張表的結構與意義
Activiti的後臺是有數據庫中表的設計結構:
activiti框架中history表結構設計圖
完整表結構圖

4、使用API操作工作流框架

初步模擬 流程 使用代碼片段如下:

1、畫圖:畫出流程圖

作出流程圖

2、部署流程

1)部署流程定義

  /**
   * 初步模擬一個請假流程
   * 1、部署流程定義
   * 意義:將設計流程圖插入到數據庫中
   */
    @Test
    public void test4() {
        //流程部署定義
        //部署構建器,用於加載流程定義文件,部署流程定義
        DeploymentBuilder deploymentBuilder = 
                processEngine.getRepositoryService().createDeployment();
        //加載流程定義文件(bpmn、png)
        deploymentBuilder.addClasspathResource("demo01.bpmn");
        deploymentBuilder.addClasspathResource("demo01.png");
        //返回部署對象
        Deployment deployment = deploymentBuilder.deploy();
        //常看當前的流程部署ID
        System.out.println(deployment.getId());
    }

2)查詢流程定義

    // 查詢流程定義
    @Test
    public void test5() {
        //流程定義查詢對象,操作的數據表act_re_prodef
        ProcessDefinitionQuery query = 
                processEngine.getRepositoryService().createProcessDefinitionQuery();
        //查詢到流程定義(流程定義表的而查詢)
        //可以添加過濾條件
        query.processDefinitionNameLike("請假流程");
        //添加排序條件
        query.orderByProcessDefinitionVersion().desc();

        List<ProcessDefinition> list = 
                query.listPage(0, 1); // 分頁查詢

        //流程定義對象的遍歷
        for (ProcessDefinition processDefinition : list) {
            String id   = processDefinition.getId();
            String name = processDefinition.getName();
            int version = processDefinition.getVersion();
            String deploymentId = processDefinition.getDeploymentId();
            String resourceName = processDefinition.getResourceName();
            System.out.println(id + "\t" + name + "\t" + version);
            System.out.println(deploymentId + "\t" + resourceName);
        }
    }

3)根據流程定義的ID查詢實例

    // act_ac_execution:存放的當前啓動的實例信息
    // act_ru_task: 存放當前產生的任務(整個流程向下推進十分重要)
    @Test
    public void test6() {
        String processDefinitionId = "qjlc:4:304"; //流程定義ID自己根據數據庫表中數據修改
        ProcessInstance processInstance = 
                processEngine.getRuntimeService().startProcessInstanceById(processDefinitionId);
        System.out.println(processInstance.getId());
    }

4)查詢個人任務行爲

    @Test
    public void test7() {
        //任務查詢對象,查詢任務表
        TaskQuery query = 
                processEngine.getTaskService().createTaskQuery();
        //添加過濾條件,根據任務的辦理人過濾
        query.taskAssignee("張三");
        List<Task> list = query.list();
        for (Task task : list) {
            System.out.println(task.getId() + "====" + task.getName());
        }
    } 

4)辦理個人任務行爲

    @Test
    public void test8() {
        String taskId = "1804"; // 任務ID,根據數據庫中task表中的數據進行修改
        //自動推向到下一個任務人
        processEngine.getTaskService().complete(taskId);
    }

5)清理數據庫activiti表中的所有數據

    @Test
    public void test() {
        DeploymentQuery query = processEngine.getRepositoryService().createDeploymentQuery();
        List<Deployment> list = query.list();
        for (Deployment deployment : list) {
            //完全清理數據,級聯清理數據
            processEngine.getRepositoryService().deleteDeployment(deployment.getId(), true);
        }
    }

流程實例的操作(代碼爲了保證完整性的功能與上述代碼功能會有部分重複)
1)首先聲明一個流程操作引擎,基本在整個框架的聲明週期中都會有所使用

//在項目中可以使用spring的注入技術進行處理,現在暫時使用普通方法
ProcessEngine pe = ProcessEngines.getDefaultProcessEngine();

2)部署流程定義
* 方式一:加載單個的流程定義文件
* 方式二:加載zip壓縮文件(將bpmn文件以及png文件進行打包爲process.zip)
代碼中使用的文件截圖

@Test
    public void test1() {
        DeploymentBuilder deploymentBuilder = 
                pe.getRepositoryService().createDeployment();
//      ZipInputStream zipInputStream_file = null;
        // 方式一:加載單個流程定義文件
//      deploymentBuilder.addClasspathResource("demo01.bpmn");
//      deploymentBuilder.addClasspathResource("demo01.png");
//      Deployment deployment = deploymentBuilder.deploy();

        // 方式二:加載zip壓縮文件PS: 只支持zip
        // Web項目中使用該方式
//      try {
//          zipInputStream_file = new ZipInputStream(new FileInputStream(new File("d:\\process.zip")));
//      } catch (FileNotFoundException e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }
        ZipInputStream zipInputStream 
            = new ZipInputStream(this.getClass().getClassLoader().getResourceAsStream("process.zip"));
        deploymentBuilder.addZipInputStream(zipInputStream);
        deploymentBuilder.name("部署名稱測試");
        Deployment deployment = deploymentBuilder.deploy();
        String id = deployment.getId();
        System.out.println(id);
    }

3)查詢部署信息,查詢的通用寫法

      pe.getXXXService().createXXXQuery().list()
@Test
    public void test2() {
//      pe.getRepositoryService().createDeploymentQuery().list();
//      pe.getRepositoryService().createProcessDefinitionQuery().list();
//      pe.getRuntimeService().createProcessInstanceQuery().list();
//      pe.getTaskService().createTaskQuery().list();
//      pe.getHistoryService().createHistoricActivityInstanceQuery().list();

        List<Deployment> list = pe.getRepositoryService().createDeploymentQuery().list();
        for (Deployment deployment : list) {
            System.out.println(deployment.getId() + "\t" + deployment.getDeploymentTime());
        }

    }

3)刪除部署信息

    // 刪除部署信息
    @Test
    public void test3() {
        //刪除deploymentId爲501的部署信息數據,同樣會影響幾張表
        String deploymentId = "501";
        //是否級聯刪除(會刪除更多的表)
        boolean cascade = true;
        pe.getRepositoryService().deleteDeployment(deploymentId,cascade);
    }

3)查詢流程定義數據

@Test
    public void test4() {
        List<ProcessDefinition> list = pe.getRepositoryService().createProcessDefinitionQuery().list();
        for (ProcessDefinition processDefinition : list) {
            System.out.println(processDefinition.getId() + "\t" + 
                    processDefinition.getKey() + "\t" + 
                    processDefinition.getResourceName() + "\t" + 
                    processDefinition.getVersion());
        }
    }

4) 刪除流程定義數據,通過刪除部署信息達到刪除流程定義的目的

@Test
    public void test5() {
        //刪除部署的時候會自動刪除流程定義
        String deploymentId = "501";
        pe.getRepositoryService().deleteDeployment(deploymentId);
    }

5)查詢相關

    /**
     * 查詢最新版本的流程定義數據
     */
    @Test
    public void test6() {
        //查詢的是所有的
        pe.getRepositoryService().createDeploymentQuery().list();
        //查詢最新的
        List<ProcessDefinition> list = pe.getRepositoryService().createProcessDefinitionQuery().latestVersion().list();
        for (ProcessDefinition processDefinition : list) {
            System.out.println(processDefinition.getVersion() + "\t" + processDefinition.getDeploymentId());
        }
    }

    @Test
    public void test7() {
        //沒有提供過濾條件就需要自己來寫
        ProcessDefinitionQuery query = pe.getRepositoryService().createProcessDefinitionQuery();
        //按照version升序排列
        query.orderByProcessDefinitionVersion().asc(); //排序的方法
        List<ProcessDefinition> list = query.list();   //list展示
        Map<String, ProcessDefinition> map = new HashMap<String, ProcessDefinition>();
        for (ProcessDefinition processDefinition : list) {
            map.put(processDefinition.getKey(), processDefinition);
        }
        System.out.println(map);

        list = new ArrayList<ProcessDefinition>(map.values());
        for (ProcessDefinition processDefinition : list) {
            System.out.println(processDefinition.getName() + "\t" + processDefinition.getId());
        }
    }

    /**
     * 查詢一次部署的對應的流程定義文件名稱和輸入流
     * @throws IOException 
     */
    @Test
    public void test8() throws IOException {
        String deploymentId = "1101"; // 部署ID
        List<String> names = pe.getRepositoryService().getDeploymentResourceNames(deploymentId);
        for (String name : names) {
            System.out.println(name);
            //文件輸入流(是用來讀取BLOB字段的文件的)
            InputStream inputStream = pe.getRepositoryService().getResourceAsStream(deploymentId, name);
            //讀取出數據

            FileUtils.copyInputStreamToFile(inputStream, new File("d:\\" + name));

//          byte[] bytes = new byte[1024];
//          while(inputStream.read(bytes) != -1) {
//              i++;
//              inputStream.read(bytes);
//              outputStream = new FileOutputStream(new File("d:\\" + name));
//              outputStream.write(bytes);
//          }
//          
            inputStream.close();
//          outputStream.close();
        }
    }

    /**
     * 獲得圖片的輸入流
     * @throws IOException 
     */
    @Test
    public void test9() throws IOException {
        //從頁面上獲取一個流程ID
        String processDefinitionId = "qjlc:9:1404"; // 流程定義ID
        InputStream inputStream = pe.getRepositoryService().getProcessDiagram(processDefinitionId);
        FileUtils.copyInputStreamToFile(inputStream, new File("d:\\my.png"));
        inputStream.close();
    }

6)啓動流程實例

    /**
     * 啓動流程實例
     * 方式一:根據流程定義的ID啓動實例
     * 方式二:根據流程定義的key啓動實例 (建議使用,會自動選擇最新版本)
     */
    @Test
    public void test10() {
        String processDefinitionId = "qjlc:7:1204"; // 流程定義ID
        //不會管是不是最新的流程版本
        //方式一:根據流程定義的ID啓動流程實例
        ProcessInstance pi = pe.getRuntimeService().startProcessInstanceById(processDefinitionId);
        System.out.println(pi.getId());

        String processDefinitionKey = "qjlc";
        //方式二:根據流程定義的key啓動流程
        //會根據最新的流程進行啓動
        ProcessInstance pi_ = pe.getRuntimeService().startProcessInstanceByKey(processDefinitionKey);
        System.out.println(pi_.getProcessDefinitionId());
    }

7)查詢流程實例

    /**
     * 查詢流程實例
     */
    @Test
    public void test11() {
        //流程實例查詢對象,查詢表act_ru_execution
        ProcessInstanceQuery query = pe.getRuntimeService().createProcessInstanceQuery();
        List<ProcessInstance> list = query.list();
        for (ProcessInstance processInstance : list) {
            System.out.println(processInstance.getId()+"\t"+processInstance.getActivityId());
        }
    }

8)刪除流程實例

/**
     * 刪除流程實例
     */
    @Test
    public void test12() {
        String processInstanceId = "1601"; // 流程實例ID
        String deleteReason = "不請假了";      // 刪除流程實例原因
        //刪除一個流程實例
        pe.getRuntimeService().deleteProcessInstance(processInstanceId, deleteReason);
    }

9)查詢個人任務

    /**
     * 查詢個人任務
     */
    @Test
    public void test13() {
        TaskQuery query = pe.getTaskService().createTaskQuery();
        String assignee = "王五";
        query.taskAssignee(assignee);
        List<Task> list = query.list();
        for (Task task : list) {
            System.out.println(task.getId() + "\t" + task.getName());
        }
    }

10)辦理個人任務

    /**
     * 辦理個人任務
     */
    public void test14() {
        String taskId = "1509"; //注意此處數據必須存在於數據庫的taskId表中
        pe.getTaskService().complete(taskId);
    }
發佈了29 篇原創文章 · 獲贊 16 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章