亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

工作流學習——Activiti流程定義管理三步曲

2019-11-08 00:25:03
字體:
來源:轉載
供稿:網友

一、前言

 

    在上一篇文章我們通過一個小demo對Activiti進行了宏觀的介紹,讓大家對Activiti有了整體的認識,這篇文章我們來學習具體的流程定義管理的CRUD.

 

二、正文

 

流程定義是什么

 

    PRocessDefinition(流程定義)就是一個流程的步驟說明,比如我們接下來要說的這個流程,申請人王三發起提交申請,李四作為部門經理進行審批,審批完成后,此申請到達下一級總經理王五,進行審批。就這么整個流程說明其實就是流程定義,不過在Activiti中整個流程定義是以helloworld.bpmn與helloworld.png格式存在的。

 

 

    在上一篇文章中我們只是稍微提了下,關于helloworld.bpmn是在流程設計器中拖拖拽拽形成的,其實還可以通過在配置文件中進行配置,具體的圖形我已經放到了上一篇文章中了,現在我就將我配置好的helloworld.bpmn配置文件展示給大家:

[html] view plain copy<?xml version="1.0" encoding="UTF-8"?>  <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">    <process id="HelloWorld" name="HelloWorldProcess" isExecutable="true">      <startEvent id="startevent1" name="Start"></startEvent>      <endEvent id="endevent1" name="End"></endEvent>      <userTask id="usertask1" name="提交申請" activiti:assignee="張三"></userTask>      <userTask id="usertask2" name="審批【部門經理】" activiti:assignee="李四"></userTask>      <userTask id="usertask3" name="審批【總經理】" activiti:assignee="王五"></userTask>      <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>      <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>      <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>      <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>    </process>    <bpmndi:BPMNDiagram id="BPMNDiagram_HelloWorld">      <bpmndi:BPMNPlane bpmnElement="HelloWorld" id="BPMNPlane_HelloWorld">        <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">          <omgdc:Bounds height="35.0" width="35.0" x="320.0" y="50.0"></omgdc:Bounds>        </bpmndi:BPMNShape>        <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">          <omgdc:Bounds height="35.0" width="35.0" x="320.0" y="430.0"></omgdc:Bounds>        </bpmndi:BPMNShape>        <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">          <omgdc:Bounds height="55.0" width="105.0" x="285.0" y="120.0"></omgdc:Bounds>        </bpmndi:BPMNShape>        <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">          <omgdc:Bounds height="55.0" width="105.0" x="285.0" y="240.0"></omgdc:Bounds>        </bpmndi:BPMNShape>        <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">          <omgdc:Bounds height="55.0" width="105.0" x="285.0" y="350.0"></omgdc:Bounds>        </bpmndi:BPMNShape>        <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">          <omgdi:waypoint x="337.0" y="85.0"></omgdi:waypoint>          <omgdi:waypoint x="337.0" y="120.0"></omgdi:waypoint>        </bpmndi:BPMNEdge>        <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">          <omgdi:waypoint x="337.0" y="175.0"></omgdi:waypoint>          <omgdi:waypoint x="337.0" y="240.0"></omgdi:waypoint>        </bpmndi:BPMNEdge>        <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">          <omgdi:waypoint x="337.0" y="295.0"></omgdi:waypoint>          <omgdi:waypoint x="337.0" y="350.0"></omgdi:waypoint>        </bpmndi:BPMNEdge>        <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">          <omgdi:waypoint x="337.0" y="405.0"></omgdi:waypoint>          <omgdi:waypoint x="337.0" y="430.0"></omgdi:waypoint>        </bpmndi:BPMNEdge>      </bpmndi:BPMNPlane>    </bpmndi:BPMNDiagram>  </definitions>      通過流程設計器或者通過配置文件直接書寫都是可以的。

 

流程定義的CRUD

 

 

部署流程定義

 

    在進行流程定義的操作之前,先要將流程定義進行部署,部署流程定義的方式有兩種:

 

    1.部署流程定義的helloworld.bpmn與helloworld.png兩個文件

[java] view plain copy/**  * 部署流程定義 類路徑從classpath  */  @Test  public void deoploymentProcessDefinition_classpath() {      Deployment deployment = processEngine.getRepositoryService() // 與流程定義和部署對象相關的service              .createDeployment()// 創建一個部署對象              .name("流程定義")// 添加部署的名稱              .addClasspathResource("diagrams/helloworld.bpmn")// 從classpath的資源中加載,一次只能加載一個文件              .addClasspathResource("diagrams/helloworld.png")// 從classpath的資源中加載,一次只能加載一個文件              .deploy();// 完成部署      System.out.println("部署ID:" + deployment.getId());      System.out.println("部署名稱:" + deployment.getName());  }  運行結果:

    部署ID:301

    部署名稱:流程定義

 

 

    2.將helloworld.bpmn與helloworld.png壓縮成zip進行部署

[java] view plain copy/**  * 部署流程定義 zip  */  @Test  public void deploymentProcessDefinition_zip() {      InputStream in = this.getClass().getClassLoader()              .getResourceAsStream("diagrams/helloworld.zip");      ZipInputStream zipInputStream = new ZipInputStream(in);      Deployment deployment = processEngine.getRepositoryService()// 與流程定義和部署對象相關的service              .createDeployment()// 創建一個部署對象              .name("流程定義")// 添加部署              .addZipInputStream(zipInputStream)// 指定zip格式的文件完成部署              .deploy();// 完成部署      System.out.println("部署ID:" + deployment.getId());      System.out.println("部署名稱:" + deployment.getName());    }  運行結果:

    部署ID:401

    部署名稱:流程定義

 

我們將上面部署的過程進行下解釋:

    1)先獲取流程引擎對象:在創建時會自動加載classpath下的activiti.cfg.xml

    2)通過獲取的流程引擎對象,通過流程引擎對象獲取一個RepositoryService對象(倉庫對象)

    3)由倉庫的服務對象產生一個部署對象配置對象,用來封裝部署操作的相關配置

    4)這是一個鏈式編程,在部署配置對象中設置顯示名字,上傳流程定義規則文件

    5)向數據庫表中存放流程定義的規則信息

這些表都是跟部署對象和流程定義相關的表:

    act_re_deployment存放流程定義的顯示名和部署時間,每部署一次增加一條記錄;

    act_re_procdef(存放流程定義的屬性信息,部署每個新的流程定義都會在這張表中增加一條記錄,需要注意一下的當流程定義的key相同的情況下,使用的是版本升級;

    act_ge_bytearray存儲流程定義相關的部署信息。即流程定義文檔的存放地。每部署一次就會增加兩條記錄,一條是關于bpmn規則文件的,一條是圖片的(如果部署時只指定了bpmn一個文件,activiti會在部署時解析bpmn文件內容自動生成流程圖)。兩個文件不是很大,都是以二進制形式存儲在數據庫中。

 

流程定義的查詢

 

    關于流程定義在上面我們已經部署完畢了,在這里我們進行流程定義的查詢,查詢分成兩個,一個是查詢所有的流程定義還有一個查詢最新版本的流程定義

 

查看所有的流程定義

[java] view plain copy/**  * 查詢所有的流程定義  */  @Test  public void findProcessDefinition() {      List<ProcessDefinition> list = processEngine.getRepositoryService()// 與流程定義和部署對象先相關的service              .createProcessDefinitionQuery()// 創建一個流程定義的查詢              /** 指定查詢條件,where條件 */              // .deploymentId(deploymentId) //使用部署對象ID查詢              // .processDefinitionId(processDefinitionId)//使用流程定義ID查詢              // .processDefinitionNameLike(processDefinitionNameLike)//使用流程定義的名稱模糊查詢                /* 排序 */              .orderByProcessDefinitionVersion().asc()              // .orderByProcessDefinitionVersion().desc()                /* 返回的結果集 */              .list();// 返回一個集合列表,封裝流程定義      // .singleResult();//返回惟一結果集      // .count();//返回結果集數量      // .listPage(firstResult, maxResults);//分頁查詢        if (list != null && list.size() > 0) {          for (ProcessDefinition pd : list) {              System.out.println("流程定義ID:" + pd.getId());// 流程定義的key+版本+隨機生成數              System.out.println("流程定義的名稱:" + pd.getName());// 對應helloworld.bpmn文件中的name屬性值              System.out.println("流程定義的key:" + pd.getKey());// 對應helloworld.bpmn文件中的id屬性值              System.out.println("流程定義的版本:" + pd.getVersion());// 當流程定義的key值相同的相同下,版本升級,默認1              System.out.println("資源名稱bpmn文件:" + pd.getResourceName());              System.out.println("資源名稱png文件:" + pd.getDiagramResourceName());              System.out.println("部署對象ID:" + pd.getDeploymentId());              System.out.println("#########################################################");          }      }  }  運行結果:

    流程定義ID:HelloWorld:1:304

    流程定義的名稱:HelloWorldProcess

    流程定義的key:HelloWorld

    流程定義的版本:1

    資源名稱bpmn文件:diagrams/helloworld.bpmn

    資源名稱png文件:diagrams/helloworld.png

    部署對象ID:301

    #########################################################

    流程定義ID:HelloWorld:2:404

    流程定義的名稱:HelloWorldProcess

    流程定義的key:HelloWorld

    流程定義的版本:2

    資源名稱bpmn文件:helloworld.bpmn

    資源名稱png文件:helloworld.png

    部署對象ID:401

    #########################################################

 

    從上面我們可以看出,流程定義key值相同的情況下,版本是從1開始逐次升級的,流程定義的id是【key:版本:生成ID】;

 

我們對上面代碼進行下說明:

 

    1)流程定義和部署對象相關的Service都是RepositoryService。

    2)創建流程定義查詢對象,可以在ProcessDefinitionQuery上設置查詢的相關參數

    3)調用ProcessDefinitionQuery對象的list方法,執行查詢,獲得符合條件的流程定義列表

    4)由運行結果可以看出:Key和Name的值為:bpmn配置文件process節點的id和name的屬性值

    5)key屬性被用來區別不同的流程定義。

    6)帶有特定key的流程定義第一次部署時,version為1。之后每次部署都會在當前最高版本號上加1

    7)Id的值的生成規則為:{processDefinitionKey}:{processDefinitionVersion}:{generated-id},這里的generated-id是一個自動生成的唯一的數字

    8)重復部署一次,deploymentId的值以一定的形式變化規則act_ge_property表生成

 

 

    查看最新版本的流程定義:

[java] view plain copy查看最新版本的流程定義:  /**  * 附加功能,查詢最新版本的流程定義  */  @Test  public void findLastVersionProcessDefinition() {      List<ProcessDefinition> list = processEngine.getRepositoryService()              .createProcessDefinitionQuery()              .orderByProcessDefinitionVersion().asc() // 使用流程定義的版本升序排列              .list();        /**      * Map<String,ProcessDefinition> map集合的key:流程定義的key map集合的value:流程定義的對象      * map集合的特點:當map集合key值相同的情況下,后一次的值將替換前一次的值      */      Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();      if (list != null && list.size() > 0) {          for (ProcessDefinition pd : list) {              map.put(pd.getKey(), pd);          }      }        List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(              map.values());      if (pdList != null && pdList.size() > 0) {          for (ProcessDefinition pd : pdList) {              System.out.println("流程定義ID:" + pd.getId());// 流程定義的key+版本+隨機生成數              System.out.println("流程定義的名稱:" + pd.getName());// 對應helloworld.bpmn文件中的name屬性值              System.out.println("流程定義的key:" + pd.getKey());// 對應helloworld.bpmn文件中的id屬性值              System.out.println("流程定義的版本:" + pd.getVersion());// 當流程定義的key值相同的相同下,版本升級,默認1              System.out.println("資源名稱bpmn文件:" + pd.getResourceName());              System.out.println("資源名稱png文件:" + pd.getDiagramResourceName());              System.out.println("部署對象ID:" + pd.getDeploymentId());              System.out                      .println("#########################################################");          }      }    }  運行結果:

    

    流程定義ID:HelloWorld:2:404

    流程定義的名稱:HelloWorldProcess

    流程定義的key:HelloWorld

    流程定義的版本:2

    資源名稱bpmn文件:helloworld.bpmn

    資源名稱png文件:helloworld.png

    部署對象ID:401

    #########################################################

 

    運行結果可看到我們可以查出最新版本的流程定義,查詢與上面的全部查詢是一樣的,只不過多了一個過濾版本的功能,是用map來做代碼很好理解。

 

 

獲取流程定義的文件資源

 

    我們將流程定義部署完畢后,還可以查看流程定義的圖片。

[java] view plain copy/**  * 查看流程圖  */  @Test  public void viewPic() throws IOException {      // 將生產的圖片放到文件夾下      String deploymentId = "401";// TODO      // 獲取圖片資源名稱      List<String> list = processEngine.getRepositoryService()              .getDeploymentResourceNames(deploymentId);        // 定義圖片資源名稱      String resourceName = "";      if (list != null && list.size() > 0) {          for (String name : list) {              if (name.indexOf(".png") >= 0) {                  resourceName = name;              }          }      }        // 獲取圖片的輸入流      InputStream in = processEngine.getRepositoryService()              .getResourceAsStream(deploymentId, resourceName);        File file = new File("D:/" + resourceName);      // 將輸入流的圖片寫到D盤下      FileUtils.copyInputStreamToFile(in, file);  }  說明:

    1)deploymentId為流程部署ID

    2)resourceName為act_ge_bytearray表中NAME_列的值

    3)使用repositoryService的getDeploymentResourceNames方法可以獲取指定部署下得所有文件的名稱

    4)使用repositoryService的getResourceAsStream方法傳入部署ID和資源圖片名稱可以獲取部署下指定名稱文件的輸入流

    5)最后的有關IO流的操作,使用FileUtils工具的copyInputStreamToFile方法完成流程流程到文件的拷貝,將資源文件以流的形式輸出到指定文件夾下

 

 

流程定義的刪除

 

    流程定義的刪除,因為流程定義可以啟動,所以涉及到一個普通刪除和級聯刪除的情況,如果該流程定義下沒有正在運行的流程,則可以用普通刪除。如果是有關聯的信息,用級聯刪除。關于刪除我們既可以通過部署對象的id刪除也可以通過流程定義的key刪除,不同是使用id刪除的只是一條記錄,而使用key刪除的是將key相同的所有版本的流程定義全部刪除。

[java] view plain copy/**  * 刪除流程定義(刪除key相同的所有不同版本的流程定義)  */  @Test  public void delteProcessDefinitionByKey() {      // 流程定義的Key      String processDefinitionKey = "HelloWorld";      // 先使用流程定義的key查詢流程定義,查詢出所有的版本      List<ProcessDefinition> list = processEngine.getRepositoryService()              .createProcessDefinitionQuery()              .processDefinitionKey(processDefinitionKey)// 使用流程定義的key查詢              .list();      // 遍歷,獲取每個流程定義的部署ID      if (list != null && list.size() > 0) {          for (ProcessDefinition pd : list) {              // 獲取部署ID              String deploymentId = pd.getDeploymentId();              //      /*              //       * 不帶級聯的刪除, 只能刪除沒有啟動的流程,如果流程啟動,就會拋出異常              //       */              //       processEngine.getRepositoryService().deleteDeployment(deploymentId);                            /**              * 級聯刪除 不管流程是否啟動,都可以刪除              */              processEngine.getRepositoryService().deleteDeployment(                      deploymentId, true);            }        }  }  說明:

    1)因為刪除的是流程定義,而流程定義的部署是屬于倉庫服務的,所以應該先得到RepositoryService

    2)根據流程定義的key先查詢出key值相同的所有版本的流程定義,然后獲取每個流程定義的部署對象id

    3)利用部署對象id,進行級聯刪除

 

 

    到這里我們就將流程定義的部署、查詢、刪除介紹完了,關于流程定義的修改其實就是在key值相同的情況下再次部署,讓流程定義的版本進行升級,不影響以前的就版本的流程,對于新的流程就會默認使用最新版本的流程定義。

 

三、總結

 

    我們這篇文章主要講解了流程定義的概念,然后詳細的講解了不同方式的流程定義部署,還講解了流程定義的查詢、流程定義的文檔資源的獲取、流程定義的刪除等這些內容。

http://blog.csdn.net/zwk626542417/article/details/46602419


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人激情视频小说免费下载| 91欧美日韩一区| 播播国产欧美激情| 欧美大人香蕉在线| 亚洲自拍小视频| 亚洲国产天堂久久综合网| 久热在线中文字幕色999舞| 在线日韩精品视频| 欧美激情在线一区| 欧美综合在线第二页| 国产美女精品免费电影| 日韩欧美有码在线| 久久久精品国产| 亚洲色图美腿丝袜| 波霸ol色综合久久| 日韩精品高清视频| 亚洲一区二区三区乱码aⅴ| 最近更新的2019中文字幕| 日韩精品在线观看一区二区| 国产不卡视频在线| 一区二区欧美日韩视频| 日本精品在线视频| 久久久999精品免费| 亚洲免费伊人电影在线观看av| 欧美日韩在线视频观看| 97久久超碰福利国产精品…| 日韩专区在线播放| 欧美乱大交xxxxx另类电影| 国产精品久久久久999| 久久99热精品| 国产精品91视频| 亚洲日韩中文字幕在线播放| 欧美激情免费在线| 久久久亚洲精品视频| 日本成人在线视频网址| 久久婷婷国产麻豆91天堂| 色爱av美腿丝袜综合粉嫩av| 操91在线视频| 91九色国产社区在线观看| 日韩毛片中文字幕| 亚洲精品丝袜日韩| 欧美成人免费小视频| 久久免费视频网| 国产精品青青在线观看爽香蕉| 亚洲级视频在线观看免费1级| 91精品久久久久| 国产有码一区二区| 欧美一区二区三区免费观看| 国产精品1234| 亚洲а∨天堂久久精品9966| 色老头一区二区三区| 亚洲国产精品人人爽夜夜爽| 欧美激情在线狂野欧美精品| 午夜精品一区二区三区在线视| 亚洲成年网站在线观看| 91在线观看免费高清完整版在线观看| 久久国产精品免费视频| 国产精品一区二区性色av| 国内揄拍国内精品| 韩国欧美亚洲国产| 97在线精品国自产拍中文| 欧美成人黄色小视频| 久99九色视频在线观看| 亚洲无亚洲人成网站77777| 久久久久久亚洲| 亚洲精品xxx| 国产成人精品一区| 亚洲国产另类久久精品| 一区二区三区视频免费| 欧美日韩国产成人在线| 成人中文字幕+乱码+中文字幕| 欧美黄色三级网站| 亚洲天堂av综合网| 精品少妇一区二区30p| 成人免费视频a| 日韩性生活视频| 亚洲国产欧美自拍| 97久久精品国产| 欧美日韩视频免费播放| 久久精品这里热有精品| 欧美日韩在线免费观看| 久久夜色精品国产欧美乱| 精品视频—区二区三区免费| 视频在线观看一区二区| 777777777亚洲妇女| 亚洲第一视频网站| 精品女厕一区二区三区| 欧美成年人视频| 国产97在线|亚洲| 亚洲欧美日韩精品| 日韩理论片久久| 91精品91久久久久久| 一区二区三区视频在线| 91成人天堂久久成人| 黄色精品在线看| 亲子乱一区二区三区电影| 日本国产精品视频| 国产在线高清精品| 北条麻妃久久精品| 国产成人综合久久| 久久成人在线视频| 精品视频在线播放| 91精品国产亚洲| 91色中文字幕| 人人做人人澡人人爽欧美| 91久久国产综合久久91精品网站| 久久久久久久久久久亚洲| 一个人www欧美| 亚洲天堂成人在线视频| 国产精品成av人在线视午夜片| 国产亚洲一区精品| 97视频在线观看网址| 亚洲视频网站在线观看| 成人免费观看49www在线观看| 国产欧美亚洲视频| 中文字幕欧美日韩在线| 国产精品美女免费视频| 欧美韩日一区二区| 日韩精品999| 中文一区二区视频| 亚洲国产精品嫩草影院久久| 日本成人精品在线| 少妇高潮久久久久久潘金莲| 日韩电影免费在线观看中文字幕| 日韩av在线免费看| 欧美视频一区二区三区…| 成人在线中文字幕| 国产丝袜精品第一页| 日本欧美中文字幕| 成人网址在线观看| 26uuu另类亚洲欧美日本老年| 国产www精品| 亚洲欧美激情另类校园| 亚洲天堂网在线观看| 国产一区二区在线免费| 国产精品视频地址| 亚洲视频在线观看免费| 日韩av高清不卡| 亚洲成人免费在线视频| xxxx性欧美| 久久久久久久久久久成人| 国产精品久久久一区| 久久亚洲精品小早川怜子66| 国产视频精品免费播放| 久久人人爽人人爽人人片亚洲| 亚洲第一中文字幕在线观看| 国产丝袜一区二区三区免费视频| 欧美日韩亚洲一区二区三区| 亚洲国产精品电影在线观看| 成人国产在线视频| 亚洲高清色综合| 欧美精品亚州精品| 精品久久久久久久久国产字幕| zzijzzij亚洲日本成熟少妇| 九九久久综合网站| 久久久国产成人精品| 91亚洲精品久久久久久久久久久久| 在线播放日韩专区| 欧美精品videossex性护士| 久久综合免费视频影院| 欧美一区二区三区免费观看| 国产成人精品日本亚洲| 中文字幕亚洲欧美日韩2019| 久久在线视频在线|