【流程】Flowable流程定義總結


 

背景

      近幾年,互聯網企業從消費互聯網向產業互聯網轉型。在消費互聯網時期,企業面對的時C端消費者,而產業互聯網面對的是B端用戶。產業互聯網涉及方方面面,企業信息化的建設就是B端用戶的業務之一,在企業就存在上下級關系,存在審批業務,需要流程管理。在企業信息化建設中流程管理也是重要的一部分。

      流程引擎是低代碼開發(流程引擎,數據源,連接器,權限管理,表單等)重要的一部分, 如下基於flowable簡單的分析流程定義。

 

流程的一點基本概念

流程

  • process表示描述一個審批或自動執行的過程定義說明。

流程實例

  • 一個流程定義,提交一些form參數變量列表啟動形成一個流程實例,即創建者對一個流程的實例化過程。

任務

  • 一個流程定義中有諸如人工審批節點,自動節點等組成,流程實例運行到某一個節點后,會產生一個任務去執行,如人工任務,自動化任務等。

form表單

  • form表單是流程啟動,人工審批等環節提交給流程實例的變量列表,這些變量列表會貫穿流程實例的生命周期,而變量的提交一般通過form表單的形式提交。

開始節點,結束節點和人工任務節點

 

網關

自動服務任務

 

 順序流

 

 

網關分支

  • 並行分叉 AND-split(Parallel Split)
    • 兩個分支都需要執行
    • 如 下單后 發快遞和開發票,兩個動作都會做。
  • 排他分叉或叫異或 XOR-split(Exclusive Choice)
    • 后續分支二選一,只能走一條
    • 如 下單后的支付,選擇銀聯支付,微信支付還是支付寶支付,只能選擇一種支付方式。

 

網關合並

  • 同步AND-join(Synchronization)
    • 前面的所有的分支等待都需要完成
    • 如上面的下單,收快遞和收發票,都收到了,流程才完成。
  • 簡單合並XOR-join(Simple Merge)
    • 前面的分支只要有一個完成,流程就完成
    • 如上面的下單后支付,不管是銀聯,微信支付還是支付寶支付,只要有一個渠道支付成功,支付流程就完成。

 

Flowable相關說明

官網地址:https://flowable.com/

幫助文檔:https://flowable.com/open-source/docs/bpmn/ch02-GettingStarted/

中文幫助文檔:https://tkjohn.github.io/flowable-userguide/#_introduction

github代碼:https://github.com/flowable/flowable-engine

flowable的發展

  • Flowable是來自從Activiti5.22
  • Activiti6.0的bug太多
  • Activiti7.0主要擁抱雲
  • Flowable6版本開始按照模塊進行拆分,社區比較活躍

如下是JBoss,Alfresco和Flowable三個團隊的流程軟件關鍵時間點描述:

Flowable安裝和配置

Flow安裝

第一步、從flowable的github地址上下載如下幾個war,部署到apache的webapps下

flowable-admin.war
flowable-idm.war
flowable-modeler.war
flowable-rest.war
flowable-task.war

第二步、修改如上幾個包的配置文件,配置mysql數據地址或者使用自身的h2數據庫進行實驗。

修改admin idm modeler rest和task這5個包的配置文件WEB-INF/classes/flowable-default.properties,本實驗使用的是mysql數據庫。

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/flowable?characterEncoding=UTF-8
spring.datasource.username=flowable
spring.datasource.password=flowable

配置后,啟動tomcat服務器並登錄。

Flowable modeler登錄

訪問flowable的流程設計器

地址:http://localhost:8080/flowable-modeler

賬號密碼:admin/test

登錄后,可以訪問flowable的管理頁面 

地址:http://localhost:8080/flowable-admin/#/engine

可以看到flowable流程由如下幾個引擎組成

 

可以通過編輯REST端點檢查對應的服務運行是否正常。

本例中以流程引擎為例簡單的說明。

 

 

流程定義

定義一個簡單的請假流程,包括一個開始節點,一個審批節點,經過排他網關后,審批通過后發送一個http通知,審批拒絕后也發送一個http通知。

 

如上流程定義使用bpmn2.0的xml表示大致如下所示

<?xml version="1.0" encoding="UTF-8"?>
<definitions>
  <process id="flow_h1" name="holiday-new" isExecutable="true">
    <documentation>請求流程描述</documentation>
    <startEvent id="startEvent1" name="請假開始" flowable:formKey="formKey1" flowable:formFieldValidation="true">
      <extensionElements>
        <flowable:formProperty id="employee" name="請假人" type="string" required="true"></flowable:formProperty>
        <flowable:formProperty id="noOfHolidays" name="天數" type="long" required="true"></flowable:formProperty>
      </extensionElements>
    </startEvent>
    <userTask id="approveKey1" name="審批節點1" flowable:formFieldValidation="true"></userTask>
    <exclusiveGateway id="sid-D7F080C0-BC9D-4C03-B9EB-2D81E4010CA6" name="審批是否通過"></exclusiveGateway>
    <serviceTask id="AcceptKey1" name="通過" flowable:class="org.example.tut.flowable.handler.HolidayRejectionHandler"></serviceTask>
    <serviceTask id="RejectKey1" name="拒絕" flowable:class="org.example.tut.flowable.handler.HolidayApprovalHandler"></serviceTask>
    <endEvent id="sid-E86D23D8-DC24-44D0-B96D-BA3E8CF801C0"></endEvent>
    <serviceTask id="RejectHttpKey1" name="HTTP測試節點" flowable:type="http">
      <extensionElements>
        <flowable:field name="requestMethod">
          <flowable:string><![CDATA[POST]]></flowable:string>
        </flowable:field>
        <flowable:field name="requestUrl">
          <flowable:string><![CDATA[http://127.0.0.1:9901/test]]></flowable:string>
        </flowable:field>
        <flowable:field name="requestBody">
          <flowable:expression><![CDATA[Reject action, employee ${employee} apply ${noOfHolidays} days with reason ${description}]]></flowable:expression>
        </flowable:field>
      </extensionElements>
    </serviceTask>
    <sequenceFlow id="sid-84648711-833A-4ABE-AD08-3E32B026F247" sourceRef="RejectKey1" targetRef="RejectHttpKey1"></sequenceFlow>
    <sequenceFlow id="sid-448B4748-A744-43D9-B3EB-FC0846035F20" sourceRef="RejectHttpKey1" targetRef="sid-E86D23D8-DC24-44D0-B96D-BA3E8CF801C0"></sequenceFlow>
    <endEvent id="sid-683697FC-2E68-45C9-BE63-0F526FC2F3AB"></endEvent>
    <serviceTask id="AcceptHttpKey1" name="審批通過的HTTP消息" flowable:type="http">
      <extensionElements>
        <flowable:field name="requestMethod">
          <flowable:string><![CDATA[POST]]></flowable:string>
        </flowable:field>
        <flowable:field name="requestUrl">
          <flowable:string><![CDATA[http://127.0.0.1:9901/test]]></flowable:string>
        </flowable:field>
        <flowable:field name="requestBody">
          <flowable:expression><![CDATA[Accept Holiday employee ${employee} apply ${noOfHolidays} days with reason ${description}]]></flowable:expression>
        </flowable:field>
      </extensionElements>
    </serviceTask>
    <sequenceFlow id="sid-9788654A-171C-45B9-9A41-94A35C531AA8" sourceRef="AcceptHttpKey1" targetRef="sid-683697FC-2E68-45C9-BE63-0F526FC2F3AB"></sequenceFlow>
    <sequenceFlow id="sid-C4456145-0531-492F-AA80-E733CD0C35C9" sourceRef="AcceptKey1" targetRef="AcceptHttpKey1"></sequenceFlow>
    <sequenceFlow id="SeqFromStartToApprove" sourceRef="startEvent1" targetRef="approveKey1"></sequenceFlow>
    <sequenceFlow id="SeqFromApproveToGW" sourceRef="approveKey1" targetRef="sid-D7F080C0-BC9D-4C03-B9EB-2D81E4010CA6"></sequenceFlow>
    <sequenceFlow id="SeqRejectKey1" sourceRef="sid-D7F080C0-BC9D-4C03-B9EB-2D81E4010CA6" targetRef="RejectKey1">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${!approved}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="ReqAcceptKey1" sourceRef="sid-D7F080C0-BC9D-4C03-B9EB-2D81E4010CA6" targetRef="AcceptKey1">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${approved}]]></conditionExpression>
    </sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_flow_h1">
   ... 省
  </bpmndi:BPMNDiagram>
</definitions>

 

節點說明

這個簡單的流程中使用了flowable的幾個節點

流程定義的組成

process

  • startEvent 表示開始節點
    • 開始節點可以是空節點
    • 開始節點也可以是定時節點
  • userTask 表示人工審批節點
    • 可以通過 flowable:assignee="userId" 表示這個節點的審批人是誰
    • 可以通過 flowable:candidateGroups="managerGroup" 表示候選的審批組是什么,在這個組中的人都可以做為審批人。
    • 人工審批節點可以增加extensionElements增加自定義擴展屬性,將流程定義的擴展信息保存到CDATA中
  • exclusiveGateway 表示排他網關
    • 人工審批后的審批結果做為排他網關的判斷依據
  • serviceTask 表示自動節點
    • 有自定義的節點需要自定義一個Handler做為serviceTask節點的處理。
    • serviceTask也有一些系統內置實現(如HTTP服務 MAIL服務 MULE服務等)
    • 自動服務節點可以增加extensionElements增加自定義擴展屬性,將流程定義的擴展信息保存到CDATA中
  • sequenceFlow 表示分支流
    • 在分支流上會存在一個條件,排他網關后會跟多個sequenceFlow,排他網關會根據各自sequenceFlow上的條件決定流程的流向。
    • 條件會使用conditionExpression來表示,這個表達式一般使用JUEL表達式實現。
  • endEvent 表示結束節點

bpmndi:BPMNDiagram

  • bpmndi:BPMNShape
    • omgdc:Bounds 表示圖像的輪廓包含寬高
      • width 寬
      • height 高
  • bpmndi:BPMNEdge
    • pmgdi:waypoint
      • x 橫軸坐標
      • y 縱軸坐標

 

startEvent的定時節點如何定義?

<startEvent id="timer_start1" name="定時器節點" isInterrupting="false">
    <timerEventDefinition>
        <timeDate>2021-06-30T15:01:02</timeDate>
        <timeCycle>R/P1DT0S</timeCycle>
        <timeDuration>P10DT0S</timeDuration>
    </timerEventDefinition>
</startEvent>

時間定義參考ISO8601標准,可以參考@https://www.cnblogs.com/xdao/p/iso8601.html

 

格式解析
R2/2015-06-04T19:25:16.828696-07:00/P1DT10S

上面的字符串通過"/"分為了三部分即:

重復次數/開始時間/運行間隔

重復次數
R - 將永遠重復
R1 - 將重復一次
R231 - 將重復231次。
開始時間
任務第一次運行的時間。如果開始日期時間已經過去,Kala將返回一個錯誤。

其中"T"用來分割日期和時間,時間后面跟着的"-07:00"表示西七區,注意"-"是連字符,不是減號。

時區默認是0時區,可以用"Z"表示,也可以不寫。

對於我國,要使用"+08:00",表示東八區。
上面的字符串表示 2015年6月4日,19點25分16秒828696納秒,西七區。

運行間隔
運行間隔以"P"開始,和上面一樣也是用"T"分割日期和時間,如P1Y2M10DT2H30M15S

P 開始標記
1Y - 一年
2M - 兩個月
10D - 十天
T - 時間和日期分的割標記
2H - 兩個小時
30M - 三十分鍾
15S 十五秒鍾
例子,注意如果沒有年月日,"T"也不能省略

P1DT1M - 一天一分鍾執行一次
P1W - 一周執行一次
PT1H - 一小時執行一次
PT10S - 十秒執行一次

 

啟動流程

啟動流程的代碼:

  public ProcessInstanceResponse startProcessInstance(HolidayRequest holidayRequest) {

        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("employee", holidayRequest.getEmpName());
        variables.put("noOfHolidays", holidayRequest.getNoOfHolidays());
        variables.put("description", holidayRequest.getRequestDescription());
        variables.put("initiator", "admin");

        ProcessInstance processInstance =
                runtimeService.startProcessInstanceByKey(holidayRequest.getProcessKey(), variables);

        return new ProcessInstanceResponse(processInstance.getId(), processInstance.isEnded());
    }

 

啟動流程后,會在數據庫中增加記錄

ACT_RU_ACTINST 增加流程實例信息。

ACT_RU_VARIABLE 增加variables變量列表的變量,這個變量會貫穿流程實例的全程。

 

分配任務

分配任務的代碼:

TaskService taskService;

// taskId是任務Id,userId是用戶id,表示將任務分配給這個用戶
taskService.setAssignee(taskId, userId);

分配任務后,會在數據庫中設置審批人信息

ACT_RU_TASK 表的字段 ASSIGEE_表示審批人是誰

 

獲取待辦任務

獲取待辦任務的代碼

// 跟進userId用戶id查詢分配給這個用戶或將這個用戶設為候選的任務列表
List<Task> taskList = taskService.createTaskQuery().taskCandidateOrAssigned(userId).list();

會查詢ACT_RU_TASK表,獲取審批人的任務。

完成任務

完成任務也叫做審批任務

taskService.complete(taskId, variables);

 

 

流程運行

流程運行時,實例和變量說明什么

可以在管理頁面看到啟動流程實例是填寫的變量列表

啟動流程增加的變量

variables.put("employee", holidayRequest.getEmpName());
variables.put("noOfHolidays", holidayRequest.getNoOfHolidays());
variables.put("description", holidayRequest.getRequestDescription());
variables.put("initiator", "admin");

 

人工節點審批時增加的變量是什么

variables.put("approved", approved);
taskService.complete(taskId, variables);

即:變量時貫穿流程實例的全聲明周期,流程的很多自定義功能可以通過變量和擴展屬性進行實現。

 

 

展示流程實例的運行圖

 

done.

祝玩得開心~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM